说明:本文由 Codex 根据作者提供的主题、素材与公开资料辅助生成,属于 AI 生成/整理内容,非作者原创。请读者自行甄别并交叉验证。
升级不是一个命令#
Kubernetes 集群升级不是简单执行一条命令。
它至少涉及:
- 控制平面组件。
- kubelet。
- kube-proxy。
- CNI 插件。
- CSI 插件。
- CoreDNS。
- Ingress Controller。
- Metrics、日志、监控组件。
- API 版本兼容性。
- 应用 Pod 的驱逐和恢复。
所以更准确的说法是:
Kubernetes 升级是一组有顺序、有兼容性约束、有回滚预案的维护动作。升级方式分类#
托管 Kubernetes#
例如云厂商托管集群。
通常控制平面由云厂商升级,节点池由用户选择时间升级。
优点:
- 控制平面升级复杂度低。
- 云厂商会处理一部分兼容性细节。
- 节点池可以分批滚动。
仍然需要关注:
- 节点池版本。
- CNI/CSI/Ingress 插件兼容性。
- API 废弃和移除。
- 应用是否能承受 Pod 驱逐。
- PDB 和可用容量是否足够。
kubeadm 集群#
kubeadm 是自建集群常见方式。
官方升级流程大体是:
升级第一个控制平面节点;
升级其他控制平面节点;
升级工作节点。每个节点通常都要经历:
升级 kubeadm;
检查升级计划;
执行 kubeadm upgrade;
drain 节点;
升级 kubelet / kubectl;
重启 kubelet;
uncordon 节点;
验证状态。手工二进制或自定义部署#
如果控制平面和节点组件是手工部署的,升级步骤取决于部署方式。
原则仍然一样:
- 先看版本偏差策略。
- 先升控制平面。
- 再升节点组件。
- 每一步都要验证。
- 不跳过 minor 版本。
版本偏差约束#
升级前先看 Kubernetes Version Skew Policy。
几个核心规则:
| 组件 | 约束 |
|---|---|
kube-apiserver | HA 集群中新旧 apiserver 通常只能相差一个 minor |
kubelet | 不能比 apiserver 新,可以比 apiserver 旧若干 minor,具体看版本策略 |
kube-proxy | 不能比 apiserver 新,并且要和本机 kubelet 保持允许范围 |
kube-controller-manager / kube-scheduler | 不能比 apiserver 新,通常跟 apiserver minor 对齐 |
kubectl | 通常支持和 apiserver 相差一个 minor |
升级顺序背后的逻辑是:
先升级 apiserver;
再升级 controller-manager / scheduler;
再升级 kubelet;
最后处理 kube-proxy 等节点侧组件。不要跳过 minor 版本。
例如:
1.29 -> 1.30 -> 1.31不要直接:
1.29 -> 1.31升级前检查清单#
版本和 API#
kubectl version
kubectl get nodes -o wide
kubectl api-resources重点检查:
- 当前集群版本。
- 目标版本。
- 是否跨 minor。
- 是否有废弃 API。
- Webhook 是否支持新版本 API。
- CRD 是否仍兼容。
可以借助工具扫描废弃 API,例如 Pluto、kubent,或者根据 release notes 自查。
控制面健康#
kubectl get --raw='/readyz?verbose'
kubectl get --raw='/livez?verbose'
kubectl -n kube-system get pods -o wide对于 kubeadm 集群,还要关注静态 Pod:
ls /etc/kubernetes/manifests
crictl ps | grep kubeetcd 备份#
自建控制平面尤其要备份 etcd。
示例:
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot.db \
--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备份之后最好验证:
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-snapshot.db应用可用性#
检查 PodDisruptionBudget:
kubectl get pdb -A检查是否有单副本关键服务:
kubectl get deploy,statefulset -A检查节点容量:
kubectl top node
kubectl describe node <node-name>如果节点一 drain 就导致服务不可用,说明升级方案还没准备好。
kubeadm 升级流程#
下面是一个通用流程,具体版本号要按目标版本替换。
1. 查看目标 patch 版本#
Ubuntu / Debian:
sudo apt update
sudo apt-cache madison kubeadmRHEL / CentOS / Fedora:
sudo yum list --showduplicates kubeadm --disableexcludes=kubernetes目标应该选择当前 minor 或目标 minor 的最新 patch。
2. 升级第一个控制平面节点的 kubeadm#
sudo apt-mark unhold kubeadm
sudo apt-get update
sudo apt-get install -y kubeadm='1.<target>.x-*'
sudo apt-mark hold kubeadm确认版本:
kubeadm version3. 查看升级计划#
sudo kubeadm upgrade plan这个命令会检查当前集群是否可以升级,并展示可升级版本和组件配置状态。
4. 执行第一个控制平面节点升级#
sudo kubeadm upgrade apply v1.<target>.x执行完成后,控制平面静态 Pod 会被更新。
如果是 HA 控制平面,不要同时升级多个控制平面节点。一个节点完成并验证后,再处理下一个。
5. 升级其他控制平面节点#
其他控制平面节点使用:
sudo kubeadm upgrade node而不是再次执行 kubeadm upgrade apply。
6. drain 节点#
升级 kubelet 前,先把节点上的普通工作负载驱逐出去:
kubectl drain <node-name> --ignore-daemonsets如果有本地临时数据或特殊工作负载,可能还需要额外参数,但不要机械地把 --force、--delete-emptydir-data 当成默认选项。
7. 升级 kubelet 和 kubectl#
sudo apt-mark unhold kubelet kubectl
sudo apt-get update
sudo apt-get install -y kubelet='1.<target>.x-*' kubectl='1.<target>.x-*'
sudo apt-mark hold kubelet kubectl重启 kubelet:
sudo systemctl daemon-reload
sudo systemctl restart kubelet8. uncordon 节点#
kubectl uncordon <node-name>确认节点恢复:
kubectl get nodes -o wide
kubectl get pods -A -o wide9. 升级工作节点#
工作节点可以一个一个升级,也可以按批次升级,但要保证剩余容量足够支撑业务。
通用顺序:
drain node
upgrade kubeadm
kubeadm upgrade node
upgrade kubelet / kubectl
restart kubelet
uncordon node
verify workloadsCNI、CSI 和插件#
kubeadm 升级不会替你完整处理所有插件。
至少要单独确认:
- CNI 插件是否支持目标 Kubernetes 版本。
- CSI driver 是否支持目标 Kubernetes 版本。
- Ingress Controller 是否兼容。
- Metrics Server 是否兼容。
- CoreDNS 是否升级成功。
- kube-proxy 是否升级成功。
- 监控、日志、备份组件是否兼容。
尤其是 CNI 和 CSI,升级顺序要看各自官方文档。
网络和存储插件不兼容,比控制面升级失败更难排查。
升级中的风险点#
API 移除#
Kubernetes 会在新版本移除旧 API。
如果集群里仍有旧版本资源,例如旧 Ingress API、旧 CRD 版本、旧 PodSecurityPolicy 之类,升级后可能出现无法创建、无法更新或控制器异常。
升级前要检查:
kubectl get apiservices
kubectl get crd
kubectl get validatingwebhookconfiguration
kubectl get mutatingwebhookconfigurationPDB 阻止 drain#
如果 PDB 太严格,kubectl drain 可能无法驱逐 Pod。
这通常不是坏事,它说明升级会影响可用性。
处理方式应该是:
- 增加副本。
- 调整 PDB。
- 分批升级。
- 预留容量。
不要一上来就强制删除关键 Pod。
单副本有状态服务#
单副本 StatefulSet、数据库、队列等服务需要特别谨慎。
升级前要确认:
- 是否有备份。
- 是否允许短暂停机。
- 是否有主从切换。
- 是否依赖本地盘。
- drain 后 Pod 能否在其他节点恢复。
Webhook 影响控制面#
Admission Webhook 如果不可用,可能影响新资源创建或更新。
升级前检查:
kubectl get validatingwebhookconfiguration
kubectl get mutatingwebhookconfiguration确认 webhook 服务本身高可用,并且支持目标版本 API。
回滚和恢复#
升级前要接受一个现实:
Kubernetes 控制面升级不是普通应用发布,不应该把“回滚”当成主要恢复手段。更稳妥的是:
- 升级前备份 etcd。
- 每一步升级后立即验证。
- 一次只升级一个控制平面节点。
- 工作节点分批升级。
- 出问题先暂停,不继续扩散。
kubeadm 在升级时会在 /etc/kubernetes/tmp 下生成一些备份目录,例如静态 Pod manifest 和本地 etcd 备份。遇到失败时,应该结合官方恢复说明和现场状态处理。
验证清单#
升级后至少检查:
kubectl get nodes -o wide
kubectl get pods -A -o wide
kubectl get events -A --sort-by=.metadata.creationTimestamp
kubectl get --raw='/readyz?verbose'
kubectl get --raw='/livez?verbose'业务侧检查:
- 核心服务是否 Ready。
- Service、Ingress 是否可访问。
- DNS 是否正常。
- HPA 是否能读取指标。
- 日志和监控是否有数据。
- PVC 是否能正常挂载。
- CNI 跨节点通信是否正常。
一套保守升级策略#
生产环境可以按这个节奏:
1. 读 release notes 和 version skew policy
2. 检查废弃 API
3. 检查 CNI / CSI / Ingress / 监控组件兼容性
4. 备份 etcd 和关键应用数据
5. 先升级测试集群
6. 生产先升级一个控制平面节点
7. 验证控制平面和插件状态
8. 升级剩余控制平面节点
9. 分批升级 worker 节点
10. 做业务回归和监控观察这里的重点不是快,而是每一步都能停下来观察。
小结#
Kubernetes 升级的关键是顺序和兼容性。
不跳 minor;
先控制平面,后工作节点;
先 plan,后 apply;
先 drain,后升级 kubelet;
每一步验证;
插件兼容性单独确认。如果把升级看成“控制面、节点、插件、应用”四层协同,就比只盯着 kubeadm 命令更接近真实生产环境。