K8s(v1.25.1) 高可用集群(3 Master + 5 Node) Ansible 剧本部署(CRI使用docker,cri-docker)
Posted 山河已无恙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K8s(v1.25.1) 高可用集群(3 Master + 5 Node) Ansible 剧本部署(CRI使用docker,cri-docker)相关的知识,希望对你有一定的参考价值。
写在前面
- 分享一个 k8s 高可用集群部署的 Ansible 剧本
- 以及涉及到的一些工具的安装
- 博文内容涉及:
- 从零开始 一个 k8s 高可用 集群部署 Ansible剧本编写,
- 编写后搭建 k8s 高可用 集群
- 一些集群常用的 监控,备份工具安装,包括:
cadvisor
监控工具部署metrics-server
监控工具部署Ingress—nginx
Ingress 控制器部署Metallb
软 LoadBalancer 部署local-path-storage
基于本地存储的SC 分配器部署prometheus
监控工具部署ETCD
快照备份定时任务编写运行Velero
集群容灾备份工具部署
- 理解不足小伙伴帮忙指正
我所渴求的,無非是將心中脫穎語出的本性付諸生活,為何竟如此艱難呢 ------赫尔曼·黑塞《德米安》
部署完的 集群 node 信息查看,感觉版本有点高,生产不太建议安装这么高的版本,有些开源工具都安装不了,各种问问题…
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$kubectl get nodes
NAME STATUS ROLES AGE VERSION
vms100.liruilongs.github.io Ready control-plane 10d v1.25.1
vms101.liruilongs.github.io Ready control-plane 10d v1.25.1
vms102.liruilongs.github.io Ready control-plane 10d v1.25.1
vms103.liruilongs.github.io Ready <none> 10d v1.25.1
vms105.liruilongs.github.io Ready <none> 10d v1.25.1
vms106.liruilongs.github.io Ready <none> 10d v1.25.1
vms107.liruilongs.github.io Ready <none> 10d v1.25.1
vms108.liruilongs.github.io Ready <none> 10d v1.25.1
部署涉及机器
- master1: 192.168.26.100
- master2: 192.168.26.101
- master3: 192.168.26.102
- work Node1: 192.168.26.103
- work Node2: 192.168.26.105
- work Node3: 192.168.26.106
- work Node4: 192.168.26.107
- work Node5: 192.168.26.108
哈 104 不吉利,跳过去了…
集群部署
部署拓扑
下图为 k8s 官网文档中 HA 拓扑图,这里使用下面的拓扑方式部署
堆叠(Stacked)HA 集群拓扑, 其中 etcd 分布式数据存储集群堆叠在 kubeadm 管理的控制平面节点上
,作为控制平面的一个组件运行。
部署后的 etcd 分布
┌──[root@vms100.liruilongs.github.io]-[~/ansible/kubescape]
└─$ETCDCTL_API=3 etcdctl --endpoints https://127.0.0.1:2379 --cert="/etc/kubernetes/pki/etcd/server.crt" --key="/etc/kubernetes/pki/etcd/server.key" --cacert="/etc/kubernetes/pki/etcd/ca.crt" member list -
w table
+------------------+---------+-----------------------------+-----------------------------+-----------------------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
+------------------+---------+-----------------------------+-----------------------------+-----------------------------+
| ee392e5273e89e2 | started | vms100.liruilongs.github.io | https://192.168.26.100:2380 | https://192.168.26.100:2379 |
| 11486647d7f3a17b | started | vms102.liruilongs.github.io | https://192.168.26.102:2380 | https://192.168.26.102:2379 |
| e00e3877df8f76f4 | started | vms101.liruilongs.github.io | https://192.168.26.101:2380 | https://192.168.26.101:2379 |
+------------------+---------+-----------------------------+-----------------------------+-----------------------------+
每个控制平面节点运行 kube-apiserver
、kube-scheduler
和 kube-controller-manager
实例。 kube-apiserver
使用负载均衡器暴露给工作节点。
每个控制平面节点创建一个本地 etcd 成员(member)
,这个 etcd 成员只与该节点的 kube-apiserver 通信
。 这同样适用于本地 kube-controller-manager 和 kube-scheduler 实例。
这种拓扑将控制平面和 etcd 成员耦合在同一节点上。相对使用外部 etcd 集群, 设置起来更简单,而且更易于副本管理。
然而,堆叠集群
存在耦合失败的风险
。如果一个节点发生故障
,则 etcd 成员和控制平面实例都将丢失, 并且冗余会受到影响。你可以通过添加更多控制平面节点来降低此风险。
因此,你应该为 HA 集群运行至少三个堆叠的控制平面节点
。
┌──[root@vms100.liruilongs.github.io]-[~/ansible/kubescape]
└─$ETCDCTL_API=3 etcdctl --endpoints https://127.0.0.1:2379 --cert="/etc/kubernetes/pki/etcd/server.crt" --key="/etc/kubernetes/pki/etcd/server.key" --cacert="/etc/kubernetes/pki/etcd/ca.crt" endpoint status --cluster -w table
+-----------------------------+------------------+---------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-----------------------------+------------------+---------+---------+-----------+-----------+------------+
| https://192.168.26.100:2379 | ee392e5273e89e2 | 3.5.4 | 37 MB | false | 100 | 3152364 |
| https://192.168.26.102:2379 | 11486647d7f3a17b | 3.5.4 | 36 MB | false | 100 | 3152364 |
| https://192.168.26.101:2379 | e00e3877df8f76f4 | 3.5.4 | 36 MB | true | 100 | 3152364 |
+-----------------------------+------------------+---------+---------+-----------+-----------+------------+
┌──[root@vms100.liruilongs.github.io]-[~/ansible/kubescape]
└─$
当使用 kubeadm init 和 kubeadm join --control-plane 时, 在控制平面节点上会自动创建本地 etcd 成员。ETCD 一点要定期备份
部署中涉及太多文件,篇幅问题,文件无法展示,以上传 git 仓库,获取 git 仓库地址方式,关注 公总好 山河已无恙,回复 k8s-ha-deploy 即可获得地址。
免密配置
这里假设我们拿到的是安装了系统的新机。这里我的机器,通过 克隆的的生成的 虚机,所以配置了 YUM 源,如果没有,需要先配置一台虚机,剩下的通过 Ansible 的批量配置下 YUM ,所以对应 YUM 的配置这个教程没有涉及,YUM 主要配置为 阿里云的 就可以。配置文件小伙伴可以通过 git 获取。
在安装 Ansible 之前,方便操作,我们需要批量配置下免密,这个使用 expect
的方式实现,用直接写好了 脚本直接执行,需要配置的主机 单独列出读取。
安装 expect
┌──[root@vms100.liruilongs.github.io]-[~]
└─$yum -y install expect
列出部署主机
┌──[root@vms100.liruilongs.github.io]-[~]
└─$cat host_list
192.168.26.100
192.168.26.101
192.168.26.102
192.168.26.103
192.168.26.105
192.168.26.106
192.168.26.107
192.168.26.108
免密脚本,直接执行即可,如果主机清单文件名相同,直接读取即可
#!/bin/bash
#@File : mianmi.sh
#@Time : 2022/08/20 17:45:53
#@Author : Li Ruilong
#@Version : 1.0
#@Desc : None
#@Contact : 1224965096@qq.com
/usr/bin/expect <<-EOF
spawn ssh-keygen
expect "(/root/.ssh/id_rsa)" send "\\r"
expect
"(empty for no passphrase)" send "\\r"
"already" send "y\\r"
expect
"again" send "\\r"
"(empty for no passphrase)" send "\\r"
expect
"again" send "\\r"
"#" send "\\r"
expect "#"
expect eof
EOF
for IP in $( cat host_list )
do
if [ -n IP ];then
/usr/bin/expect <<-EOF
spawn ssh-copy-id root@$IP
expect
"*yes/no*" send "yes\\r"
"*password*" send "redhat\\r"
expect
"*password" send "redhat\\r"
"#" send "\\r"
expect "#"
expect eof
EOF
fi
done
OK,配置完免密之后,需要安装 Ansible, 运维工具,一定要装一个,机器太多了很费人。
Ansible 安装
┌──[root@vms100.liruilongs.github.io]-[~]
└─$yum -y install ansible
ansible 配置
这里的主机清单,随便配置一个无效的,建议不要在配置文件中配置正确的主机清单,防止执行剧本到错误的主机节点。
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$vim ansible.cfg
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat ansible.cfg
[defaults]
# 主机清单文件,就是要控制的主机列表
inventory=inventory
# 连接受管机器的远程的用户名
remote_user=root
# 角色目录
roles_path=roles
# 设置用户的su 提权
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
拷贝前面的文件测试下网络情况
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat host_list
192.168.26.100
192.168.26.101
192.168.26.102
192.168.26.103
192.168.26.105
192.168.26.106
192.168.26.107
192.168.26.108
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible all -m ping -i host_list
测试没问题,需要编写下 主机清单文件
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat host.yaml
ansible:
children:
ansible_master:
hosts:
192.168.26.100:
ansible_node:
hosts:
192.168.26.[101:103]:
192.168.26.[105:108]:
k8s:
children:
k8s_master:
hosts:
192.168.26.[100:102]:
k8s_node:
hosts:
192.168.26.103:
192.168.26.[105:108]:
检查清单文件,这里的分组就不多讲了。
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible-inventory -i host.yaml --graph
@all:
|--@ansible:
| |--@ansible_master:
| | |--192.168.26.100
| |--@ansible_node:
| | |--192.168.26.101
| | |--192.168.26.102
| | |--192.168.26.103
| | |--192.168.26.105
| | |--192.168.26.106
| | |--192.168.26.107
| | |--192.168.26.108
|--@k8s:
| |--@k8s_master:
| | |--192.168.26.100
| | |--192.168.26.101
| | |--192.168.26.102
| |--@k8s_node:
| | |--192.168.26.103
| | |--192.168.26.105
| | |--192.168.26.106
| | |--192.168.26.107
| | |--192.168.26.108
|--@ungrouped:
测试一下清单文件
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible all --list-hosts -i host.yaml
hosts (8):
192.168.26.100
192.168.26.101
192.168.26.102
192.168.26.103
192.168.26.105
192.168.26.106
192.168.26.107
192.168.26.108
为了使用 tab
键,这里我们建一些清单组的空文件。
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$touch ansible_master ansible_node k8s_master k8s_node
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ls
ansible.cfg ansible_node host_list_no_ansible k8s_master ps1_mod.yaml
ansible_master host_list host.yaml k8s_node
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$
为了方便演示,看到当前的执行目录,配置下 PS1
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat ps1_mod.yaml
---
- name: all modify PS1
hosts: ansible_node
tasks:
- name: PS1 modify
shell: echo 'PS1="\\[\\033[1;32m\\]┌──[\\[\\033[1;34m\\]\\u@\\H\\[\\033[1;32m\\]]-[\\[\\033[0;1m\\]\\w\\[\\033[1;32m\\]] \\n\\[\\033[1;32m\\]└─\\[\\033[1;34m\\]\\$\\[\\033[0m\\]"' >> /root/.bashrc
- name: PS1 disply
shell: cat /root/.bashrc | grep PS1
执行剧本并测试。
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook ps1_mod.yaml -i host.yaml -vv
k8s 安装前环境准备
检查机器 UUID 和 网卡MAC 地址
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible k8s -m shell -a "ip link | grep ether| awk 'print $2 ' " -i host.yaml
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible k8s -m shell -a "cat /sys/class/dmi/id/product_uuid " -i host.yaml
剩下的 操作这个编写一个 k8s 部署环境的初始化的 剧本任务 k8s_init_deploy.yaml
,涉及各项通过剧本任务引用实现
hosts 文件准备
没有 DNS ,如果有 DNS 服务器,则不需要
┌──[root@vms100.liruilongs.github.io]-[~/ansible/file]
└─$cat hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.26.100 vms100.liruilongs.github.io vms100
192.168.26.101 vms101.liruilongs.github.io vms101
192.168.26.102 vms102.liruilongs.github.io vms102
192.168.26.103 vms103.liruilongs.github.io vms103
192.168.26.105 vms105.liruilongs.github.io vms105
192.168.26.106 vms106.liruilongs.github.io vms106
192.168.26.107 vms107.liruilongs.github.io vms107
192.168.26.108 vms108.liruilongs.github.io vms108
把 hosts
文件替换为所有机器的 hosts
,编写剧本任务
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat k8s_init_deploy.yaml
---
- name: copy "/etc/hosts"
copy:
src: ./file/hosts
dest: /etc/hosts
force: yes
防火墙,交换分区,SElinux 设置
编写剧本任务,在之前的 初始化剧本补充。
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat k8s_init_deploy.yaml
---
# 拷贝 hosts 文件,没有 DNS 需要
- name: copy "/etc/hosts"
copy:
src: ./file/hosts
dest: /etc/hosts
force: yes
# 关闭防火墙,这里设置为 trusted ,以后可能处理漏洞使用
- name: firewalld setting trusted
firewalld:
zone: trusted
permanent: yes
state: enabled
# 关闭 SELinux
- name: Disable SELinux
selinux:
state: disabled
# 禁用交换分区
- name: Disable swapoff
shell: /usr/sbin/swapoff -a
# 删除 swap 配置
- name: delete /etc/fstab
shell: sed -i '/swap/d' /etc/fstab
这里我们通过 任务引用的方式来执行,并且打一个 init 的标签。方便之后单独执行,引入到当前的 k8s 部署剧本 k8s_deploy.yaml
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat k8s_deploy.yaml
---
- name: k8s deploy
hosts: k8s
tasks:
- name: init k8s
include_tasks:
file: k8s_init_deploy.yaml
tags:
- init_k8s
k8s_deploy.yaml
为部署 k8s 所有操作的剧本。可以先执行下,完成前面的部署工作。
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook k8s_deploy.yaml -i host.yaml -f 4
有 8 个 机器,这里的 -f 4
为并行执行的意思。 -i host.yaml
指定主机清单
安装容器运行时 CRI docker
这里选择 Dokcer 作为 CRI ,但是Docker 本身没有实现 CRI,在 k8s 在 1.24 的移除了 docker
和 K8s 的桥梁 Dockershim
,所以不能直接使用,需要安装 cri-docker
.
这里需要注意:
部署 cri-docker
要重载沙箱(pause)镜像,cri-dockerd 适配器能够接受指定用作 Pod 的基础容器的容器镜像(“pause 镜像”)作为命令行参数。 要使用的命令行参数是 --pod-infra-container-image
。 如果不指定,会直接从 谷歌的镜像库拉取,即使在 kubeadm init
指定了 镜像库也不行(我部署是不行),同时,如果部署 HA ,使用 keepalived + Haproxy
的方式,并且通过 静态 Pod 的方式部署,在 启动 kubelet
的时候 静态pod 也会直接从 谷歌的镜像库拉取。
对应 cgroup 驱动的使用,按照官方官网推荐的来。 如果系统通过 systemd
来引导,就用 systemd
CRI 安装的初始化工作
转发 IPv4 并让 iptables 看到桥接流量, 相关文件准备,需要注意
┌──[root@vms100.liruilongs.github.io]-[~/ansible/file/modules-load.d]
└─$cat k8s.conf
overlay
br_netfilter
┌──[root@vms100.liruilongs.github.io]-[~/ansible/file/sysctl.d]
└─$cat k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
docker 配置文件准备,这里的配置项 "data-root": "/docker/data",
为 docker 数据目录,最好找一个大一点的地方。如果修改的话,剧本的创建目录要同步修改。
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat file/daemon.json
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"data-root": "/docker/data",
"log-opts":
"max-size": "100m"
,
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"experimental": false,
"debug": false,
"max-concurrent-downloads": 10,
"registry-mirrors": [
"https://2tefyfv7.mirror.aliyuncs.com",
"https://docker.mirrors.ustc.edu.cn"
]
当前需要复制的配置文件
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ls file/*
file/daemon.json file/hosts
file/modules-load.d:
k8s.conf
file/sysctl.d:
k8s.conf
cri-dockerd rpm
包下载,下载到 Anasible 控制节点,复制到其他的节点。
PS C:\\Users\\山河已无恙\\Downloads> curl -o cri-dockerd-0.3.0-3.el7.x86_64.rpm https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.0/cri-dockerd-0.3.0-3.el7.x86_64.rpm
PS C:\\Users\\山河已无恙\\Downloads> scp .\\cri-dockerd-0.3.0-3.el7.x86_64.rpm root@192.168.26.100:/root/ansible/install_package
root@192.168.26.100's password:
cri-dockerd-0.3.0-3.el7.x86_64.rpm 100% 9195KB 81.7MB/s 00:00
PS C:\\Users\\山河已无恙\\Downloads>
存放位置
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cd install_package/;ls
cri-dockerd-0.3.0-3.el7.x86_64.rpm
CRI docker, 安装 任务剧本
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat k8s_cri_deploy.yaml
# ansible 2.9.27
# #@File : k8s_cri_deploy.yaml
# #@Time : 2023/01/19 22:32:47
# #@Author : Li Ruilong
# #@Version : 1.0
# #@Desc : 安装 CRI , 这里我们选择 Docker,需要安装 cri-docker
# #@Contact : liruilonger@gmail.com
---
# 转发 IPv4 并让 iptables 看到桥接流量
- name: Forwarding IPv4 and letting iptables see bridged traffic 1
copy:
src: ./file/modules-load.d/k8s.conf
dest: /etc/modules-load.d/k8s.conf
- name: Forwarding IPv4 and letting iptables see bridged traffic 2
shell: modprobe overlay && modprobe br_netfilter
# 永久设置所需的 sysctl 参数
- name: sysctl params required by setup, params persist across reboots
copy:
src: ./file/sysctl.d/k8s.conf
dest: /etc/sysctl.d/k8s.conf
# 刷新内核参数
- name: Apply sysctl params without reboot
shell: sysctl --system
# 安装 docker
- name: install docker-ce docker-ce-cli containerd.io
yum:
name:
- docker-ce
- docker-ce-cli
- containerd.io
state: present
# 创建 dockers 数据目录
- name: create docker data dir
file:
path: /docker/data
state: directory
# 创建 docker 配置目录
- name: create docker data dir
file:
path: /etc/docker
state: directory
# 修改 dockers 配置
- name: modify docker config
copy:
src: ./file/daemon.json
dest: /etc/docker/daemon.json
# 复制 cri-docker rpm 安装包
- name: copy install cri-docker rpm
# https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.0/cri-dockerd-0.3.0-3.el7.x86_64.rpm
copy:
src: ./install_package/cri-dockerd-0.3.0-3.el7.x86_64.rpm
dest: /tmp/cri-dockerd-0.3.0-3.el7.x86_64.rpm
# 安装 cri-docker
- name: install cri-docker
yum:
name: /tmp/cri-dockerd-0.3.0-3.el7.x86_64.rpm
state: present
# 修改 cri-docker service 文件,否则 沙箱会从谷歌的仓库拉去
- name: modify cri-dockerd service file
copy:
src: ./file/cri-docker.service
dest: /usr/lib/systemd/system/cri-docker.service
# 配置开机自启,启动 docker
- name: start docker, setting enable
service:
name: docker
state: restarted
enabled: yes
# 配置开机自启,启动 cri-docker
- name: start cri-docker, setting enable
service:
name: cri-docker
state: restarted
enabled: yes
# 配置开机自启,启动 cri-docker.socket
- name: start cri-docker,socket setting enable
service:
name: cri-docker.socket
enabled: yes
# 配置校验
- name: check init cri
include_tasks:
file: k8s_cri_deploy_check.yaml
tags: cri_check
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$
安装完的校验单独放到了 k8s_cri_deploy_check.yaml
位置,也是通过剧本引用的方式,并且打了 cri_check
标签。这个如果希望看到检查数据,需要执行剧本时加上 -vv
,这里只是写了几个基本的校验,还可以对其他的做校验
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat k8s_cri_deploy_check.yaml
# ansible 2.9.27
# #@File : k8s_cri_deploy_check.yaml
# #@Time : 2023/01/19 23:02:47
# #@Author : Li Ruilong
# #@Version : 1.0
# #@Desc : cri(docker) 配置检查剧本任务
# #@Contact : liruilonger@gmail.com
---
- name: check br_netfilter, overlay
shell: (lsmod | grep br_netfilter ;lsmod | grep overlay)
- name: charck ipv4 sysctl param
shell: sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
- name: chrck docker config
shell: docker info
当前的 k8s 安装剧本,引入了 k8s_cri_deploy.yaml
的安装,并且 打标签 cri。
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat k8s_deploy.yaml
# ansible 2.9.27
# #@File : k8s_deploy.yaml
# #@Time : 2023/01/19 23:02:47
# #@Author : Li Ruilong
# #@Version : 1.0
# #@Desc : k8s 安装剧本
# #@Contact : liruilonger@gmail.com
---
- name: k8s deploy 1
hosts: k8s
tasks:
# 初始化 K8s 安装环境
- name: init k8s
include_tasks:
file: k8s_init_deploy.yaml
tags:
- init_k8s
# 安装 CRI docker ,cri-docker
- name: CRI deploy (docker,cri-docker)
include_tasks:
file: k8s_cri_deploy.yaml
tags: cri
可以执行测试下
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook k8s_deploy.yaml -i host.yaml -f 4
安装 kubeadm、kubelet 和 kubectl
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$cat k8s_kubeadm_kubelet_kubectl_deploy.yaml
# ansible 2.9.27
# #@File : k8s_kubeadm_kubelet_kubectl_deploy.yaml
# #@Time : 2023/01/19 23:30:47
# #@Author : Li Ruilong
# #@Version : 1.0
# #@Desc : 安装 kubeadm、kubelet 和 kubectl
# #@Contact : liruilonger@gmail.com
---
# 安装 k以上是关于K8s(v1.25.1) 高可用集群(3 Master + 5 Node) Ansible 剧本部署(CRI使用docker,cri-docker)的主要内容,如果未能解决你的问题,请参考以下文章