前言
上一篇文章我们介绍了如何使用Ansible Playbook离线部署一个单Master多worker节点的kubernetes集群,相信看过的朋友都基本已经掌握了如何使用Ansible playbook在脱网环境下快速部署一个kubernetes集群。但是此架构很显然存在单点(master)故障,不能满足生产环境的要求。
本篇文章的目标:使用Ansible Playbook在之前的基础上进行扩展,离线部署一个目前最新版的k8s集群(3个Master若干Worker架构)
准备工作
在开始之前,确保你已经完成以下准备工作:
1. 一台运行Linux的服务器作为部署节点(我们将称之为“控制节点”,也就是Ansible主机)。
2. 确保你已经安装了Ansible、并做好了ssh互信,并且掌握了基本的Ansible操作知识。
3. 从官方Kubernetes GitHub仓库下载离线安装包,或者通过其他方式准备好所需的Kubernetes二进制文件。
创建Ansible Playbook
默认我认为大家已经掌握了Ansible Playbook,这里对其不做赘述,下面为整个Playbook剧本项目的整体结构:
[root@jumpserver-app-1 kubernetes]# tree ansible-deploy-k8s-v2
ansible-deploy-k8s-v2
├── add-worker.yml
├── group_vars
│ └── all.yml
├── HA-k8s-deploy.yml
├── hosts
├── kubectl
├── roles
│ ├── components
│ │ ├── files
│ │ │ ├── calico.yaml
│ │ │ └── coredns.yaml
│ │ └── tasks
│ │ └── main.yml
│ ├── containerd
│ │ ├── files
│ │ │ ├── config.toml
│ │ │ └── libseccomp-2.5.1-1.el8.x86_64.rpm
│ │ └── tasks
│ │ └── main.yml
│ ├── etcd
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ ├── etcd.conf.j2
│ │ ├── etcd.service.j2
│ │ └── etcd.sh.j2
│ ├── ha
│ │ ├── files
│ │ │ └── check_nginx.sh
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ ├── keepalived.conf.j2
│ │ └── nginx.conf.j2
│ ├── master
│ │ ├── files
│ │ │ ├── apiserver-to-kubelet-rbac.yaml
│ │ │ ├── kubelet-bootstrap-rbac.yaml
│ │ │ └── token.csv
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ ├── config.j2
│ │ ├── kube-apiserver.conf.j2
│ │ ├── kube-apiserver.service.j2
│ │ ├── kube-controller-manager.conf.j2
│ │ ├── kube-controller-manager.kubeconfig.j2
│ │ ├── kube-controller-manager.service.j2
│ │ ├── kube-scheduler.conf.j2
│ │ ├── kube-scheduler.kubeconfig.j2
│ │ └── kube-scheduler.service.j2
│ ├── sysinit
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── hosts.j2
│ ├── tls
│ │ ├── files
│ │ │ ├── generate_etcd_cert.sh
│ │ │ └── generate_k8s_cert.sh
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ ├── etcd
│ │ │ ├── ca-config.json.j2
│ │ │ ├── ca-csr.json.j2
│ │ │ └── server-csr.json.j2
│ │ └── k8s
│ │ ├── admin-csr.json.j2
│ │ ├── ca-config.json.j2
│ │ ├── ca-csr.json.j2
│ │ ├── kube-controller-manager-csr.json.j2
│ │ ├── kube-proxy-csr.json.j2
│ │ ├── kube-scheduler-csr.json.j2
│ │ └── server-csr.json.j2
│ └── worker
│ ├── tasks
│ │ └── main.yml
│ └── templates
│ ├── bootstrap.kubeconfig.j2
│ ├── kubelet-config.yml.j2
│ ├── kubelet.conf.j2
│ ├── kubelet.service.j2
│ ├── kube-proxy-config.yml.j2
│ ├── kube-proxy.conf.j2
│ ├── kube-proxy.kubeconfig.j2
│ └── kube-proxy.service.j2
└── single-master-deploy.yml
31 directories, 57 files
其实就是在原有的基础上,新增加了一个ha的roles角色,其中定义了安装keepalived和nginx的任务,然后新增了一个名为:HA-k8s-deploy.yml的剧本文件,同时对一些文件的内容进行了微调。
整个剧本由components、sysinit、containerd、etcd、ha、master、worker、tls 八个role组成,每个role分别完成的任务(task)为:
1. sysinit:系统初始化任务
2. components:部署calico、coredns、ingress-nginx等插件
3. containerd:部署containerd
4. etcd: 部署etcd集群
5. master:部署master节点所需的组件
6. ha: 部署高可用组件及负载均衡软件
7. worker:部署worker节点所需的组件
8. tls:生成集群所需的证书文件
此次分享的Ansible Playbook在原有基础上扩展为了高可用架构。
部分代码展示
由于篇幅原因,这里只展示部分剧本代码,如需完整项目代码请关注微信公众号【IT运维图谱】添加后台管理员咨询获取。👇👇👇
全局变量设置:
此文件中定义了全局变量,其中software_dir为部署时使用到的二进制文件包、cfssl工具及相关镜像;k8s_work_dir定义kubernetes安装目录;etcd_work_dir定义etcd安装目录;tmp_dir为临时文件目录;以上变量对应得目录都可以按照自己的实际情况自定义。
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# cat group_vars/all.yml
# 安装目录
software_dir: '/opt/k8s_package'
k8s_work_dir: '/opt/kubernetes'
etcd_work_dir: '/opt/etcd'
tmp_dir: '/opt/tmp/kubernetes'
# 集群网络
service_cidr: '10.0.0.0/24'
cluster_dns: '10.0.0.2' # 与roles/addons/files/coredns.yaml中IP一致,并且是service_cidr中的IP
pod_cidr: '10.244.0.0/16' # 与roles/addons/files/calico.yaml中网段一致
service_nodeport_range: '30000-32767'
cluster_domain: 'cluster.local'
nic: 'eth0' # 修改为实际内网网卡名
vip: '10.2.84.240'
# 自签证书可信任IP列表,为方便扩展,可添加多个预留IP
cert_hosts:
# 包含所有LB、VIP、Master IP和service_cidr的第一个IP
k8s:
- 10.0.0.1
- 10.2.84.110
- 10.2.84.111
- 10.2.84.112
- 10.2.84.116
- 10.2.84.117
- 10.2.84.240
- kubeapi.zstp.com
# 包含所有etcd节点IP
etcd:
- 10.2.84.110
- 10.2.84.111
- 10.2.84.112
资源角色规划:
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# cat hosts
[master]
# 默认Naster节点也部署Node组件
10.2.84.110 node_name=master01
10.2.84.111 node_name=master02
10.2.84.112 node_name=master03
[worker]
10.2.84.113 node_name=worker-01
10.2.84.114 node_name=worker-02
10.2.84.115 node_name=worker-03
[etcd]
10.2.84.110 etcd_name=etcd-1
10.2.84.111 etcd_name=etcd-2
10.2.84.112 etcd_name=etcd-3
[lb]
10.2.84.116 lb_name=lb-master
10.2.84.117 lb_name=lb-backup
[k8s:children]
master
worker
[newnode]
#10.2.84.120 node_name=k8s-worker-13
Playbook主入口文件:
此文件定义各个部署任务(tasks)的入口及部署任务执行顺序,同时在每个roles下都配置了tags,我们也可以在执行playbook部署任务时通过指定tag或者跳过某个tag进行部署任务。
---
- name: 1. 开始系统初始化
gather_facts: false
hosts: all
roles:
- sysinit
tags: sysinit
- name: 2. 开始生成自签证书
gather_facts: false
hosts: localhost
roles:
- tls
tags: tls
- name: 3. 开始部署Containerd
gather_facts: false
hosts: k8s
roles:
- containerd
tags: containerd
- name: 4. 开始部署ETCD集群
gather_facts: false
hosts: etcd
roles:
- etcd
tags: etcd
- name: 5 .部署K8S Master节点
gather_facts: false
hosts: master
roles:
- master
tags: master
- name: 6. 开始部署负载均衡及高可用
gather_facts: false
hosts: lb
roles:
- ha
tags: ha
- name: 7. 开始部署K8S Worker节点
gather_facts: false
hosts: k8s
roles:
- worker
tags: worker
- name: 8. 开始部署插件
gather_facts: false
hosts: master
roles:
- components
tags: components
HA部署任务:
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# cat roles/ha/tasks/main.yml
---
- name: 创建临时目录
file: dest={{ tmp_dir }} state=directory
- name: 拷贝nginx,keepalived安装包
unarchive: src={{ software_dir }}/ha.tar.gz dest={{ tmp_dir }}
- name: 安装keepalived高可用软件
shell: rpm -ivh {{ tmp_dir }}/{{ item }}
with_items:
- "net-snmp-libs-5.7.2-49.el7.x86_64.rpm"
- "lm_sensors-libs-3.4.0.el7.x86_64.rpm"
- "net-snmp-agent-libs-5.7.2-49.el7.x86_64.rpm"
- "keepalived-1.3.5-19.el7.x86_64.rpm"
- name: 安装nginx负载均衡器
shell: rpm -ivh {{ tmp_dir }}/nginx-1.18.0-1.el7.ngx.x86_64.rpm
- name: 拷贝nginx配置文件
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: 拷贝keepalived配置文件
template: src=keepalived.conf.j2 dest=/etc/keepalived/keepalived.conf
- name: 拷贝nginx健康检查脚本
copy: src=check_nginx.sh dest=/etc/keepalived/ mode=u+x
- name: 启动服务
systemd: name={{ item }} state=restarted enabled=yes daemon_reload=yes
with_items:
- nginx
- keepalived
更新后的Containerd部署脚本:
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# cat roles/containerd/tasks/main.yml
---
- name: 分发依赖包
copy: src=libseccomp-2.5.1-1.el8.x86_64.rpm dest=/tmp/libseccomp-2.5.1-1.el8.x86_64.rpm
- name: 安装依赖
shell: rpm -Uvh libseccomp-2.5.1-1.el8.x86_64.rpm
args:
chdir: /tmp
- name: 分发并解压Containerd二进制包
unarchive: src={{ item }} dest=/
with_fileglob:
- "{{ software_dir }}/cri-containerd-*.tar.gz"
- name: 创建Containerd配置文件目录
file: dest=/etc/containerd state=directory
- name: 分发Containerd配置文件
copy: src=config.toml dest=/etc/containerd
- name: 启动Containerd
systemd: name=containerd state=restarted enabled=yes daemon_reload=yes
- name: 查看状态
shell: systemctl status containerd.service
register: containerd
- debug: var=containerd.stdout_lines
使用方法
修改hosts文件,根据规划修改对应IP和名称,如我的规划如下:
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# cat hosts
[master]
# 默认Naster节点也部署Node组件
10.2.84.110 node_name=master01
10.2.84.111 node_name=master02
10.2.84.112 node_name=master03
[worker]
10.2.84.113 node_name=worker-01
10.2.84.114 node_name=worker-02
10.2.84.115 node_name=worker-03
[etcd]
10.2.84.110 etcd_name=etcd-1
10.2.84.111 etcd_name=etcd-2
10.2.84.112 etcd_name=etcd-3
[lb]
10.2.84.116 lb_name=lb-master
10.2.84.117 lb_name=lb-backup
[k8s:children]
master
worker
[newnode]
#10.2.84.140 node_name=k8s-worker-13
修改group_vars/all.yml文件,自定义软件包目录和证书可信任IP,此篇文章的规划如下:
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# cat group_vars/all.yml
# 安装目录
software_dir: '/opt/k8s_package'
k8s_work_dir: '/opt/kubernetes'
etcd_work_dir: '/opt/etcd'
tmp_dir: '/opt/tmp/kubernetes'
# 集群网络
service_cidr: '10.0.0.0/24'
cluster_dns: '10.0.0.2' # 与roles/addons/files/coredns.yaml中IP一致,并且是service_cidr中的IP
pod_cidr: '10.244.0.0/16' # 与roles/addons/files/calico.yaml中网段一致
service_nodeport_range: '30000-32767'
cluster_domain: 'cluster.local'
nic: 'eth0' # 修改为实际内网网卡名
vip: '10.2.84.240'
# 自签证书可信任IP列表,为方便扩展,可添加多个预留IP
cert_hosts:
# 包含所有LB、VIP、Master IP和service_cidr的第一个IP
k8s:
- 10.0.0.1
- 10.2.84.110
- 10.2.84.111
- 10.2.84.112
- 10.2.84.116
- 10.2.84.117
- 10.2.84.240
- kubeapi.zstp.com
# 包含所有etcd节点IP
etcd:
- 10.2.84.110
- 10.2.84.111
- 10.2.84.112
部署
- 单Master多worker架构部署
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# ansible-playbook -i hosts single-master-deploy.yml
- 扩容新的worker节点
修改hosts文件中[newworker]主机组,其下添加要要加入的新的worker节点的ip和节点名:
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# cat add-worker.yml
---
- name: 1. 开始系统初始化
gather_facts: false
hosts: newworker
roles:
- sysinit
tags: sysinit
- name: 2. 开始部署Containerd
gather_facts: false
hosts: newworker
roles:
- containerd
tags: containerd
- name: 3. 开始部署K8S Worker节点
gather_facts: false
hosts: newworker
roles:
- worker
tags: worker
修改完成后,按照如下命令进行部署:
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# ansible-playbook -i hosts add-worker.yml
- 高可用架构部署
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# ansible-playbook -i hosts HA-k8s-deploy.yml
- 查看集群状态
部署完成后,我们登录任意一个master节点查看集群状态及pod运行状态:
[root@master01 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
etcd-0 Healthy ok
controller-manager Healthy ok
[root@master01 ~]# kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master01 Ready <none> 6m55s v1.28.1 10.2.84.110 <none> CentOS Linux 7 (Core) 3.10.0-1160.71.1.el7.x86_64 containerd://1.7.2
master02 Ready <none> 4m16s v1.28.1 10.2.84.111 <none> CentOS Linux 7 (Core) 3.10.0-1160.71.1.el7.x86_64 containerd://1.7.2
master03 Ready <none> 3m30s v1.28.1 10.2.84.112 <none> CentOS Linux 7 (Core) 3.10.0-1160.71.1.el7.x86_64 containerd://1.7.2
worker-01 Ready <none> 2m25s v1.28.1 10.2.84.113 <none> CentOS Linux 7 (Core) 3.10.0-1160.71.1.el7.x86_64 containerd://1.7.2
worker-02 Ready <none> 86s v1.28.1 10.2.84.114 <none> CentOS Linux 7 (Core) 3.10.0-1160.71.1.el7.x86_64 containerd://1.7.2
worker-03 Ready <none> 50s v1.28.1 10.2.84.115 <none> CentOS Linux 7 (Core) 3.10.0-1160.71.1.el7.x86_64 containerd://1.7.2
[root@master01 ~]# kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-64d779b5d-shggg 1/1 Running 0 22m
kube-system calico-node-2bjc9 1/1 Running 0 3m33s
kube-system calico-node-dqpzz 1/1 Running 0 6m58s
kube-system calico-node-jpcgr 1/1 Running 0 89s
kube-system calico-node-ppjch 1/1 Running 0 53s
kube-system calico-node-qz5gp 1/1 Running 0 4m19s
kube-system calico-node-vwn8w 1/1 Running 0 2m28s
kube-system coredns-8457f566b7-694xp 1/1 Running 0 22m
同时细心的朋友可能已经发现,我们在规划集群变量的时候,添加的负载均衡的地址(10.2.84.116、10.2.84.117)vip地址(10.2.84.240)以及一个域名:kubeapi.zstp.com,这样的话,生成的证书的中会包含其签名信息,这样的话我们就可以通过域名绑定ip加上config文件就可以访问集群了。
注意:安全起见,请一定保管好集群证书文件及config文件。
部署效果图:
以下是我在部署的过程中保存的一些部署效果图:
完善后的containerd部署效果(添加了containerd容器运行时的依赖):
部署过程中获取到的etcd集群状态信息:
部署完成后的集群状态信息:
可以看到最终部署成了一个包含3个master节点和3个worker节点的高可用kubernetes集群。
总结
使用Ansible Playbook离线部署Kubernetes集群是一种自动化方式,可以简化Kubernetes集群的部署过程。不过在部署过程中需要确保安全性,包括SSH访问的安全性、密钥管理、防火墙设置等。总之,使用Ansible Playbook离线部署Kubernetes集群可以提高自动化程度,减少了手动部署的复杂性和错误风险,同时也使得重复性部署更容易管理。但需要确保Playbook和配置文件的正确性,以及对Kubernetes组件的监控和维护,以保持集群的稳定性和可用性。
由于篇幅原因,这里只展示部分剧本代码,如需完整项目代码请关注微信公众号【IT运维图谱】添加后台管理员咨询获取获取。👇👇👇