升级注意事项
版本依赖关系
在高可用(HA)集群中, 多个
kube-apiserver
实例小版本号最多差 1。- 例如: 最新的 kube-apiserver 版本号如果是 1.20,则受支持的 kube-apiserver 版本号包括 1.20 和 1.19
kubelet
版本号不能高于 kube-apiserver,最多可以比 kube-apiserver 低两个小版本。- 例如: kube-apiserver 版本号如果是 1.20,受支持的的 kubelet 版本将包括 1.20、1.19 和 1.18
说明:如果 HA 集群中多个
kube-apiserver
实例版本号不一致,相应的kubelet
版本号可选范围也要减小。
如果 kube-apiserver 实例同时存在 1.20 和 1.19,kubelet 的受支持版本将是 1.19 和 1.18 (1.20 不再支持,因为它比 1.19 版本的 kube-apiserver 更新)
- 例如: kube-apiserver 版本号如果是 1.20,受支持的的 kubelet 版本将包括 1.20、1.19 和 1.18
kube-controller-manager
、kube-scheduler
和cloud-controller-manager
版本不能高于 kube-apiserver 版本号。 最好它们的版本号与 kube-apiserver 保持一致,但允许比 kube-apiserver 低一个小版本(为了支持在线升级)- 例如: 如果 kube-apiserver 版本号为 1.20,kube-controller-manager、kube-scheduler 和 cloud-controller-manager 版本支持 1.20 和 1.19
kubectl
可以比 kube-apiserver 高一个小版本,也可以低一个小版本。- 例如: 如果 kube-apiserver 当前是 1.20 版本,kubectl 则支持 1.21、1.20 和 1.19
如果 HA 集群中的多个 kube-apiserver 实例版本号不一致,相应的 kubectl 可用版本范围也会减小。
- 例如: 如果 kube-apiserver 当前是 1.20 版本,kubectl 则支持 1.21、1.20 和 1.19
组件升级次序
组件之间支持的版本偏差会影响组件升级的顺序。
kube-apiserver –> kube-controller-manager –> kube-scheduler –> cloud-controller-manager(安装了的话,未安装可忽略) –> kubelet –> kube-proxy
宏观升级流程
- 升级主master节点
- 升级其他master节点
- 升级node节点
微观升级步骤
- 先升级第一个主控制平面节点 Master 组件
- 再升级第一个主控制平面节点上的 Kubelet 和 kubectl
- 升级其他控制平面节点
- 升级Node节点
- 验证集群
升级 kubernetes 集群
升级之前注意事项
- 备份 etcd 数据库是最佳实践。
- 升级后,所有容器都会重启动,因为容器的hash值已更改。
- 由于版本的兼容性,只能从一个次要版本升级到另外一个次要版本,不能跳跃升级。
升级 ETCD 到 3.5.x 版本
此处略,参考文章:ETCD 升级
升级到 kubernetes v1.22.17
在 k8s-master01 节点下载 kubernetes 安装包
1
wget https://dl.k8s.io/v1.22.17/kubernetes-server-linux-amd64.tar.gz
拷贝安装包到所有节点
1
2
3for i in k8s-master02 k8s-master03 k8s-node01 k8s-node02;do
scp kubernetes-server-linux-amd64.tar.gz root@$i:~/
done所有节点解压安装包,并进入解压后的
kubernetes/server/bin/
目录1
tar xf kubernetes-server-linux-amd64.tar.gz && cd kubernetes/server/bin/
当前目录存在的文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20total 1095300
-rwxr-xr-x 1 root root 53030912 Dec 8 2022 apiextensions-apiserver
-rwxr-xr-x 1 root root 45871104 Dec 8 2022 kubeadm
-rwxr-xr-x 1 root root 50851840 Dec 8 2022 kube-aggregator
-rwxr-xr-x 1 root root 124850176 Dec 8 2022 kube-apiserver
-rw-r--r-- 1 root root 9 Dec 8 2022 kube-apiserver.docker_tag
-rw------- 1 root root 129631232 Dec 8 2022 kube-apiserver.tar
-rwxr-xr-x 1 root root 118538240 Dec 8 2022 kube-controller-manager
-rw-r--r-- 1 root root 9 Dec 8 2022 kube-controller-manager.docker_tag
-rw------- 1 root root 123319296 Dec 8 2022 kube-controller-manager.tar
-rwxr-xr-x 1 root root 46944256 Dec 8 2022 kubectl
-rwxr-xr-x 1 root root 53919192 Dec 8 2022 kubectl-convert
-rwxr-xr-x 1 root root 120902008 Dec 8 2022 kubelet
-rwxr-xr-x 1 root root 43454464 Dec 8 2022 kube-proxy
-rw-r--r-- 1 root root 9 Dec 8 2022 kube-proxy.docker_tag
-rw------- 1 root root 105456128 Dec 8 2022 kube-proxy.tar
-rwxr-xr-x 1 root root 49188864 Dec 8 2022 kube-scheduler
-rw-r--r-- 1 root root 9 Dec 8 2022 kube-scheduler.docker_tag
-rw------- 1 root root 53969920 Dec 8 2022 kube-scheduler.tar
-rwxr-xr-x 1 root root 1593344 Dec 8 2022 mounterk8s 客户端节点升级
kubectl
工具1
\cp -rp kubectl /usr/local/bin/
执行
kubectl version
查看客户端版本信息,输出内容如下1
2Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.17", GitCommit:"a7736eaf34d823d7652415337ac0ad06db9167fc", GitTreeState:"clean", BuildDate:"2022-12-08T11:47:36Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.14", GitCommit:"0f77da5bd4809927e15d1658fb4aa8f13ad890a5", GitTreeState:"clean", BuildDate:"2022-06-15T14:11:36Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}
升级 Master 组件
升级主 Master 节点的 kube-apiserver 组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 停止 kube-apiserver 服务
systemctl stop kube-apiserver
# 备份 kube-apiserver 组件
cp -rp /usr/local/kubernetes/bin/kube-apiserver /tmp/kube-apiserver.bak-1.21.14
# 替换 kube-apiserver 组件
\cp -rp kube-apiserver /usr/local/kubernetes/bin/
# 查看 kube-apiserver 文件版本
/usr/local/kubernetes/bin/kube-apiserver --version
# 启动 kube-apiserver 服务
systemctl daemon-reload && systemctl restart kube-apiserver.service
# 查看服务状态
systemctl status kube-apiserver.service
# 查看服务日志
journalctl -xef -u kube-apiserver.service升级主 Master 节点的 kube-controller-manager, kube-scheduler 组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# 停止 kube-controller-manager 和 kube-scheduler 服务
systemctl stop kube-controller-manager.service kube-scheduler.service
# 备份 kube-controller-manager 和 kube-scheduler 文件
cp -rp /usr/local/kubernetes/bin/kube-controller-manager /tmp/kube-controller-manager.bak-1.21.14
cp -rp /usr/local/kubernetes/bin/kube-scheduler /tmp/kube-scheduler.bak-1.21.14
# 替换 kube-controller-manager 和 kube-scheduler 文件
\cp -rp kube-controller-manager kube-scheduler /usr/local/kubernetes/bin/
# 查看 kube-controller-manager 和 kube-scheduler 文件版本
/usr/local/kubernetes/bin/kube-controller-manager --version
/usr/local/kubernetes/bin/kube-scheduler --version
# 启动 kube-controller-manager 和 kube-scheduler 服务
systemctl daemon-reload && systemctl start kube-controller-manager kube-scheduler
# 查看服务状态
systemctl status kube-controller-manager kube-scheduler
# 查看服务日志
journalctl -xef -u kube-controller-manager
journalctl -xef -u kube-scheduler使用同样的方法升级其他 master 节点
1
2
3
4
5
6
7
8# 登录其他 master 节点,停止 master 组件服务
systemctl stop kube-apiserver kube-controller-manager kube-scheduler
# 拷贝文件到其他 master 节点
\cp kube-apiserver kube-controller-manager kube-scheduler /usr/local/kubernetes/bin/
# 启动 Master 组件服务
systemctl start kube-apiserver kube-controller-manager kube-scheduler查看 master 组件状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 查看服务状态
systemctl status kube-apiserver kube-controller-manager kube-scheduler
# 查看集群状态
# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-1 Healthy {"health":"true","reason":""}
etcd-2 Healthy {"health":"true","reason":""}
etcd-0 Healthy {"health":"true","reason":""}
# 查看集群版本
# kubectl version
升级 Worker 组件
升级 kube-proxy 组件
所有节点停止 kube-proxy 服务
1
systemctl stop kube-proxy
备份 kube-proxy 文件
1
cp -rp /usr/local/kubernetes/bin/kube-proxy /tmp/kube-proxy.bak-1.21.14
替换 kube-proxy 文件
1
2
3
4for i in k8s-master01 k8s-master02 k8s-master03 k8s-node01 k8s-node02;do
ssh root@$i systemctl stop kube-proxy;
scp -rp kube-proxy root@$i:/usr/local/kubernetes/bin/;
done查看文件版本
1
/usr/local/kubernetes/bin/kube-proxy --version
启动 kube-proxy 服务
1
2
3
4
5
6
7systemctl start kube-proxy
# 查看服务状态
systemctl status kube-proxy
# 查看服务日志
journalctl -xef -u kube-proxy.service
升级 kubelet 组件
注意: 如果节点上部署了有状态服务,或者存在绑定节点运行的服务,比如 Elasticsearch 服务,不建议驱逐节点上的 Pod,建议直接停止 kubelet 服务,然后替换文件进行升级
将节点设置成不可调度状态
1
2
3
4# kubectl cordon k8s-sit-master01
node/k8s-sit-master01 cordoned
# kubectl get nodes驱逐该节点上的 pod
1
2
3
4# kubectl drain k8s-sit-master01 --delete-emptydir-data --ignore-daemonsets --force
node/k8s-sit-master01 already cordoned
WARNING: ignoring DaemonSet-managed Pods: kube-system/calico-node-qz4zl
node/k8s-sit-master01 drained停止节点上的 kubelet 服务
1
systemctl stop kubelet.service
备份 kubelet 文件
1
cp -rp /usr/local/kubernetes/bin/kubelet /tmp/kubelet.bak-1.21.14
替换 kubelet 组件
1
\cp -rp kubelet /usr/local/kubernetes/bin/
启动 kubelet 服务
1
systemctl start kubelet.service
查看节点状态
1
2
3systemctl status kubelet.service
kubectl get nodes恢复节点可调度状态
1
kubectl uncordon k8s-sit-master01
再次确认节点状态
1
kubectl get nodes
使用同样的方式滚动更新其他 worker 节点,升级完后节点状态如下
1
kubectl get nodes
建议重启 calico 网络插件
1
kubectl rollout restart ds -n kube-system calico-node
升级 Calico 网络插件
官方文档: Upgrade Calico on Kubernetes
下载最新的 calico 资源清单文件,这里下载的是 v3.24.5
1
curl https://raw.githubusercontent.com/projectcalico/calico/v3.24.5/manifests/calico-etcd.yaml -O
参考部署 calico 文档修改文件
- 修改 calico-etcd 配置,添加 ETCD 节点信息以及证书
1
2
3
4
5
6
7
8
9sed -i 's#etcd_endpoints: "http://<ETCD_IP>:<ETCD_PORT>"#etcd_endpoints: "https://10.1.30.41:2379,https://10.1.30.42:2379,https://10.1.30.43:2379"#g' calico-etcd.yaml
ETCD_CA=`cat /usr/local/etcd/ssl/etcd-ca.pem | base64 | tr -d '\n'`
ETCD_CERT=`cat /usr/local/etcd/ssl/etcd.pem | base64 | tr -d '\n'`
ETCD_KEY=`cat /usr/local/etcd/ssl/etcd-key.pem | base64 | tr -d '\n'`
sed -i "s@# etcd-key: null@etcd-key: ${ETCD_KEY}@g; s@# etcd-cert: null@etcd-cert: ${ETCD_CERT}@g; s@# etcd-ca: null@etcd-ca: ${ETCD_CA}@g" calico-etcd.yaml
sed -i 's#etcd_ca: ""#etcd_ca: "/calico-secrets/etcd-ca"#g; s#etcd_cert: ""#etcd_cert: "/calico-secrets/etcd-cert"#g; s#etcd_key: "" #etcd_key: "/calico-secrets/etcd-key" #g' calico-etcd.yaml- 修改 calico 中 CIDR 的网段为 Pods 网段,即 172.16.0.0/16
1
sed -i "s@# - name: CALICO_IPV4POOL_CIDR@- name: CALICO_IPV4POOL_CIDR@g; s@# value: \"192.168.0.0/16\"@ value: \"192.168.20.0/16\"@g" calico-etcd.yaml
- 添加节点亲和性,使 calico 不调度到边缘节点上(可选,如果不是边缘集群可以忽略这一步)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28...
template:
metadata:
labels:
k8s-app: calico-node
spec:
nodeSelector:
kubernetes.io/os: linux
hostNetwork: true
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/edge
operator: DoesNotExist
- key: node-role.kubernetes.io/agent
operator: DoesNotExist
tolerations:
# Make sure calico-node gets scheduled on all nodes.
- effect: NoSchedule
operator: Exists
# Mark the pod as a critical add-on for rescheduling.
- key: CriticalAddonsOnly
operator: Exists
- effect: NoExecute
operator: Exists
...将 DaemonSet 副本控制器的升级策略改为 OnDelete
1
2
3
4
5
6
7
8
9
10
11
12...
spec:
selector:
matchLabels:
k8s-app: calico-node
updateStrategy:
type: OnDelete
template:
metadata:
labels:
k8s-app: calico-node
...执行以下命令创建资源
1
kubectl apply -f calico-etcd.yaml
手动删除 calico-node 节点上的 Pod,触发服务更新
1
kubectl delete pods -n kube-system calico-node-xxx
查看新的 pods 的镜像版本
1
2
3
4
5
6
7
8
9# kubectl get pods -n kube-system calico-node-q5clq -oyaml |grep image:
image: docker.io/calico/node:v3.24.5
image: docker.io/calico/cni:v3.24.5
image: docker.io/calico/node:v3.24.5
- image: calico/pod2daemon-flexvol:v3.15.5
- image: docker.io/calico/node:v3.24.5
- image: docker.io/calico/cni:v3.24.5
- image: docker.io/calico/node:v3.24.5
- image: calico/pod2daemon-flexvol:v3.15.5