前言

上一篇文章我们介绍了如何使用Ansible Playbook离线部署一个单Master多worker节点的kubernetes集群,相信看过的朋友都基本已经掌握了如何使用Ansible playbook在脱网环境下快速部署一个kubernetes集群。但是此架构很显然存在单点(master)故障,不能满足生产环境的要求。

本篇文章的目标:使用Ansible Playbook在之前的基础上进行扩展,离线部署一个目前最新版的k8s集群(3个Master若干Worker架构)

Ansible Playbook快速部署最新版Kubernetes集群v1.28.1(离线高可用版)_Ansible

准备工作

在开始之前,确保你已经完成以下准备工作:

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

部署

  1. 单Master多worker架构部署
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# ansible-playbook -i hosts single-master-deploy.yml
  1. 扩容新的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
  1.  高可用架构部署
[root@jumpserver-app-1 ansible-deploy-k8s-v2]# ansible-playbook -i hosts HA-k8s-deploy.yml
  1. 查看集群状态

部署完成后,我们登录任意一个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容器运行时的依赖):

Ansible Playbook快速部署最新版Kubernetes集群v1.28.1(离线高可用版)_Kubernetes_02

部署过程中获取到的etcd集群状态信息:

Ansible Playbook快速部署最新版Kubernetes集群v1.28.1(离线高可用版)_Kubernetes_03

部署完成后的集群状态信息:

Ansible Playbook快速部署最新版Kubernetes集群v1.28.1(离线高可用版)_Ansible_04

可以看到最终部署成了一个包含3个master节点和3个worker节点的高可用kubernetes集群。

总结

使用Ansible Playbook离线部署Kubernetes集群是一种自动化方式,可以简化Kubernetes集群的部署过程。不过在部署过程中需要确保安全性,包括SSH访问的安全性、密钥管理、防火墙设置等。总之,使用Ansible Playbook离线部署Kubernetes集群可以提高自动化程度,减少了手动部署的复杂性和错误风险,同时也使得重复性部署更容易管理。但需要确保Playbook和配置文件的正确性,以及对Kubernetes组件的监控和维护,以保持集群的稳定性和可用性。

由于篇幅原因,这里只展示部分剧本代码,如需完整项目代码请关注微信公众号【IT运维图谱】添加后台管理员咨询获取获取。👇👇👇

Ansible Playbook快速部署最新版Kubernetes集群v1.28.1(离线高可用版)_Ansible_05