记录学习部署k8s过程中踩过的坑,下次部署有个参考
节点规划 1 2 3 4 5 k8s 1.20.2 + docker + flannel 0.20.2 node0 192.168.126.139 master 4GB 40GB node1 192.168.126.140 slave 4GB 40GB node2 192.168.126.141 slave 4GB 40GB
前置工作(所有节点)
修自定义主机名,即刻应用,以一个为例
整个顺手的文本编辑器,笔者这里选了nano
配置主机名解析
/etc/hosts
是一个本地的静态文件,用于将主机名映射到 IP 地址。当系统需要解析主机名时,首先查找该文件。如果找到匹配项,则使用该 IP 地址,而不通过 DNS 服务器
添加如下内容
关闭swap,selinux,禁用防火墙
k8s运行需要禁用swap(交换空间)更好的进行容器内存管理。swapoff -a
关闭swap。/etc/fstab
用于定义系统启动时自动挂载的文件系统、分区、交换空间(swap)等信息,sed -ri 's/.*swap.*/#&/' /etc/fstab
注释掉其中关于swap的信息。setenforce 0
禁用 SELinux 的强制安全策略避免k8s遇到权限问题。systemctl stop firewalld && systemctl disable firewalld
关闭并禁用防火墙
启用内核模块
**modprobe overlay
**:加载 Overlay 文件系统(用于容器运行时)内核模块,支持容器文件系统。
**modprobe br_netfilter
**: 加载网络桥接过滤模块,用于容器和主机之间的流量控制。
网络转发常用配置
net.bridge.bridge-nf-call-iptables = 1
部署容器时,容器网络通常会与宿主机的网络进行桥接。在处理跨越网络桥接的数据包时,调用 iptables
进行包过滤。避免容器间的流量被误拦截。
net.ipv4.ip_forward = 1
启用 IP 转发,使主机能够转发网络流量,保证不同节点间的 Pod 可以相互通信。
net.bridge.bridge-nf-call-ip6tables = 1
与第一个参数类似,关于ipv6的。
vm.swappiness=0
设置虚拟内存的交换行为,swappiness
控制内核决定什么时候将内存页面交换到硬盘上。swappiness=0
表示内核尽量避免交换,优先使用物理内存,避免频繁的内存交换。
1 2 3 4 5 6 cat > /etc/sysctl.d/kubernetes.conf <<EOF net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 vm.swappiness=0 EOF
生效规则
docker安装(所有节点)
开机自启
查看版本,确定安装成功
网络组件配置准备(所有节点) Flannel 是 Kubernetes 的网络插件,用于为集群中的容器提供跨节点的网络通信,常用的还有calico,flannel简单易用,calico功能更强大
内容如下,注意这里的镜像是国外的,可以换成国内的,也可以给docker配置代理
另外,如果使用其他版本的flannel,可以直接去其github仓库下载对应yml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 --- kind: Namespace apiVersion: v1 metadata: name: kube-flannel labels: pod-security.kubernetes.io/enforce: privileged --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: flannel rules: - apiGroups: - "" resources: - pods verbs: - get - apiGroups: - "" resources: - nodes verbs: - get - list - watch - apiGroups: - "" resources: - nodes/status verbs: - patch - apiGroups: - "networking.k8s.io" resources: - clustercidrs verbs: - list - watch --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: flannel roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: flannel subjects: - kind: ServiceAccount name: flannel namespace: kube-flannel --- apiVersion: v1 kind: ServiceAccount metadata: name: flannel namespace: kube-flannel --- kind: ConfigMap apiVersion: v1 metadata: name: kube-flannel-cfg namespace: kube-flannel labels: tier: node app: flannel data: cni-conf.json: | { "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ] } net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } } --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds namespace: kube-flannel labels: tier: node app: flannel spec: selector: matchLabels: app: flannel template: metadata: labels: tier: node app: flannel spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/os operator: In values: - linux hostNetwork: true priorityClassName: system-node-critical tolerations: - operator: Exists effect: NoSchedule serviceAccountName: flannel initContainers: - name: install-cni-plugin image: docker.io/rancher/mirrored-flannelcni-flannel-cni-plugin:v1.1.2 command: - cp args: - -f - /flannel - /opt/cni/bin/flannel volumeMounts: - name: cni-plugin mountPath: /opt/cni/bin - name: install-cni image: docker.io/rancher/mirrored-flannelcni-flannel:v0.20.2 command: - cp args: - -f - /etc/kube-flannel/cni-conf.json - /etc/cni/net.d/10-flannel.conflist volumeMounts: - name: cni mountPath: /etc/cni/net.d - name: flannel-cfg mountPath: /etc/kube-flannel/ containers: - name: kube-flannel image: docker.io/rancher/mirrored-flannelcni-flannel:v0.20.2 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr resources: requests: cpu: "100m" memory: "50Mi" securityContext: privileged: false capabilities: add: ["NET_ADMIN" , "NET_RAW" ] env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: EVENT_QUEUE_DEPTH value: "5000" volumeMounts: - name: run mountPath: /run/flannel - name: flannel-cfg mountPath: /etc/kube-flannel/ - name: xtables-lock mountPath: /run/xtables.lock volumes: - name: run hostPath: path: /run/flannel - name: cni-plugin hostPath: path: /opt/cni/bin - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg - name: xtables-lock hostPath: path: /run/xtables.lock type: FileOrCreate
安装cni并配置到flannel的默认路径
CNI(Container Network Interface)是容器网络接口的缩写,为容器提供网络配置和管理功能,包括为容器分配 IP 地址、设置网络策略、路由流量等
copy cni配置到flannel默认读取的目录
依赖组件conntrack
conntrack
是一种用户空间工具,用于操作和管理 netfilter
跟踪连接的状态,此处用于处理容器间的网络连接
kubelet开启自启
K8s主节点
安装组件
初始化控制平面
1 2 3 4 kubeadm init --apiserver-advertise-address=192.168.126.139 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.20.2 \ --service-cidr=10.1.0.0/16 --pod-network-cidr=10.244.0.0/16
这里笔者配置了附录的docker代理,如果没有,可以考虑在这里直接指定国内源,比如下面这种方式
1 kubeadm init --kubernetes-version=1.20.2 --apiserver-advertise-address=192.168.126.139 --cri-socket=/var/run/isulad.sock --image-repository=registry.aliyuncs.com/google_containers --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16 --v=5
输出以下信息初始化成功
保存join命令在从节点运行
1 2 kubeadm join 192.168.126.139:6443 --token dokaoz.sfrch50yf43iubsz \ --discovery-token-ca-cert-hash sha256:44507460bd82478c7447280af83889673149a76a3a24f75b7e828e9b56a69dc4
配置kubectl
/etc/profile
是一个系统级的 shell 配置文件,通常用于设置所有用户的环境变量和启动时执行的系统命令
最后面添加
1 export KUBECONFIG=/etc/kubernetes/admin.conf
应用改变
查看节点状态
此时提示NotReady,是因为网络插件未配置(这里笔者已经在从节点执行了1. 2步骤加入了集群)
配置flannel,之前导入的配置直接应用即可(实际上部署完发现从节点不需要使用kubectl apply -f /opt/yaml/kube-flannel.yaml配置flannel,也可以正常使用网络,原因还没搞明白,坑++)
1 kubectl apply -f /opt/yaml/kube-flannel.yaml
可以使用如下命令查看flannel部署进度和集群状态
1 2 kubectl get nodes kubectl get pods -n kube-flannel
安装完成后状态如下所示
K8s从节点
安装组件
1 [root@node0 ~]# dnf install -y kubernetes-kubeadm kubernetes-kubelet kubernetes-node
加入集群
1 2 kubeadm join 192.168.126.139:6443 --token dokaoz.sfrch50yf43iubsz \ --discovery-token-ca-cert-hash sha256:44507460bd82478c7447280af83889673149a76a3a24f75b7e828e9b56a69dc4
显示如下信息加入成功
集群测试 此处选择nginx进行测试创建并暴露端口
【来自GPT】
kubectl create deployment nginx --image=nginx
**kubectl create deployment
**:创建一个新的部署(Deployment)。Deployment 是 Kubernetes 中管理应用生命周期的资源对象,它定义了应用的期望状态(例如 Pod 数量、副本、容器镜像等)。
**nginx
**:指定部署的名称。这个名字会被用作创建的 Deployment 资源的标识。
**--image=nginx
**:指定容器使用的镜像。这里指定的是 nginx
镜像,意味着创建的 Pod 中将运行 Nginx Web 服务器。这个镜像是从 Docker Hub 中拉取的官方 Nginx 镜像。
kubectl expose deployment nginx --port=80 --type=NodePort
**kubectl expose
**:该命令用于暴露一个服务,使其可以通过网络访问。通常,Kubernetes 使用 Service
资源来暴露应用,使其在集群内或集群外可访问。
**deployment nginx
**:暴露的对象是之前创建的 nginx
Deployment。意味着这个命令会创建一个 Service,将 nginx
部署暴露出去。
**--port=80
**:指定暴露服务的端口号,80
是 Nginx 的默认 HTTP 服务端口。这个端口将用于访问 Nginx Web 服务器。
**--type=NodePort
**:指定服务暴露的类型为 NodePort
。NodePort
类型的服务会在每个节点上打开一个端口,使集群外部的用户可以通过节点的 IP 地址和指定的端口号来访问服务。Kubernetes 会自动为该服务分配一个端口,默认范围是 30000 到 32767。
1 2 kubectl create deployment nginx --image=nginx kubectl expose deployment nginx --port=80 --type =NodePort
查询当前集群中 Pod 和 Service 状态,查看是否运行成功
查看pod运行的节点可以用
1 kubectl get pods -o wide
在从节点查看,可以发现这里自动部署在在192.168.126.141节点上
所有节点均可访问nginx服务器
1 2 3 192.168.126.140:32641 192.168.126.141:32641 192.168.126.142:32641
比如主节点
扩展副本
1 kubectl scale deployment nginx --replicas=3
附录-常见问题 静态ip配置
笔者文件如下
对于要设置的静态ip所属子网,可以在宿主机使用ipconfig命令查询,笔者使用NAT链接虚拟机和宿主机,这里是VMnet 8网络,网关一般默认为xxx.xxx.xxx.2
,DNS照搬即可。
更改如下选项即可,黄色由dhcp
改为static
,红色为新加的。
之后重启网卡即可生效设置
重启后已经可以访问网络
实际上有时候管用,有时候不管用,原因笔者还没弄明白,坑++,这里选择粗暴的重启节点
dnf太慢,挂个终端代理 1 2 [root@node0 ~]# export http_proxy="http://192.168.1.104:7890" [root@node0 ~]# export https_proxy="http://192.168.1.104:7890"
docker配置代理以访问国外镜像源 1 2 3 4 5 6 [root@node0 ~]# sudo mkdir /etc/systemd/system/docker.service.d [root@node0 ~]# cd /etc/systemd/system/docker.service.d [root@node0 docker.service.d]# nano proxy.conf [root@node0 docker.service.d]# sudo systemctl daemon-reload [root@node0 docker.service.d]# sudo systemctl restart docker [root@node0 docker.service.d]# docker info
proxy.conf内容为
1 2 3 [Service ] Environment="HTTP_PROXY=http://192.168.1.104:7890" Environment="HTTPS_PROXY=http://192.168.1.104:7890"
初始化时警告,主节点socat缺失
1 [WARNING FileExisting-socat]: socat not found in system path
补一个即可
cgroups不一致 初始化时警告docker cgroups与推荐不一致,在
“/etc/docker/daemon.json”添加
1 "exec-opts": ["native.cgroupdriver=systemd" ]
之后重启docker和守护进程即可,查看docker info可以看到当前的cgroups
1 2 3 4 [root@lab2 docker]# nano /etc/docker/daemon.json [root@lab2 docker]# sudo systemctl daemon-reload [root@lab2 docker]# sudo systemctl restart docker [root@lab2 docker]# docker info
完整文件示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 “ { "exec-opts": ["native.cgroupdriver=systemd" ], "log-driver": "json-file" , "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" , "registry-mirrors": [ "https://registry.docker-cn.com" , "https://docker.mirrors.ustc.edu.cn" , "https://hub-mirror.c.163.com" , "https://mirror.baidubce.com" , "https://ccr.ccs.tencentyun.com" ] } ”
如果想查看k8s的cgroups
1 nano /var/lib/kubelet/config.yaml
删除配置以重新初始化 下面的命令可以在所有节点删除现有配置
此命令不会删除docker,k8s组件等镜像,只会删除初始化的影响
主节点需要额外执行
1 sudo rm -rf /etc/kubernetes
从节点加入提示节点已出现 问题:
1 2 3 [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml' error execution phase kubelet-start: a Node with name "lab2" and status "Ready" already exists in the cluster. You must delete the existing Node or change the name of this new joining Node To see the stack trace of this error execute with --v=5 or higher
方法(主节点)
1 kubectl delete node lab2
然后从节点重新加入
flannel部署出错删除配置 1 2 3 4 5 6 7 [root@lab2 ~]# kubectl delete -f /opt/yaml/kube-flannel.yaml namespace "kube-flannel" deleted clusterrole.rbac.authorization.k8s.io "flannel" deleted clusterrolebinding.rbac.authorization.k8s.io "flannel" deleted serviceaccount "flannel" deleted configmap "kube-flannel-cfg" deleted daemonset.apps "kube-flannel-ds" deleted
删除测试时创建的nginx服务 删除 Deployment 和 Pod
1 kubectl delete deployment nginx
删除对应的 Service
1 kubectl delete svc nginx
确认资源已被删除
过程中的k8s命令&&从节点配置kubectl kubelet
:在 每个节点 上运行,负责管理节点上的容器和 Pod。
kubeadm
:在 主节点 上用于初始化集群,在 从节点 上用于加入集群。
kubectl
:在 任意节点 上运行,用于操作和管理集群。
上述过程中kubectl
只部署在了主节点上,从节点调用相关指令有如下错误
1 2 [root@lab2 ~]# kubectl apply -f /opt/yaml/kube-flannel.yaml The connection to the server localhost:8080 was refused - did you specify the right host or port?
如果想在从节点执行这些指令时,用不了,可以复制主节点的配置即可
1 2 3 kubectl apply -f /opt/yaml/kube-flannel.yaml kubectl get nodes kubectl get pods -n kube-flannel
具体操作
查看从节点配置:
1 2 [root@lab2 ~]# ls ~/.kube/config ls : 无法访问 '/root/.kube/config' : No such file or directory
没有找到 ~/.kube/config 文件,说明 kubectl 配置文件还没有正确设置。
解决步骤: 在主节点上获取 kubeconfig 文件:
1 sudo cat /etc/kubernetes/admin.conf
复制配置文件到工作节点
将输出的配置文件内容复制到工作节点上的 ~/.kube/config 文件
没有则新建
1 2 [root@lab2 ~]# mkdir -p ~/.kube [root@lab2 ~]# nano ~/.kube/config
然后就好了
1 2 3 4 5 [root@lab2 ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION lab0 Ready control-plane,master 32h v1.20.2 lab2 Ready <none> 18m v1.20.2 lab3 Ready <none> 27m v1.20.2
参考文章 K8s+iSulad环境部署 | openEuler文档 | openEuler社区 | v22.03_LTS_SP3
openEuler 部署Kubernetes(K8s)集群_《openeuler kubernetes 集群部署指南》-CSDN博客
K8s+iSulad环境部署 | openEuler文档 | openEuler社区 | v22.03_LTS_SP3
docker国内镜像源配置及走代理设置_docker镜像代理-CSDN博客
It seems like the kubelet isn‘t running or healthy_it seems like the kubelet isn’t running or healthy-CSDN博客