news 2026/9/8 23:14:43

Kubernetes生产运维14:集群升级怎么做到业务无感,从API兼容到逐节点驱逐的完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kubernetes生产运维14:集群升级怎么做到业务无感,从API兼容到逐节点驱逐的完整流程

Kubernetes生产运维14:集群升级怎么做到业务无感,从API兼容到逐节点驱逐的完整流程

写在前面

集群升级是运维里少数"做对了没人夸,做错了全公司都知道"的操作。它最怕两件事:

  • 废弃API:新版本删掉了某些API版本,你的工作负载还在用,升级后突然失效
  • 节点驱逐:升级节点时要把上面的Pod赶走,如果驱逐不当,业务会被打断

做到业务无感的核心不是运气,而是一套有顺序、有保护、有回退的流程:先查兼容、先升控制面、节点逐批升、每批验证、随时能退。

这篇给出这套完整流程和一份可直接用的Runbook,并结合一段EKS逐节点升级的真实脱敏经验,说明实际会踩的坑。

本文按照Kubernetes官方机制整理,并结合作者管理多云集群、做过EKS逐节点升级的脱敏经验。由于当前没有连接可验证的实验集群,命令和输出均为说明性重建,不是某次升级的原始记录。不同Kubernetes版本、托管服务(EKS/GKE/ACK等)和自建方式的升级步骤差异很大,务必以对应版本和平台的官方文档为准。升级是高风险操作,每步都要有验证和回退。

写在前面的真实经验

先说一个我在EKS升级中反复确认的经验,它定了这篇的基调:

升级前我会先借助工具审查新版本是否调整了API版本或CRD,看当前工作负载要不要改;升级时先升控制面(托管集群由云厂商升),再逐个升级Node Pool,一台一台来,每升一批观察Pod是否正常。曾经踩过的坑是:有些Pod没有指定nodegroup或调度约束,节点升级驱逐后飘到了错误的节点,所以每次升级都要特别注意Pod的调度约束。

这段是A级脱敏经验:先查兼容、控制面先升、节点逐台升、注意调度约束。下面把它展开成完整流程。文中的具体命令输出属于说明性重建,不是那次升级的原始记录。


一、升级前:查兼容,别让API废弃埋雷

2.1 看版本变更和废弃API

升级前先读目标版本和中间版本的Release Notes,重点是废弃(deprecated)和移除(removed)的API版本。Kubernetes会在若干版本前标记废弃,到某个版本正式移除。

如果你的工作负载还在用被移除的API版本,升级后这些资源会无法创建或更新。

2.2 扫描现有工作负载用了哪些废弃API

不要靠人工翻YAML。用工具扫描集群里实际在用的API版本,例如社区的废弃API检测工具,或云厂商EKS/GKE提供的升级前检查(insights)。

原则:

  • 升级前扫描出所有使用废弃或将被移除API的资源
  • 提前把它们迁移到新API版本,在升级前就改好
  • 不只看自己的应用,还要看Ingress Controller、监控组件、CRD、Operator等第三方组件是否兼容目标版本

2.3 检查组件兼容性

除了API,还要确认:

  • Ingress Controller、CNI、CSI、监控栈是否支持目标版本
  • CRD和Operator是否兼容
  • kubelet与控制面的版本偏差是否在支持范围内


二、升级顺序:先控制面,再节点

3.1 为什么控制面先升

Kubernetes支持控制面比节点版本高一定范围(版本偏差策略)。所以顺序是先升控制面,再升节点,反过来不行。

  • 托管集群(EKS/GKE/ACK):控制面由云厂商升级,你点一下或调API,云厂商负责。没有master/slave这种自己管的概念。
  • 自建集群:按kubeadm等工具的流程,先升控制面组件,多控制面节点逐个升。

3.2 节点升级:逐批而不是一起

节点升级不能一次全升,否则大量Pod同时被驱逐会打断业务。做法是逐批(甚至逐台):

对每个节点:

cordon 该节点(标记不可调度,新Pod不再进来) → drain 该节点(驱逐上面的Pod,让它们在别处重建) → 升级/替换该节点 → 节点Ready后uncordon(重新可调度) → 验证,再进行下一批

