Kubernetes集群升级须严格遵循基线核查、etcd快照、控制面逐组件升级、Worker节点滚动排水五步流程。①检查etcd健康与Leader唯一性;②保存独立路径快照并校验大小一致性;③按etcd→apiserver→controller-manager/scheduler顺序升级;④Worker节点执行cordon→drain→运行时与kubelet升级→uncordon;⑤全程禁止etcd写操作,确保业务零中断。

在生产环境中将Kubernetes集群从当前小版本(如v1.27.x)升级至最新稳定版(如v1.35.x),必须确保控制面组件逐台切换、etcd数据面零抖动、工作节点滚动排空与重建不中断业务流量。
升级前基线核查与etcd快照锁定
这一步不能跳过,否则后续任何异常都无法回滚。必须先确认etcd集群健康且Leader稳定,再执行一致性快照。
① 登录任意控制面节点,执行etcd健康状态检查:
ETCDCTL_API=3 etcdctl --endpoints=https://10.0.1.10:2379,https://10.0.1.11:2379,https://10.0.1.12:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key endpoint status --write-out=table
② 确认输出中所有节点的“IS LEADER”列仅有一个为true,且“HEALTH”全为true;若出现false或timeout,立即中止升级流程。
③ 执行全量快照备份:
ETCDCTL_API=3 etcdctl --endpoints=https://10.0.1.10:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot save /data/backup/etcd-snapshot-$(date +%Y%m%d%H%M).db
【快照必须保存到独立磁盘路径,不可写入系统盘根目录】否则备份过程可能触发inode耗尽导致kubelet崩溃。
④ 校验快照完整性:
ETCDCTL_API=3 etcdctl snapshot status /data/backup/etcd-snapshot-*.db | awk '{print $2}' | sort -n | uniq -c
确认各节点快照大小差异不超过5%,否则说明某节点etcd数据已偏移,不可继续升级。
控制面组件逐台升级
控制面升级顺序固定:先升级etcd → 再升级kube-apiserver → 最后升级controller-manager与scheduler。三者不可并行,必须等前一个组件就绪后再操作下一个。
方法一:使用kubeadm原地升级(推荐用于kubeadm初始化的集群)
在首台Master节点执行:
kubeadm upgrade plan → 查看可升级目标版本;
kubeadm upgrade apply v1.35.0 → 等待apiserver Pod重启完成;
kubectl get pod -n kube-system -l component=kube-apiserver -o wide → 确认新Pod Running且IP已变更。
方法二:手动替换二进制(适用于hard-way或定制化部署)
下载对应版本kube-apiserver二进制:
curl -L https://dl.k8s.io/v1.35.0/bin/linux/amd64/kube-apiserver -o /usr/local/bin/kube-apiserver && chmod +x /usr/local/bin/kube-apiserver;
修改/etc/kubernetes/manifests/kube-apiserver.yaml中image字段为k8s.gcr.io/kube-apiserver:v1.35.0;
等待kubelet自动拉起新Pod并终止旧Pod。
【升级期间禁止对etcd执行任何写操作,包括kubectl apply、helm install等】否则可能引发Raft日志不一致。
Worker节点滚动排水与Kubelet升级
节点升级必须严格遵循“标记不可调度→排水→升级运行时→升级Kubelet→恢复调度”五步链路,且每次仅处理一台节点。
第一步:标记节点为SchedulingDisabled
kubectl cordon node-01
第二步:排水并等待业务Pod全部迁移完成
kubectl drain node-01 --ignore-daemonsets --delete-emptydir-data --grace-period=30 --timeout=120s
第三步:升级containerd运行时(v1.7.20 → v1.7.23)
systemctl stop containerd && curl -L https://github.com/containerd/containerd/releases/download/v1.7.23/containerd-1.7.23-linux-amd64.tar.gz | tar -C /usr -xz && systemctl start containerd
第四步:升级kubelet与kubeadm(保持版本严格对齐)
yum install -y kubelet-1.35.0-0 kubeadm-1.35.0-0 && systemctl daemon-reload && systemctl restart kubelet
第五步:解除封锁并验证节点Ready状态
kubectl uncordon node-01 && kubectl get node node-01 -o wide
确认STATUS为Ready、VERSION显示v1.35.0、ROLES未丢失label。若ROLES为空,需手动补回:
kubectl label node node-01 node-role.kubernetes.io/worker=

















