将Kubernetes集群版本从1.18升级至1.24
1. 系统配置
虚拟机版本:VMware Workstation Pro 17
虚拟机镜像版本:CentOS Linux release 7.9.2009 (Core)
Docker版本:ce-20.10.11
旧Kubernetes版本:1.18.0
新Kubernetes版本:1.24.16
2. 版本区别
Kubernetes从1.20版本开始已经弃用了DockerShim,并在1.24版本移除了DockerShim,后续如果需要使用Docker作为容器运行时(Container Runtime),需要安装cri-docker,即一个CRI(Container Runtime Interface)的实现。
3. 升级过程
3.1 cri-docker的安装与配置
安装cri-docker作为CRI的实现:
# v0.3.4是2023年7月30日的新版本
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.4/cri-dockerd-0.3.4.amd64.tgz
tar -xf cri-dockerd-0.3.4.amd64.tgz
cp cri-dockerd/cri-dockerd /usr/bin/
chmod +x /usr/bin/cri-dockerd
相关文件的配置:
cri-docker.service:
vim /usr/lib/systemd/system/cri-docker.service
# 写入下面的内容
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
# 此阿里云地址需要联网,如果不能联网需要指定本地镜像仓库
ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.7
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
cri-docker.socket,这个文件配置了kubelet与cri-dockerd的通信:
vim /usr/lib/systemd/system/cri-docker.socket
# 写入下面的内容
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service
[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
配置Kubernetes使用cri-docker:
vim /var/lib/kubelet/kubeadm-flags.env
# 添加参数
KUBELET_KUBEADM_ARGS="--cgroup-driver=systemd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.7 --container-runtime=remote --container-runtime-endpoint=unix:///var/run/cri-dockerd.sock"
启动cri-docker服务:
systemctl daemon-reload
systemctl start cri-docker
3.2 Kubernetes集群版本的升级
开始升级前,需要注意:
1)新版本的Kubernetes不再使用docker作为默认的CRI实现,需要我们自己配置实现。
2)Kubernetes的集群升级不支持跨版本,即不能从1.18直接升级到1.24,具体可见https: //v1-24.docs.kubernetes.io/zh-cn/releases/version-skew-policy/
3)在1.24版本中,Kubernetes正式移除了关于DockerShim的相关配置,所以使用旧版本的配置启动Kubernetes会出现参数无法识别的问题。
上面的几个点都是博主在升级过程中遇到的错误,下面是升级的过程,具体也可以查看官方文档:https: //v1-24.docs.kubernetes.io/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
如果集群还在工作,可以使用下面的指令腾空节点,腾空后该节点禁止被调度:
# 在主节点使用
# 主节点一般不运行pod,所以主要用来腾空工作节点
kubectl drain <nodeName> --ignore-daemonsets
# 升级完成后,解除腾空
kubectl uncordon <nodeName>
【主节点】
升级kubeadm版本:
# 由于不能跨版本升级,所以这里直接使用Kubernetes-1.18.0的下一个大版本1.19.0
yum install -y kubeadm-1.19.0-0 --disableexcludes=kubernetes
使用新版本的kubeadm查看更新计划:
# 这一步会检测你现在的环境、版本、配置等是否符合升级的要求
# 某些问题会提示你使用 --config 的方式进行配置解决
kubeadm upgrade plan
如果你想从1.18版本直接跳到1.24版本,那么它会提示:
[upgrade/config] FATAL: this ersion of kubeadm only supports deploying clusters with the control plane version >= 1.23.0. Current version: v1.18.0.
没有问题或解决完相关的问题后,进行集群的升级:
kubeadm upgrade apply v1.19.0
# 等待
...... successful
将kubelet和kubectl也更新到1.19.0
# 安装新版本的kubelet和kubectl
yum install -y kubelet-1.19.0-0 kubectl-1.19.0-0 --disableexcludes=kubernetes
# 服务重启
systemctl daemon-reload
systemctl restart kubelet
此时可以查看主节点的版本是否已经更新:
# 由于机器性能等原因,版本不一定会马上刷新,如版本未更新,可以等待一会查看
kubectl get nodes -o wide
【工作节点】
工作节点的大部分流程和主节点的流程一致,只是在集群升级上有出入:
# 主节点
kubectl upgrade apply v1.19.0
# 工作节点
kubectl upgrade node
由于不能跨版本升级,所以博主这里是一个大版本一个大版本升上去的,中间的过程基本一致,所以这里就省略到1.24版本的升级,如果升级途中有问题,可以查看下面的内容,下面内容记录了博主升级过程中遇到的错误。
3.3 问题总结
如果成功升级到1.24版本且每个节点的运行状态正常,可以忽略后续内容。
1)"--network-plugin"配置无法识别
到1.24版本,查看节点状态会发现每个节点都是"NotReady",即启动失败,此时查看kubelet.service的状态,会发现其没有"active"。
查看kubelet的相关日志:
journalctl -f -u kubelet
...
k8s-master: Error: failed to parse kubelet flag: unknown flag: --network-plugin
发现kubelet无法识别"--network-plugin"这个参数,因为该配置和"DockerShim"一起在Kubernetes的1.24版本移除了。(开始博主以为是某个TLS漏洞的问题,还将集群从1.23.0升级到1.23.17,以为是小版本跨越太多导致的,日志要认真从底下看,Error是最需要注意的)
发现问题后,需要去将配置中的"--network-plugin"删除:
# 找到 "--network-plugin" 删除即可
vim /var/lib/kubelet/kubeadm-flags.env
# 服务重启
systemctl restart kubelet
2)默认cgroupDriver未设置
在升级过程中,可能遇到下面的问题:
the value of KubeletConfiguration.cgroupDriver is empty; setting it to "systemd"
此时需要将在Kubelet的配置文件中设定默认"cgroupDriver"为"systemd"。
vim /etc/kubernetes/kubelet.conf
# or
vim /var/lib/kubelet/config.yaml
3)Docker版本问题
博主这里使用的Docker版本是ce-20.10.11,是Kubernetes认可的比较新的稳定版本,如果出现Docker有关的问题,可以尝试将Docker升级或降级到ce-20.10版本。
4)不要太相信AI
开始升级前,我去“请示”了一下copilot如何从1.18升级到1.24,它告诉我直接拉取1.24版本的kubeadm然后upgrade,这当然是错的,跨版本问题和CRI实现问题copilot都没有提出,当然,这也浪费了我的许多时间,许多情况下,百度和官方文档比AI好用得多。