托管集群常用的是替换式升级:创建新版本节点,把旧节点上的Pod迁过去,再删旧节点。原理一样,关键都是逐批、有驱逐、有验证。

3.3 cordon和drain的作用

kubectl cordon'<node>'kubectl drain'<node>'--ignore-daemonsets --delete-emptydir-data
  • cordon:只标记节点不可调度,不动现有Pod,让新Pod不再进来
  • drain:驱逐节点上的Pod,触发它们在其他节点重建;--ignore-daemonsets因为DaemonSet每节点都有、不需迁移,--delete-emptydir-data表示接受emptyDir数据丢失

drain是有序驱逐,会尊重PDB。


三、用PDB保证驱逐期间的可用性

4.1 PDB是什么

PodDisruptionBudget(PDB)声明一个工作负载在自愿驱逐(如drain)期间,最少要保留多少可用副本,或最多容忍多少不可用。

apiVersion:policy/v1kind:PodDisruptionBudgetmetadata:name:web-pdbnamespace:appspec:minAvailable:2# 驱逐期间至少保留2个可用selector:matchLabels:app:web

4.2 PDB如何让升级无感

drain驱逐Pod时会遵守PDB:如果驱逐某个Pod会导致可用副本低于PDB的要求,drain会等待,直到有足够副本就绪才继续。

这样即使在逐节点升级、不断驱逐Pod的过程中,每个工作负载始终保持足够的可用副本,业务不中断。

设计要点:

  • 关键服务都应配PDB,minAvailable按能容忍的最小可用副本设
  • 单副本服务无法在驱逐时保持可用,PDB也救不了,要先多副本化
  • PDB配得太严(如minAvailable等于总副本数)会让drain卡住,永远驱逐不动

4.3 配合readiness和优雅关闭

驱逐时Pod会被终止并在别处重建。要做到无感,还需要:

  • readiness探针正确,新Pod就绪后才接流量(第11篇)
  • 优雅关闭,旧Pod先摘流量再终止
  • 足够副本和合理的滚动,避免瞬时容量不足


四、C级生产化重建案例:升级卡在一个drain不动的节点

5.1 先说明哪些是真的,哪些是重建的

下面结合真实的EKS逐节点升级经验,但具体场景和输出是根据机制构造的生产化重建,不是某次升级的原始记录。

内容证据属性
先查兼容、控制面先升、节点逐台升、注意调度约束A级脱敏经验
cordon、drain、PDB和驱逐的机制Kubernetes官方机制
drain卡住、PDB阻止驱逐的具体场景机制一致的重建场景
Namespace、资源名、副本数和终端输出为讲解构造的说明性信息
某服务PDB配置过严导致drain卡住模拟根因,不是某次升级原始记录

所有输出按真实对象关系编排,但没有连接实际集群采集,读者不能把下面的数值引用为某次升级的真实数据。

5.2 现场卡片

逐节点升级进行到某个节点时,drain一直卡住不动,节点上的一个Pod始终驱逐不掉,升级停滞。团队最初怀疑节点或Pod卡死。

重建的相对时间线:

相对时间观察或动作当时能够得出的结论
T+00drain某节点长时间不返回驱逐受阻,原因未知
T+02怀疑Pod卡死待验证假设
T+04drain输出提示违反PDB转向PDB
T+06发现该服务PDB的minAvailable等于总副本数得到可验证的主假设
T+验证调整PDB或先扩副本后观察drain单变量验证

相对时间只表示排查顺序,不代表真实数值。

5.3 看drain为什么卡住

kubectl drain worker-5 --ignore-daemonsets --delete-emptydir-data

机制一致的说明性输出:

evicting pod app/web-xxxx error when evicting pods/"web-xxxx" -n "app": Cannot evict pod as it would violate the pod's disruption budget.

drain明确说:驱逐这个Pod会违反它的PDB。不是Pod卡死,是PDB在阻止。

5.4 查PDB配置

kubectl get pdb-napp kubectl describe pdb web-pdb-napp

