【说明】
本文档详细描述了在openEuler 22.03 LTS上通过ansible以二进制模式自动化部署高可用Kubernetes集群(适用k8s v1.26版本)。
本文档参考了小陈运维的ansible剧本,并进行了适当改造,使之适用于openEuler 22.03 LTS,并改用nginx实现高可用;仅采用containerd作为容器运行时;采用calico网络插件;采用yaml配置文件自动部署dashboard。改造后的ansible剧本在华为私有云中的ECS测试通过,ECS系统统一采用openEuler 22.03 LTS SP1(根据小陈运维的说法,也可以支持CentOS 7、CentOS 8和Ubuntu,因此改造后的剧本理论上也可以支持)。
改造后的联网部署的ansible剧本已发布到gitee,联网部署仓库。
适用于内部离线部署的ansible剧本可参考仓库:内网部署仓库
手动部署可参见:手动部署k8s集群
本文档采用6台华为ECS进行部署,其中一台为ansible主控节点,另外5台为k8s节点,基本情况如下表所示。
主机名称 | IP地址 | 说明 | 软件 |
ansible-controller | 192.168.1.100 | ansible主控节点 | ansible 2.9.27、git、sshpass |
k8s-master-1 | 192.168.1.31 | master节点 | kube-apiserver、kube-controller-manager、kube-scheduler、etcd、 kubelet、kube-proxy、nfs-client、nginx |
k8s-master-2 | 192.168.1.32 | master节点 | kube-apiserver、kube-controller-manager、kube-scheduler、etcd、 kubelet、kube-proxy、nfs-client、nginx |
k8s-master-3 | 192.168.1.33 | master节点 | kube-apiserver、kube-controller-manager、kube-scheduler、etcd、 kubelet、kube-proxy、nfs-client、nginx |
k8s-node-1 | 192.168.1.34 | node节点 | kubelet、kube-proxy、nfs-client、nginx |
k8s-node-2 | 192.168.1.35 | node节点 | kubelet、kube-proxy、nfs-client、nginx |
k8s节点涉及的主要软件及其版本如下表所示。
软件 | 版本 |
kernel | 5.10.0 |
openEuler | 22.03 LTS |
etcd | v3.5.6 |
containerd | 1.6.15 |
cfssl | v1.6.3 |
cni | 1.1.1 |
crictl | 1.24.1 |
k8s主机:192.168.1.0/24
service:10.96.0.0/12
pod:172.16.0.0/12
注:在开始以下操作前,请确保k8s各节点及ansible主控节点能访问Internet。
本节操作在专用的ansible主控节点上操作完成。
openEuler默认已配置好yum软件仓库,在确认ansible主控节点可连网的情况下,直接安装ansible软件包即可。
注:若是内网部署,请先为主控节点配置好yum软件仓库,再安装软件包。
[root@ansible-controller ~]# dnf -y install ansible
其中的IP地址可根据自身情况修改。
[root@ansible-controller ~]# vim /etc/ansible/hosts
[kube_pki]
192.168.1.31
[etcd]
192.168.1.31 hostname=etcd-1
192.168.1.32 hostname=etcd-1
192.168.1.33 hostname=etcd-1
[kube_master]
192.168.1.31 hostname=k8s-master-1
192.168.1.32 hostname=k8s-master-2
192.168.1.33 hostname=k8s-master-3
[kube_node]
192.168.1.34 hostname=k8s-node-1
192.168.1.35 hostname=k8s-node-2
[chrony]
192.168.1.31
ansible剧本文件已上传至gitee,点击该链接可查看。
可用git工具将其克隆至本地,操作如下:
# 安装git
[root@ansible-controller ~]# dnf -y install git
# 克隆下载文件
[root@ansible-controller ~]# git clone https://gitee.com/ptu706/k8s
# 查看
[root@ansible-controller ~]# ll
# 切换至目标目录
[root@ansible-controller ~]# cd k8s
# 安装sshpass软件包
[root@ansible-controller k8s]# dnf -y install sshpass
# 生成密钥
[root@ansible-controller k8s]# ssh-keygen -f /root/.ssh/id_rsa -P ''
脚本中的IP地址可根据自身情况修改。
# 创建或编辑文件
[root@ansible-controller k8s]# vim ssh.sh
export IP="192.168.1.31 192.168.1.32 192.168.1.33 192.168.1.34 192.168.1.35"
export SSHPASS=Mima12346789#
for HOST in $IP
do
sshpass -e ssh-copy-id -o StrictHostKeyChecking=no $HOST
done
[root@ansible-controller k8s]# bash ssh.sh
在files目录下的download.sh文件中,列出了需要下载的文件及其版本,若有需要修改,可在该文件中修改,然后执行该shell文件下载软件包。
[root@ansible-controller k8s]# cd files/
[root@ansible-controller files]# bash download.sh
# 下载完成后返回至父目录
[root@ansible-controller files]# cd ..
注:建议多执行一两次下载的Shell脚本,确保文件全部成功下载。
在pki/files/pki.sh文件中包括了主节点的IP地址,可根据自身情况修改。
[root@ansible-controller k8s]# vim pki/files/pki.sh
#!/bin/bash
export k8s_master01="192.168.1.31"
export k8s_master02="192.168.1.32"
export k8s_master03="192.168.1.33"
……此处省略后续内容……
在nginx/files/kube-nginx.conf配置文件中包括了k8s主节点的IP地址,可根据自身情况修改。
[root@ansible-controller k8s]# vim nginx/files/kube-nginx.conf
……此处省略部分内容……
server 192.168.1.31:6443 max_fails=3 fail_timeout=30s;
server 192.168.1.32:6443 max_fails=3 fail_timeout=30s;
server 192.168.1.33:6443 max_fails=3 fail_timeout=30s;
……此处省略后续内容……
main.yaml文件中包含了k8s各节点的IP地址,以及SSH登录这些节点的账号root及其密码(均统一指定为相同的密码)。
[root@ansible-controller k8s]# vim main.yaml
……此处省略部分输出……
# all 写所有IP地址
# passed 是所有的系统密码,此密码需要所有主机相同
- hosts:
- etcd
- kube_master
- kube_node
remote_user: root
vars:
- all: 192.168.1.31 192.168.1.32 192.168.1.33 192.168.1.34 192.168.1.35
- passwd: Mima12346789#
……此处省略后继内容……
修改local_init/files/hosts.sh文件中k8s主机对应的IP地址。
[root@ansible-controller k8s]# vim local_init/files/hosts.sh
cat >> /etc/hosts << EOF
192.168.1.31 k8s-master-1
192.168.1.32 k8s-master-2
192.168.1.33 k8s-master-3
192.168.1.34 k8s-node-1
192.168.1.35 k8s-node-2
EOF
注:强烈建议在执行以下操作前,为k8s各节点做好系统快照,以便在需要时可随时回滚,特别是因为网络或其它原因导致安装失败时需要恢复系统后再次重新部署。
在ansible主控节点上执行剧本文件,开始自动化部署。
[root@ansible-controller k8s]# ansible-playbook main.yaml
稍候十余分钟后,最后显示的消息应如下所示。
PLAY RECAP **************************************************************************************************************************************************
192.168.1.31 : ok=90 changed=80 unreachable=0 failed=0 skipped=27 rescued=0 ignored=0
192.168.1.32 : ok=61 changed=54 unreachable=0 failed=0 skipped=25 rescued=0 ignored=0
192.168.1.33 : ok=61 changed=54 unreachable=0 failed=0 skipped=25 rescued=0 ignored=0
192.168.1.34 : ok=45 changed=41 unreachable=0 failed=0 skipped=23 rescued=0 ignored=0
192.168.1.35 : ok=45 changed=41 unreachable=0 failed=0 skipped=23 rescued=0 ignored=0
完成自动化部署后,等候大约10-15分钟,甚至更久一些(内网部署非常快,1-2分钟即可),Pod才可能成功拉取并启动,这时才能看到k8s集群资源和服务的正常状况。
以下操作在任一个k8s主节点上操作完成,请注意Shell命令提示符。
要求能显示集群所有节点,且其状态均为Ready。
[root@k8s-master-1 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master-1 Ready 11m v1.26.0
k8s-master-2 Ready 11m v1.26.0
k8s-master-3 Ready 11m v1.26.0
k8s-node-1 Ready 11m v1.26.0
k8s-node-2 Ready 11m v1.26.0
除ingress-nginx-admission-开头的1~2个Pod外,要求所有其它Pod的状态为Running,READY为1/1。
[root@k8s-master-1 ~]# kubectl get pod -A -owide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx ingress-nginx-admission-patch-vk8t6 0/1 Completed 0 12m 10.88.0.7 k8s-node-1
ingress-nginx ingress-nginx-controller-64668d8c7b-44w98 1/1 Running 0 12m 172.17.201.1 k8s-node-1
kube-system calico-kube-controllers-75679fbd89-4bjnd 1/1 Running 0 12m 10.88.0.5 k8s-node-1
kube-system calico-node-6x7nz 1/1 Running 0 12m 192.168.1.31 k8s-master-1
kube-system calico-node-dc8t4 1/1 Running 0 12m 192.168.1.35 k8s-node-2
kube-system calico-node-hrx5s 1/1 Running 0 12m 192.168.1.32 k8s-master-2
kube-system calico-node-twpqp 1/1 Running 0 12m 192.168.1.34 k8s-node-1
kube-system calico-node-whvxx 1/1 Running 0 12m 192.168.1.33 k8s-master-3
kube-system calico-typha-75ffcf7dcc-jdd94 1/1 Running 0 12m 192.168.1.34 k8s-node-1
kube-system coredns-58c7668f8d-9wq9j 1/1 Running 0 12m 10.88.0.2 k8s-node-1
kube-system default-http-backend-6f89b4654f-z7wgw 1/1 Running 0 12m 10.88.0.3 k8s-node-1
kube-system kubernetes-dashboard-549694665c-4xw6k 1/1 Running 0 12m 10.88.0.6 k8s-node-1
kube-system metrics-server-7888bbf49b-cjqhs 1/1 Running 0 12m 192.168.1.32 k8s-master-2
[root@k8s-master-1 ~]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 443/TCP 16m
ingress-nginx ingress-nginx-controller NodePort 10.101.232.208 80:30359/TCP,443:31826/TCP 15m
ingress-nginx ingress-nginx-controller-admission ClusterIP 10.97.22.157 443/TCP 15m
kube-system calico-typha ClusterIP 10.108.92.67 5473/TCP 15m
kube-system default-http-backend ClusterIP 10.110.142.210 80/TCP 15m
kube-system kube-dns ClusterIP 10.96.0.10 53/UDP,53/TCP,9153/TCP 15m
kube-system kubernetes-dashboard NodePort 10.97.12.241 443:31080/TCP 15m
kube-system metrics-server ClusterIP 10.100.91.208 443/TCP 15m
[root@k8s-master-1 ~]# kubectl get namespaces
NAME STATUS AGE
default Active 17m
ingress-nginx Active 15m
kube-node-lease Active 17m
kube-public Active 17m
kube-system Active 17m
利用busybox.yaml文件创建一个pod。
[root@k8s-master-1 ~]# kubectl apply -f busybox.yaml
pod/busybox created
1-2分钟后,查看pod运行的运行状况如下所示。
[root@k8s-master-1 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 2m15s
若提示错误,可执行【kubectl describe pod busybox】命令或者【kubectl logs -f pod busybox】查看失败原因。有时候可执行【kubectl delete -f busybox.yaml】删除busybox,然后重新创建,或者将busybox.yaml文件中的busybox的版本修改为1.28,或者1.28.4,然后重新部署即可。
默认情况下,在default命名空间会有一个kubernetes服务,如下所示。
[root@k8s-master-1 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 25m
该服务与前面的busybox在同一命名空间,利用busybox测试能否解析kubernetes服务。
[root@k8s-master-1 ~]# kubectl exec busybox -n default -- nslookup kubernetes
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: kubernetes
Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local
若出现以下的nslookup: can't resolve 'kubernetes的错误提示。
[root@k8s-master-1 ~]# kubectl exec busybox -n default -- nslookup kubernetes
nslookup: can't resolve 'kubernetes'
Server: 10.96.0.10
Address 1: 10.96.0.10
command terminated with exit code 1
可执行【kubectl delete pod coredns容器名 -n kube-system】删除coredns开头的Pod,系统会自动再新建一个该类Pod,执行【kubectl get pod -A】命令查看Pod状态,待到该Pod状态为running后再测试即可(具体原因不详)。
执行【kubectl get svc -A】可查看所有名称空间下的服务,如下所示。
[root@k8s-master-1 ~]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 443/TCP 38m
ingress-nginx ingress-nginx-controller NodePort 10.97.14.31 80:31574/TCP,443:32510/TCP 36m
ingress-nginx ingress-nginx-controller-admission ClusterIP 10.105.123.151 443/TCP 36m
kube-system calico-typha ClusterIP 10.97.17.197 5473/TCP 37m
kube-system default-http-backend ClusterIP 10.103.117.233 80/TCP 36m
kube-system kube-dns ClusterIP 10.96.0.10 53/UDP,53/TCP,9153/TCP 37m
kube-system kubernetes-dashboard NodePort 10.107.195.56 443:31080/TCP 36m
kube-system metrics-server ClusterIP 10.100.157.45 443/TCP 36m
可见kube-system名称空间下有一个名为kube-dns的服务,可利用busybox解析该服务,如下所示。
[root@k8s-master-1 ~]# kubectl exec busybox -n default -- nslookup kube-dns.kube-system
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: kube-dns.kube-system
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
从前面可以看到kubernetes服务的集群IP地址为10.96.0.1,服务端口为443/TCP,可在任意一个k8s节点上测试访问该服务端口,如下所示。
[root@k8s-master-1 ~]# telnet 10.96.0.1 443
Trying 10.96.0.1...
Connected to 10.96.0.1.
Escape character is '^]'.
从前面查看服务可看到kube-dns服务的集群IP地址为10.96.0.10,服务端口为53,可在任意一个k8s节点上测试访问该服务问口,如下所示。
[root@k8s-node-2 ~]# telnet 10.96.0.10 53
Trying 10.96.0.10...
Connected to 10.96.0.10.
Escape character is '^]'.
Connection closed by foreign host.
[root@k8s-node-2 ~]# curl 10.96.0.10:53
curl: (52) Empty reply from server
正常情况下,Pod与k8s节点之间要相通,执行【kubectl get pod -owide】可查看当前命名空间下的Pod详情,包括其所在k8s节点和IP地址,如下所示。
[root@k8s-master-1 ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 24m 172.17.251.193 k8s-master-1
执行【kubectl get pod -owide -n kube-system】可查看kube-system命名空间下的Pod详情,包括其所在k8s节点和IP地址,如下所示。
[root@k8s-master-1 ~]# kubectl get pod -owide -n kube-system
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-kube-controllers-75679fbd89-85t5w 1/1 Running 0 52m 10.88.0.5 k8s-node-1
calico-node-845n8 1/1 Running 0 52m 192.168.1.31 k8s-master-1
calico-node-g44rx 1/1 Running 0 52m 192.168.1.33 k8s-master-3
calico-node-nx54k 1/1 Running 0 52m 192.168.1.34 k8s-node-1
calico-node-srns9 1/1 Running 0 52m 192.168.1.32 k8s-master-2
calico-node-v559h 1/1 Running 0 52m 192.168.1.35 k8s-node-2
calico-typha-75ffcf7dcc-d5sc5 1/1 Running 0 52m 192.168.1.34 k8s-node-1
coredns-58c7668f8d-sm2sc 1/1 Running 0 20m 172.19.196.193 k8s-master-3
default-http-backend-6f89b4654f-7gppl 1/1 Running 0 52m 10.88.0.4 k8s-node-1
kubernetes-dashboard-549694665c-n4zgh 1/1 Running 0 52m 10.88.0.6 k8s-node-1
metrics-server-7888bbf49b-gqz6j 1/1 Running 0 52m 192.168.1.31 k8s-master-1
执行【kubectl exec -ti busybox -- /bin/sh】命令可进入busybox容器内部,然后测试ping其它Pod的IP地址,比如busybox在k8s-master-1,而kubernetes-dashboard容器在k8s-node-1,可测试busybox与节点k8s-node-1之间的连通性,如下所示。
[root@k8s-master-1 ~]# kubectl exec -it busybox -- /bin/sh
/ # ping -c3 192.168.1.34
PING 192.168.1.34 (192.168.1.34): 56 data bytes
64 bytes from 192.168.1.34: seq=0 ttl=63 time=0.449 ms
64 bytes from 192.168.1.34: seq=1 ttl=63 time=0.223 ms
64 bytes from 192.168.1.34: seq=2 ttl=63 time=0.207 ms
--- 192.168.1.34 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.207/0.293/0.449 ms
注意:Pod与Pod之间有可能是不通的,比如busybox容器与kubernetes-dashboard容器的IP地址就不通,如下所示。
/ # ping 10.88.0.6
PING 10.88.0.6 (10.88.0.6): 56 data bytes
^C
--- 10.88.0.6 ping statistics ---
85 packets transmitted, 0 packets received, 100% packet loss
[root@k8s-master-1 ~]# kubectl apply -f ingress-demo-app.yaml
deployment.apps/hello-server created
1、查看Pod
稍候片刻后,执行【kubectl get pod -owide】命令可查看到4个Pod,并分布部署在不同的节点上,如下所示:
[root@k8s-master-1 ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-server-6d9d5d86c9-kdc9h 1/1 Running 0 11m 172.17.251.194 k8s-master-1
hello-server-6d9d5d86c9-p8bht 1/1 Running 0 11m 172.19.196.194 k8s-master-3
nginx-demo-655bc4c9db-kd6ql 1/1 Running 0 11m 172.17.201.1 k8s-node-1
nginx-demo-655bc4c9db-ztg2s 1/1 Running 0 11m 172.23.152.129 k8s-master-2
2、查看应用
执行【kubectl get ingress】命令ingress-demo-app的状况,如下所示。
[root@k8s-master-1 ~]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-host-bar nginx hello.ptuxgk.cn,demo.ptuxgk.cn 192.168.2.33 80 12m
3、查看服务端口
执行【kubectl get svc -A | grep ingress】可过滤查看ingress端口,如下所示。
[root@k8s-master-1 ~]# kubectl get svc -A | grep ingress
ingress-nginx ingress-nginx-controller NodePort 10.99.182.49 80:30709/TCP,443:31642/TCP 42m
ingress-nginx ingress-nginx-controller-admission ClusterIP 10.111.187.62 443/TCP 42m
在自动化部署时默认在kube-system命名空间创建一个管理账号admin-user,并将其与集群管理角色进行了绑定,现只需要获得该账号的token就可以访问。
[root@k8s-master-1 ~]# kubectl -n kube-system create token admin-user
eyJhbGciOiJSUzI1NiIsImtpZCI6IkYzREpjUUlDdkVCYS1Tc1Z1emFKMUdQQmJUa2ZIM25sQndrWUxjQTYwNGcifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlCm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjgwNjk1MTEyLCJpYXQiOjE2ODA2OTE1MTIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJhZG1pbi11c2VyIiwidWlkIjoiNjYyYjNjYmYtZWRmOC00YjE0LTk1OTQtYWQ5MGNkODIxZDVhIn19LCJuYmYiOjE2ODA2OTE1MTIsInN1YiI6Inn5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphZG1pbi11c2VyIn0.S63invWZYZ1hnxnQ0SeyBT7EKEcx2NhEc7bLlkRufLVmcKN64OGKI3PxO_23nVnc9vlhhddpQPXYfJT0EudT4RNaJt9LSiML-w0kwQEWAS3yuQCv4_1a2hfPo9B0YIR3kkOaOu7Az1woqCquNt_VnGFGZexpSn8L-cZo7nyzPqr8WsNq5y3jU1Qtt8MkT78E-gzjsUIeCax6SX8wjeUSq4Rsyi_URnx_YLj0M6UrTWkTCEmjr2GA1DIOV8Kvwec9a1f2Matq3KUZEcMjHwH6JbGwBeCxQ1i5Wc0YI0GSZsMNkOG6Hh_q_Ot7Sl25_Tmx6P0PojfSyRvXqHCGMsU5QQ
复制上面的token,访问URL地址:https://dashboard容器所在节点IP地址:31080,如下所示。
粘贴前面生成的token,登录成功后的效果如下图所示。
在k8s上部署应用可参见: 分布式部署gpmall Web应用系统