title: K8s 系列 | 第 28 天:集群升级最佳实践:Control Plane 与 Node 升级步骤
tags:
– Kubernetes
– K8s系列
– DevOps
– 集群运维
– 升级迁移
K8s 系列 | 第 28 天:集群升级最佳实践:Control Plane 与 Node 升级步骤
第 28/30 天 | 本文将从零梳理 K8s 集群升级的全流程,涵盖 Control Plane 升级、Node 升级、kubelet/kubectl 版本管理、升级前检查与回滚方案,帮助你安全高效地完成生产集群的大版本更新。
一、引言
Kubernetes 版本迭代非常迅速——每个小版本约 3 个月发布一次,社区通常同时维护最新的三个 minor 版本(例如 v1.28、v1.29、v1.30)。运行老旧集群意味着错过安全补丁、新特性和性能优化,甚至面临上游停止支持的风险。
然而,集群升级也是生产事故的高发操作。错误的升级顺序、遗漏的 API 变更、未备份的 etcd,都可能导致集群不可用。本文将基于 kubeadm 工具,详细讲解从 v1.28.x → v1.29.x 的完整升级步骤,并涵盖 Drain/Uncordon 策略、kubelet 滚动更新、节点池分批升级等核心实践。
二、升级前的准备工作
2.1 版本兼容性规则
K8s 的版本偏移规则(skew policy)要求:
| 组件 | 允许的版本差 |
|---|---|
| kube-apiserver | N 或 N-1 |
| kube-controller-manager / kube-scheduler | N 或 N-1 |
| kubelet | N-2 到 N(推荐 N-1) |
| kube-proxy | 与 kubelet 一致 |
| kubectl | N-1 到 N+1 |
实战建议:一次只升一个 minor 版本(如 v1.28 → v1.29),不建议跨多个 minor 版本升级,否则风险倍增。
2.2 升级前 Checklist
# 1. 检查当前版本
kubectl version --short
kubeadm version
# 2. 检查集群健康状态
kubectl get nodes -o wide
kubectl get pods -A | grep -v Running
# 3. 备份 etcd
ETCDCTL_API=3 etcdctl
--endpoints=https://127.0.0.1:2379
--cacert=/etc/kubernetes/pki/etcd/ca.crt
--cert=/etc/kubernetes/pki/etcd/server.crt
--key=/etc/kubernetes/pki/etcd/server.key
snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db
# 4. 查看 API 弃用资源(重点!)
kubectl get apiservice
2.3 检查 CRD 和 API 兼容性
每个 K8s 大版本都会移除一批旧版 API(例如 v1.22 移除了 extensions/v1beta1 所有资源、v1.26 移除了 flowcontrol.apiserver.k8s.io/v1beta1)。你需要提前检查集群中是否使用了即将被移除的 API 版本:
# 安装 pluto 工具检测 API 兼容性
wget https://github.com/FairwindsOps/pluto/releases/latest/download/pluto_5.19.0_linux_amd64.tar.gz
tar -xzf pluto_5.19.0_linux_amd64.tar.gz
./pluto detect-all --target-version=v1.29
三、Control Plane 升级步骤
Control Plane 是集群的大脑,升级时必须遵循 先 Control Plane、后 Worker Node 的顺序。如果有多主节点,需逐个升级。
3.1 在第一个 Control Plane 节点执行
# 第一步:确定可用的目标版本
apt update
apt-cache madison kubeadm | grep 1.29
# 第二步:锁住 kubeadm 版本并安装
apt-mark unhold kubeadm
apt-get install -y kubeadm=1.29.10-1.1
apt-mark hold kubeadm
# 第三步:检查升级计划(关键步骤)
kubeadm upgrade plan
# 第四步:应用升级(将 1.29.10 替换为你的目标版本)
kubeadm upgrade apply v1.29.10
kubeadm upgrade apply 会自动执行以下操作:
– 检查集群是否可升级
– 更新 kube-apiserver、kube-controller-manager、kube-scheduler 的静态 Pod 镜像版本
– 更新 kube-dns / CoreDNS 配置
– 更新 kube-proxy 配置
– 更新 etcd(如果也在 Control Plane 上)
3.2 升级 kubelet 和 kubectl
# 更新 kubelet 和 kubectl
apt-mark unhold kubelet kubectl
apt-get install -y kubelet=1.29.10-1.1 kubectl=1.29.10-1.1
apt-mark hold kubelet kubectl
# 重启 kubelet 服务
systemctl daemon-reload
systemctl restart kubelet
# 验证节点状态
kubectl get nodes
3.3 处理 Control Plane 节点上的 Taint
升级完成后,Control Plane 节点默认带有 node-role.kubernetes.io/control-plane 污点。此时你的工作负载不会被调度到该节点。你可以通过以下命令确认:
kubectl describe node <control-plane-node> | grep Taints
在生产环境中,建议保留这个污点——不要让业务 Pod 跑到 Control Plane 节点上。
3.4 升级其他 Control Plane 节点(可选)
如果集群有多个 Control Plane 节点(高可用架构),在第一个节点成功升级后,在其他 Control Plane 节点上依次执行:
# 在第二、第三个控制平面节点上(不用运行 kubeadm upgrade apply)
kubeadm upgrade node
四、Worker Node 升级步骤
Worker Node 是整个集群的”体力担当”,承载着业务 Pod。升级时要注意逐节点进行、确保 Pod 被安全迁移。
4.1 节点逐批升级流程
# ---- 在目标 Worker Node 上执行 ----
# 步骤 1:标记节点不可调度并驱逐 Pod
NODE_NAME=$(hostname)
kubectl cordon $NODE_NAME
kubectl drain $NODE_NAME --ignore-daemonsets --delete-emptydir-data
# 步骤 2:升级 kubeadm
apt-mark unhold kubeadm
apt-get install -y kubeadm=1.29.10-1.1
apt-mark hold kubeadm
kubeadm upgrade node
# 步骤 3:升级 kubelet 和 kubectl
apt-mark unhold kubelet kubectl
apt-get install -y kubelet=1.29.10-1.1 kubectl=1.29.10-1.1
apt-mark hold kubelet kubectl
systemctl daemon-reload
systemctl restart kubelet
# 步骤 4:恢复节点调度
kubectl uncordon $NODE_NAME
4.2 批量化升级脚本示例
#!/bin/bash
# batch-upgrade-worker.sh - 逐节点批量升级 Worker Node
NODES=("node-1" "node-2" "node-3" "node-4")
TARGET_VERSION="1.29.10"
for NODE in "${NODES[@]}"; do
echo ">>> 开始升级节点: $NODE"
# Drain 节点
kubectl cordon "$NODE"
kubectl drain "$NODE" --ignore-daemonsets --delete-emptydir-data --timeout=300s
# SSH 到节点执行升级(实际中你可能使用 Ansible 或直接 SSH)
ssh "$NODE" bash -s << EOF
apt-mark unhold kubeadm
apt-get install -y kubeadm=${TARGET_VERSION}-1.1
apt-mark hold kubeadm
kubeadm upgrade node
apt-mark unhold kubelet kubectl
apt-get install -y kubelet=${TARGET_VERSION}-1.1 kubectl=${TARGET_VERSION}-1.1
apt-mark hold kubelet kubectl
systemctl daemon-reload
systemctl restart kubelet
EOF
# 恢复调度
kubectl uncordon "$NODE"
echo "<<< 节点 $NODE 升级完成"
# 批次间等待,观察集群稳定性
sleep 60
done
echo "所有 Worker Node 升级完成!"
4.3 Drain 超时处理
kubectl drain 默认超时,如果你的 Pod 带 PDB(PodDisruptionBudget),drain 会遵守 PDB 规则。假如某个节点始终无法完成 drain:
# 强制忽略所有 Pod(谨慎使用!)
kubectl drain $NODE_NAME --ignore-daemonsets --delete-emptydir-data --force
# 如果还不行,取消 cordon 并排查:
kubectl uncordon $NODE_NAME
kubectl get pods -A --field-selector spec.nodeName=$NODE_NAME
五、升级后验证
5.1 集群健康检查
# 1. 检查所有节点状态
kubectl get nodes -o wide
# 输出示例:
# NAME STATUS ROLES VERSION
# master1 Ready control-plane v1.29.10
# node-1 Ready <none> v1.29.10
# node-2 Ready <none> v1.29.10
# 2. 检查所有核心组件
kubectl get pods -n kube-system
# 3. 检查 API 版本
kubectl api-resources | grep -E "v1beta1|v1alpha1"
5.2 功能验证
# 部署一个测试 Pod 验证调度正常
kubectl run test-pod --image=nginx --restart=Never
kubectl get pod test-pod -o wide
kubectl delete pod test-pod
# 验证 Service 联通性
kubectl run curl-test --image=curlimages/curl --restart=Never --rm -it -- curl -s http://kubernetes.default.svc
5.3 回滚方案
如果升级后发现问题,使用 etcd 快照恢复是最可靠的回滚方式:
# 停止 kube-apiserver
mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
# 恢复 etcd 快照
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot-20250714.db
--data-dir=/var/lib/etcd-restored
# 修改 etcd 配置指向恢复后的数据目录
# 然后重启所有 Control Plane 组件
# 重新安装旧版本的 kubelet
apt-get install -y kubeadm=1.28.15-1.1 kubelet=1.28.15-1.1 kubectl=1.28.15-1.1
systemctl restart kubelet
六、常见问题与避坑指南
❌ 坑 1:跳过小版本直接升级
kubeadm upgrade apply 会检查是否支持跳过版本。K8s 官方只保证从 N-1 到 N 的升级路径。从 v1.26 → v1.29 必须分三步:v1.26 → v1.27 → v1.28 → v1.29。
❌ 坑 2:未检查 CRD 和 API 废弃
升级后才发现某个 CRD 调用旧版 API 报错,导致 Operator 不可用。升级前务必运行
pluto detect-all。
❌ 坑 3:忘记解除 PodDisruptionBudget
某些 PDB 设置
maxUnavailable: 0或minAvailable: 100%,会导致 drain 一直等待。升级前检查:
kubectl get pdb -A
❌ 坑 4:节点升级顺序错误
先升 Worker Node 再升 Control Plane 会导致 kubelet 告知 apiserver 版本不匹配(kubelet 最多只能比 apiserver 低 2 个小版本)。一定要先升 Control Plane。
七、总结
K8s 集群升级并不是一件可怕的事,只要你按部就班:
| 阶段 | 关键动作 |
|---|---|
| 准备 | 备份 etcd、检查 API 弃用、确认版本兼容性 |
| Control Plane | 先第一个节点(kubeadm upgrade apply),再其他节点(kubeadm upgrade node) |
| Worker Node | cordon → drain → 升级 → uncordon,逐节点进行 |
| 验证 | 节点状态、Pod 调度、Service 联通性 |
| 回滚 | etcd 快照恢复 + 降级组件版本 |
记住一条黄金法则:升级前必须有可验证的 etcd 快照,一次只升一个 minor 版本,分阶段逐步推进。
下期预告
第 29 天:多集群管理:Federation / Cluster API / 多集群服务网格——当你的团队拥有 5 个、10 个甚至 50 个 K8s 集群时,单集群的运维经验已远远不够。我们将深入探讨多集群管理的三种主流方案:KubeFed(Federation v2)、Cluster API(声明式集群生命周期管理)以及服务网格的多集群互通模式。
📖 系列目录:K8s 30 天系列 – 全部文章















暂无评论内容