机制一致的说明性输出:

NAME MIN AVAILABLE ALLOWED DISRUPTIONS web-pdb 3 0 (web Deployment副本数为3)

关键发现:PDB的minAvailable是3,而该Deployment总共就3个副本。这意味着任何时候都不允许有Pod不可用,ALLOWED DISRUPTIONS为0,drain永远无法驱逐任何一个Pod。

证据链:

drain提示违反PDB,不是Pod卡死 + PDB minAvailable=3 + Deployment副本数也是3 + ALLOWED DISRUPTIONS=0 = 强烈支持PDB配置过严导致drain无法驱逐

这仍是主假设,验证前不写成根因已闭环。

5.5 止损与单变量验证

有两种单变量修正,选影响最小的:

  • 方案一:临时把副本从3扩到4,这样允许1个被驱逐,drain能继续
  • 方案二:把PDB的minAvailable从3改成2,允许1个不可用

方案一不降低可用性,更稳妥。只改副本数这一项:

kubectl scale deployment web-napp--replicas=4kubectl rollout status deployment/web-napp--timeout=5m

然后重试drain:

kubectl drain worker-5 --ignore-daemonsets --delete-emptydir-data kubectl get pdb web-pdb-napp

机制一致的说明性输出:

node/worker-5 drained NAME MIN AVAILABLE ALLOWED DISRUPTIONS web-pdb 3 1

扩到4副本后,PDB允许1个被驱逐,drain顺利完成,升级继续。

这些输出分别证明不同范围的事实:

输出能够支持不能单独证明
ALLOWED DISRUPTIONS变1有了可驱逐余量所有节点都能顺利drain
node drained成功该节点已安全腾空业务完全无感
副本扩到4驱逐期间仍满足minAvailable长期需要4副本

5.6 根因闭环与永久修复

  • 临时:扩副本让drain继续,完成本次升级
  • 永久:修正PDB设计,minAvailable不应等于总副本数,要留出至少1个可驱逐余量;或按可用性需求同时提高副本数和PDB
  • 升级完成后如果临时扩了副本,按需恢复

这也印证了那段真实经验:升级前的准备(包括PDB和副本设计)比升级动作本身更重要。PDB配错不是升级时才暴露,而是升级时才被"用到"。


五、完整升级Runbook

一、升级前(准备) [ ] 阅读目标版本和中间版本的Release Notes,列出废弃和移除的API [ ] 用工具扫描集群在用的废弃API,提前迁移到新版本 [ ] 确认Ingress Controller、CNI、CSI、监控、CRD、Operator兼容目标版本 [ ] 确认关键服务多副本且配了合理的PDB [ ] 检查Pod的调度约束,避免驱逐后飘到错误节点 [ ] 在测试集群先完整升一遍,观察一段时间 [ ] 准备回退预案,确认能退到什么程度 二、升级控制面 [ ] 选低峰窗口 [ ] 托管集群触发控制面升级,自建集群逐个升控制面节点 [ ] 验证控制面组件健康、API正常 三、逐批升级节点 [ ] 一批一台或少量节点:cordon → drain(遵守PDB)→ 升级/替换 → Ready后uncordon [ ] 每批后验证:Pod正常调度、无异常重启、关键服务可用 [ ] 观察调度约束,确认Pod没飘到错误节点 [ ] 有问题立即暂停,不继续下一批 四、升级后验证 [ ] 核心业务功能验证 [ ] 监控指标、错误率、延迟对比升级前 [ ] 组件和CRD工作正常 [ ] 恢复升级期间的临时调整(如临时扩的副本) 五、回退 [ ] 若控制面升级异常,按平台回退能力处理 [ ] 若某批节点异常,暂停并排查,必要时回退该批 [ ] 记录问题,复盘后再继续

这份Runbook可以直接改成你集群的检查项。


六、监控与治理

7.1 升级期间监控什么

  • 每批节点升级后Pod的调度和就绪情况
  • 关键服务的可用副本数是否始终满足PDB
  • 业务错误率、延迟与升级前对比
  • 是否有Pod因调度约束飘到错误节点
  • 控制面组件健康

