集群升级:滚动升级与版本兼容性
「K8s 集群能不能热升级?」——能,但有讲究。
K8s 升级是生产环境运维中最需要谨慎对待的操作之一。升级顺序、版本兼容性、回滚策略,每一个环节都可能影响业务连续性。这一篇讲解 K8s 升级的正确姿势和避坑指南。
升级原则
永远不要跳过两个大版本
K8s 的版本兼容性策略是 N-2:只保证当前版本和最近两个次版本的兼容性。
- 当前运行 1.23 → 可以升级到 1.24 或 1.25
- 如果在 1.21,直接升级到 1.24 → 风险极大,不推荐
升级顺序:先 Control Plane,后 Worker
升级顺序:
1. etcd(Control Plane 节点)
2. kube-apiserver(Control Plane 节点)
3. kube-controller-manager、kube-scheduler、kube-proxy(Control Plane 节点)
4. kube-proxy、kubelet(Worker 节点)
5. CNI 插件
6. 其他集群组件核心原则:Control Plane 组件永远领先 Worker 组件一个版本,或者最多持平。
升级前的准备工作
1. 确认当前版本
bash
kubectl version --short
kubectl get nodes
# VERSION 列显示 kubelet 版本2. 检查 API 废弃
bash
# 查看即将废弃的 API
kubectl api-resources -o wide | grep deprecated
# 确认是否有使用废弃 API 的资源
kubectl get all -A -o json | jq '.items[] | select(.apiVersion | contains("deprecated")) | .metadata.name'3. 备份 etcd
bash
# 升级前必须备份
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 /var/backups/etcd-pre-upgrade-$(date +%Y%m%d).db4. 检查节点资源
升级过程中新旧组件会同时运行,需要额外资源:
bash
kubectl top nodes
# 确保每个节点有至少 30% 的空闲 CPU 和内存5. 通知相关团队
- 升级期间 API Server 可能短暂不可用(通常 < 1 分钟)
- kubelet 重启期间 Pod 会显示 NotReady
- 确认业务有重试机制
升级步骤(kubeadm 为例)
Control Plane 节点升级
bash
# 1. 升级 kubeadm(所有 Control Plane 节点)
apt-get update && apt-get install -y kubeadm=1.28.0-*
kubeadm version
# 2. 在第一个 Control Plane 节点执行升级计划
sudo kubeadm upgrade plan v1.28.0
# 查看需要升级的组件和版本
# 3. 执行升级(第一个节点)
sudo kubeadm upgrade apply v1.28.0
# 4. 升级其他 Control Plane 节点
sudo kubeadm upgrade node experimental-control-plane
# 5. 升级 kubelet 和 kubectl(所有 Control Plane 节点)
apt-get update && apt-get install -y kubelet=1.28.0-* kubectl=1.28.0-*
sudo systemctl daemon-reload
sudo systemctl restart kubelet
# 6. 验证
kubectl get nodes
# 第一个节点变为 Ready (v1.28.0)Worker 节点升级
bash
# 7. 升级 kubeadm(Worker 节点)
apt-get update && apt-get install -y kubeadm=1.28.0-*
# 8. 驱逐 Worker 节点上的 Pod(业务低峰期操作)
kubectl drain node-2 --ignore-daemonsets --delete-emptydir-data --force
# 9. 升级 kubelet 配置
kubeadm upgrade node
# 10. 升级 kubelet 和 kubectl
apt-get install -y kubelet=1.28.0-* kubectl=1.28.0-*
systemctl daemon-reload
systemctl restart kubelet
# 11. 恢复节点调度
kubectl uncordon node-2
# 12. 验证
kubectl get nodes
# node-2 变为 Ready (v1.28.0)滚动升级策略
分批升级
不要一次性升级所有节点。建议按以下顺序:
第一批(1个节点):测试升级流程,观察 2-4 小时
│
▼
第二批(所有 Control Plane 剩余节点)
│
▼
第三批(1个 Worker 节点):测试驱逐和恢复
│
▼
第四批(剩余 Worker 节点,3-5 个一批)配置升级超时
yaml
# kubeadm-config ConfigMap 中配置超时
apiVersion: v1
kind: ConfigMap
metadata:
name: kubeadm-config
namespace: kube-system
data:
ClusterConfiguration: |
upgrade:
timeout: 10m版本兼容性矩阵
组件兼容性(以升级到 1.28 为例):
kubelet (1.27) → 可以连接 → kube-apiserver (1.28) ✓
kubelet (1.26) → 可以连接 → kube-apiserver (1.28) ✓
kubelet (1.28) → 可以连接 → kube-apiserver (1.27) ✓
kubectl (1.26) → 可以操作 → kube-apiserver (1.28) ✓(受 API 废弃影响)
kubectl (1.28) → 可以操作 → kube-apiserver (1.27) ✓
但实际生产中建议版本差 ≤ 2回滚
如果升级失败
bash
# etcd 快照在,停止集群,从快照恢复
systemctl stop kube-apiserver
systemctl stop etcd
ETCDCTL_API=3 etcdctl snapshot restore /var/backups/etcd-pre-upgrade-20240101.db \
--data-dir=/var/lib/etcd
systemctl start etcd
systemctl start kube-apiserver
# 验证集群状态
kubectl get nodes
kubectl get pods -APod 的回滚
Deployment 的镜像回滚不需要升级集群:
bash
# 升级集群后,如果业务 Pod 有问题,直接回滚镜像
kubectl rollout undo deployment/myapp -n production
kubectl rollout undo deployment/myapp --to-revision=3 -n production升级后的检查清单
bash
# 1. 节点状态
kubectl get nodes -o wide
kubectl top nodes
# 2. Pod 状态
kubectl get pods -A | grep -v Running
kubectl get pods -A --field-selector=status.phase!=Running
# 3. etcd 状态
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 endpoint health
# 4. API Server 可用性
kubectl get --raw=/healthz
kubectl get --raw=/healthz/etcd
kubectl get --raw=/healthz/apiserver
# 5. 核心组件日志
kubectl logs -n kube-system -l component=kube-apiserver --tail=100
kubectl logs -n kube-system -l component=kube-controller-manager --tail=100面试追问方向
- K8s 的版本兼容性策略是什么?N-2 是什么意思?
- 为什么 Control Plane 必须先于 Worker 升级?反过来可以吗?
- kubeadm upgrade plan 输出的是什么?它根据什么判断需要升级哪些组件?
- 升级期间 API Server 和 etcd 的版本不匹配会发生什么?
- 如果升级后某个 Pod 一直无法 Running,怎么排查?
K8s 升级是技术活,更是心理活——不慌不忙、按部就班、备份先行,是安全升级的三原则。
