3. 滚动升级原理:策略、参数与流程拆解

滚动升级(Rolling Update)是 Kubernetes 节点池升级的默认策略,其核心思想是“逐步替换”:每次只升级少量节点,在保证整体集群负载能力不降级的前提下,完成全部节点的版本切换。理解 maxSurge 与 maxUnavailable 的配合关系,是排障的基础。

3.1 滚动升级策略对比

Kubernetes 支持三种升级策略,但节点池场景下最常用的是滚动升级。下表对比了三种策略的适用场景与风险:

策略类型 执行方式 集群容量影响 升级速度 典型场景
滚动升级(RollingUpdate) 逐批替换旧节点,每批数量由参数控制 可控,可维持最小可用节点数 中等,可调 生产环境默认策略
重建升级(Recreate) 先删除所有旧节点,再创建新节点 升级期间容量为零 最快(但中断最长) 测试环境、可接受完全中断的场景
原地升级(In-Place) 直接修改节点系统组件,不重建节点 无额外容量消耗 最快(无调度延迟) 托管节点池(如 GKE、AKS)
排障提示: 在自建集群中,滚动升级是排查“节点池版本卡住”问题的主要战场。maxSurge 和 maxUnavailable 配置错误,是导致升级进度阻塞的常见根因。

3.2 maxSurge 与 maxUnavailable 详解

这两个参数共同决定了滚动升级的“节奏”与“安全边界”。它们的单位可以是数量(整数)或百分比(基于节点池总节点数)。

参数 含义 默认值 典型配置 排障关注点
maxSurge 升级过程中,允许超出期望节点数的最大额外节点数 25% 1 或 10% 过大可能导致资源争抢;过小会拖慢升级速度
maxUnavailable 升级过程中,允许同时不可用的最大节点数 25% 0 或 1 设为 0 可保证零中断,但升级速度最慢
关键公式: 滚动升级的“安全窗口” = maxSurge + maxUnavailable。例如,节点池有 10 个节点,maxSurge=1,maxUnavailable=1,则升级期间最多允许 12 个节点存在(10+1+1),但最多只能有 1 个节点不可用。

3.3 升级流程拆解(5 步循环)

滚动升级是一个循环迭代的过程,每次迭代处理一批节点。以下 SVG 图展示了单批节点的完整生命周期:

滚动升级单批节点流程 滚动升级单批节点流程(5 步循环) ① 标记不可调度 kubectl cordon ② 驱逐 Pod kubectl drain ③ 删除旧节点 云商 API / 自建 ④ 创建新节点 新版本镜像 ⑤ 等待就绪 NodeReady + 健康检查 ⚠️ 排障关键检查点: • 步骤② 驱逐失败:检查 PDB(PodDisruptionBudget)是否阻止驱逐 • 步骤⑤ 就绪超时:检查节点组件版本、CNI 插件、kubelet 证书 • 循环卡住:检查 maxSurge/maxUnavailable 是否导致“死锁”

3.4 参数组合对升级行为的影响

不同的 maxSurge 与 maxUnavailable 组合,会产生截然不同的升级行为。以下表格总结了四种典型组合的效果:

组合场景 maxSurge maxUnavailable 升级行为 适用场景
零中断保守型 0 1 每次只升级 1 个节点,先创建新节点,再驱逐旧节点,保证始终有 N 个节点可用 核心生产集群,不允许 Pod 中断
快速替换型 1 1 允许 1 个额外节点和 1 个不可用节点,升级速度较快 大多数生产环境默认推荐
激进加速型 25% 25% 允许大量节点同时替换,升级速度最快,但资源争抢风险高 非生产环境、紧急版本升级
资源受限型 0 0 不允许任何额外节点或不可用节点,升级无法启动(死锁) ❌ 错误配置,需避免
死锁场景: 当 maxSurge=0 且 maxUnavailable=0 时,滚动升级无法启动任何批次,因为既不能创建新节点(maxSurge=0),也不能删除旧节点(maxUnavailable=0)。这是排障中常见的“升级进度 0%”根因之一。

3.5 升级流程中的状态机

从控制器视角看,滚动升级是一个有限状态机。以下 SVG 图展示了节点池在升级过程中的状态转换:

节点池滚动升级状态机 节点池滚动升级状态机 稳定(Stable) 所有节点版本一致 触发升级 升级中(Upgrading) 逐批替换节点 全部完成 完成(Complete) 新版本全部就绪 驱逐失败 / 就绪超时 失败(Failed) 部分节点版本不一致 回滚/手动修复 回滚中(Rollback) 恢复旧版本节点 回滚完成

3.6 排障视角:升级流程中的常见阻塞点

基于上述流程拆解,以下是每个步骤对应的典型故障模式:

  • 步骤① 标记不可调度失败: 节点处于 NotReady 状态,kubelet 失联,cordon 操作无法执行。
  • 步骤② 驱逐 Pod 失败: PodDisruptionBudget(PDB)设置过于严格,导致驱逐操作被阻塞;或 Pod 存在 local storage 且未设置 --delete-emptydir-data。
  • 步骤③ 删除节点失败: 云商 API 限流、节点处于保护状态(如 AWS Termination Protection)、或自建集群中 etcd 记录残留。
  • 步骤④ 创建节点失败: 云资源配额不足、镜像拉取失败、初始化脚本(UserData)报错。
  • 步骤⑤ 等待就绪超时: kubelet 证书过期、CNI 插件未部署、节点组件版本不兼容。
实战建议: 在升级前执行 kubectl get pdb --all-namespaces 检查所有 PDB 配置,确保 maxUnavailable 或 minAvailable 不会阻止驱逐。这是排障“升级卡在 0%”的第一步。