7.2 治理

  • 升级前检查(API扫描、兼容性、PDB、调度约束)标准化成清单
  • 关键服务默认多副本加PDB,PDB不设成等于总副本数
  • 固定升级节奏(如跟随社区版本每隔一到两个小版本升一次),不跨大版本跳升
  • 每次升级后复盘,把踩的坑回补进Runbook
  • 测试集群先行,生产低峰窗口执行

七、常见误区

误区1:不查废弃API直接升

工作负载用了被移除的API,升级后失效。

误区2:节点一次全升

大量Pod同时驱逐会打断业务,要逐批。

误区3:不配PDB就drain

没有PDB保护,驱逐可能瞬间打掉过多副本。

误区4:PDB设成等于总副本数

ALLOWED DISRUPTIONS为0,drain永远卡住。

误区5:单副本服务指望升级无感

单副本驱逐必然中断,要先多副本化。

误区6:忽略Pod调度约束

驱逐后Pod可能飘到错误节点,升级前要检查。

误区7:先升节点再升控制面

违反版本偏差策略,顺序必须控制面先。

误区8:不在测试集群预演

生产直接升,遇到兼容问题就是事故。


八、面试怎么说

60秒版本

集群升级我按固定流程:升级前先查废弃和移除的API,用工具扫描集群在用的版本,提前迁移,还要确认Ingress、CNI、CSI、监控和CRD兼容目标版本。顺序是控制面先升,托管集群由云厂商升,然后节点逐批升,不能一次全升。每个节点cordon加drain,drain会遵守PDB保证关键服务始终有足够可用副本。每批升完验证Pod调度和业务,有问题就暂停。我踩过的坑是有些Pod没设调度约束,驱逐后飘到错误节点,所以每次都要检查。最后测试集群先行、低峰执行、有回退预案。

3分钟场景版本

假设逐节点升级时drain卡在一个节点不动。我先看drain输出,提示"会违反PDB",说明不是Pod卡死,是PDB在阻止。查这个服务的PDB,minAvailable设成了3,而Deployment副本也是3,导致ALLOWED DISRUPTIONS为0,任何驱逐都不允许,drain永远卡住。根因是PDB配置过严。我选影响最小的方案,临时把副本扩到4,让PDB允许1个被驱逐,drain随即完成,升级继续。永久修复是改PDB设计,minAvailable不能等于总副本数,要留可驱逐余量。这件事说明升级的坑往往在准备阶段就埋下了:PDB、副本、调度约束这些不是升级时才配,而是升级时才被用到。所以我把这些检查都放进升级前的Runbook。


九、延伸问答

1. 为什么控制面要先升

版本偏差策略允许控制面比节点高一定范围,反过来不行,所以控制面先升。

2. 节点为什么要逐批升

一次全升会同时驱逐大量Pod打断业务,逐批加PDB才能无感。

3. cordon和drain区别

cordon只标记不可调度不动现有Pod,drain会驱逐Pod让它们在别处重建。

4. PDB怎么保证升级无感

drain遵守PDB,驱逐会导致可用副本不足时会等待,保证始终有足够副本。

5. PDB设成minAvailable等于总副本会怎样

ALLOWED DISRUPTIONS为0,drain永远无法驱逐,升级卡住。

6. 废弃API怎么提前发现

用社区废弃API检测工具或云厂商升级前检查扫描集群实际在用的版本。

7. 托管集群升级和自建有什么不同

托管集群控制面由云厂商升,你不用管master;自建要自己按kubeadm等流程升控制面。

8. 升级出问题怎么回退

控制面按平台回退能力处理,节点批次异常就暂停排查,必要时回退该批并复盘。


小结

  1. 升级最怕废弃API和节点驱逐打断业务,靠流程而非运气解决。
  2. 升级前查废弃API并提前迁移,确认组件兼容。
  3. 顺序是控制面先升,再节点逐批升。
  4. 节点cordon加drain,drain遵守PDB保证可用副本。
  5. 关键服务多副本加PDB,PDB不能等于总副本数。
  6. 检查Pod调度约束,避免驱逐后飘到错误节点。
  7. 测试集群先行,低峰执行,每批验证,有回退预案。
  8. 升级的坑多在准备阶段埋下,把检查标准化成Runbook。

下一篇预告

下一篇是本专栏最后一篇:监控、告警与故障复盘。我们会讲清RED和USE方法、SLO、告警降噪、故障时间线和Postmortem,把前面所有排障经验收敛成稳定性闭环。

参考资料

  1. Kubernetes官方文档:Version Skew Policy
  2. Kubernetes官方文档:Upgrade A Cluster
  3. Kubernetes官方文档:Deprecated API Migration Guide
  4. Kubernetes官方文档:Kubernetes Deprecation Policy
  5. Kubernetes官方文档:Specifying a Disruption Budget for your Application
  6. Kubernetes官方文档:Disruptions
  7. Kubernetes官方文档:Safely Drain a Node
  8. Kubernetes官方文档:Upgrading kubeadm clusters
  9. Kubernetes官方文档:kubectl drain
  10. Kubernetes官方文档:PodDisruptionBudget API
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 23:13:04

2026小程序工具生态技术趋势:轻量化免费替代桌面软件的路径解析

工具形态的更替往往不是功能胜出&#xff0c;而是门槛胜出。桌面软件功能完整&#xff0c;但安装包动辄数百 MB、依赖本地算力、更新依赖手动升级&#xff1b;小程序工具以零安装、云端算力、即用即走的形态切入&#xff0c;把工具使用门槛压缩到"打开即用"。2026 年…

作者头像 李华
网站建设 2026/9/5 18:34:55

Linux下的代码调试

调试1、什么样的程序才能调试2、初识gdb和cgdb3、cgdb调试指令3.1、断点3.2、逐过程与逐语句3.3、变量的观察3.4、跳出循环的方法3.5、其它指令4、三种调试技巧4.1、watch4.2、set var4.3、条件断点1、什么样的程序才能调试 比如我们编写一个1~100求和的小程序&#xff0c;编译…

作者头像 李华
网站建设 2026/9/4 14:50:23

奇安信笔试题复盘:路径遍历与Java数组引用陷阱解析

1. 笔试题的整体设计思路与考察逻辑1.1 一份试卷的结构&#xff1a;Java、安全、Linux、算法的组合逻辑奇安信2019春招笔试题&#xff08;二&#xff09;给我的第一印象是&#xff1a;这不是一份纯粹的技术刷题卷&#xff0c;而是一份“安全岗基本功体检表”。那段时间我在帮准…

作者头像 李华
网站建设 2026/9/5 20:49:20

微信小程序商城实战:小米商城增删改查毕设项目

微信小程序商城项目实战&#xff1a;手把手搭建小米商城&#xff0c;增删改查全流程&#xff0c;毕设面试两不误这次我们直接开干一个微信小程序商城项目&#xff0c;以小米商城为原型&#xff0c;从零搭建前端界面、后台管理系统&#xff0c;并完整实现商品增删改查、用户登录…

作者头像 李华
网站建设 2026/9/5 19:30:32

LangChain实战指南:从核心概念到RAG与Agent工程落地

最近不少读者问我&#xff1a;LangChain 版本更新这么快&#xff0c;社区资料又杂&#xff0c;到底该怎么学才不踩坑&#xff1f;这个问题问得很实在。我见过不少团队把 LangChain 当成“调用大模型的 HTTP 封装”来用&#xff0c;结果项目一复杂就发现到处都是坑&#xff1a;P…

作者头像 李华
网站建设 2026/9/5 21:54:09

移动平均模型MA:用“意外”预测时间序列的量化利器

如果你刚开始接触量化交易里的时间序列建模&#xff0c;大概率会被“MA模型”这个词搞晕。技术分析里有 MA5、MA10 均线&#xff0c;AI 圈最近也天天聊模型量化&#xff08;比如 INT8 压缩&#xff09;&#xff0c;而统计学里还有一个 Moving Average Model。同样是“MA”&…

作者头像 李华