4. RollingUpdate 深入:maxSurge、maxUnavailable 参数详解、滚动更新速率控制、PodDisruptionBudget(PDB)的作用

滚动更新(RollingUpdate)是 Kubernetes Deployment 默认且最常用的更新策略。其核心思想是逐步用新版本 Pod 替换旧版本 Pod,在保证服务可用性的前提下完成版本升级。理解 maxSurge、maxUnavailable 以及 PodDisruptionBudget(PDB)的协同机制,是精准控制更新速率、保障多集群环境下服务稳定性的关键。

4.1 maxSurge 与 maxUnavailable:滚动更新的“油门”与“刹车”

这两个参数定义在 Deployment 的 spec.strategy.rollingUpdate 字段中,它们共同决定了滚动更新的并发度与资源占用。参数值可以是整数(数量)或百分比(相对于期望副本数 replicas 的百分比),Kubernetes 在计算时会向上取整。

参数 含义 默认值 典型场景
maxSurge 更新期间,允许超出期望副本数(replicas)的最大 Pod 数量。即“最多可以多创建多少个新 Pod”。 25% 加速更新:允许短时间内创建大量新 Pod,快速完成替换。
maxUnavailable 更新期间,允许相对于期望副本数不可用的最大 Pod 数量。即“最多可以有多少个旧 Pod 同时被销毁”。 25% 保障容量:限制同时不可用的 Pod 数量,确保服务容量不跌穿阈值。

核心公式: 在滚动更新的任意时刻,集群中实际运行的 Pod 总数(可用 + 不可用)必须满足:

  • 实际 Pod 总数 ≤ 期望副本数 + maxSurge
  • 不可用 Pod 数 ≤ maxUnavailable

4.1.1 参数组合与更新速率控制

通过调整这两个参数的比值,可以实现不同的更新速率策略。以下以 replicas=10 为例,展示不同配置下的更新行为差异:

配置组合 maxSurge maxUnavailable 更新行为描述 适用场景
快速替换 25% (3) 25% (3) 同时创建 3 个新 Pod,销毁 3 个旧 Pod,每批替换 3 个,总 Pod 数在 10~13 之间波动。 开发/测试环境,追求速度。
零停机(容量优先) 0% (0) 25% (3) 先销毁 3 个旧 Pod,再创建 3 个新 Pod,总 Pod 数始终 ≤10,但容量会短暂下降。 对总资源有严格上限的场景。
零停机(冗余优先) 25% (3) 0% (0) 先创建 3 个新 Pod,待其 Ready 后再销毁 3 个旧 Pod,总 Pod 数在 10~13 之间,容量始终 ≥10。 生产环境,要求服务容量不降低。
保守更新 10% (1) 10% (1) 每次只替换 1 个 Pod,更新速度最慢,但资源波动最小。 对稳定性要求极高,或资源紧张的场景。

生产建议: 对于无状态服务,推荐使用 maxSurge=25%、maxUnavailable=0% 的组合。这能保证在更新过程中,始终有足够的 Pod 处理请求,避免容量雪崩。对于有状态服务(如数据库),通常需要更保守的设置,例如 maxSurge=0%、maxUnavailable=1(数量)。

4.2 滚动更新速率控制:从参数到实际节奏

滚动更新的实际速率不仅取决于 maxSurge 和 maxUnavailable,还受到 minReadySeconds、progressDeadlineSeconds 以及 Pod 就绪检查(Readiness Probe)的影响。

  • minReadySeconds:新创建的 Pod 在进入 Ready 状态后,需要保持该状态至少 minReadySeconds 秒,才会被视为“可用”并被用于替换旧 Pod。这可以防止 Pod 在启动初期因短暂抖动而被误判为就绪。
  • progressDeadlineSeconds:如果滚动更新在指定时间内(默认 10 分钟)没有完成,Deployment 控制器会将更新标记为失败(Progressing 状态变为 False),并停止后续更新操作。这可以防止更新卡死。
  • Readiness Probe:Pod 只有通过 Readiness Probe 检查后,才会被添加到 Service 的 Endpoint 中,开始接收流量。这是滚动更新“安全阀”的核心。

下图展示了滚动更新中,一个 Pod 从创建到正式接管流量的完整生命周期,以及各参数的作用点:

滚动更新 Pod 生命周期与参数作用点 滚动更新 Pod 生命周期与参数作用点 创建新 Pod Readiness Probe Pod Ready 加入 Endpoint 参数作用说明: • maxSurge:控制“创建新 Pod”的并发上限(图中第1步)。 • Readiness Probe:决定 Pod 何时进入 Ready 状态(图中第2步)。 • minReadySeconds:Pod Ready 后需等待该时间,才被视为“可用”(图中第3步后)。 • maxUnavailable:控制“销毁旧 Pod”的并发上限(图中第4步后触发)。

4.3 PodDisruptionBudget(PDB):保障自愿中断下的服务韧性

PDB 是 Kubernetes 提供的一种资源对象,用于限制在自愿中断(Voluntary Disruptions)场景下,同一时间最多有多少个 Pod 可以同时不可用。自愿中断包括:节点维护(kubectl drain)、集群自动缩放(Cluster Autoscaler 缩容)、主动驱逐等。PDB 与 Deployment 的滚动更新机制互补,共同构建了 Pod 层面的高可用防线。

4.3.1 PDB 与滚动更新的关系

滚动更新属于应用层的更新策略,由 Deployment Controller 驱动;而 PDB 属于集群层的保护策略,由 Disruption Controller 或 Eviction API 强制执行。当两者同时作用于同一组 Pod 时,遵循以下原则:

  • 滚动更新不受 PDB 限制:Deployment 在滚动更新中销毁旧 Pod 时,使用的是 DELETE 操作,而非 Eviction 操作,因此 PDB 不会拦截滚动更新中的 Pod 销毁。
  • 节点维护受 PDB 限制:当执行 kubectl drain 驱逐 Pod 时,Eviction API 会检查 PDB 规则。如果驱逐一个 Pod 会导致不可用 Pod 数超过 PDB 限制,则该驱逐请求会被拒绝,直到有新的 Pod 就绪或 PDB 限制被满足。

关键区别: 滚动更新是“主动替换”,PDB 是“被动保护”。滚动更新通过 maxUnavailable 控制自身节奏;PDB 通过 minAvailable 或 maxUnavailable 控制外部干扰(如节点维护)对服务的影响。两者独立工作,但目标一致:保障服务可用性。

4.3.2 PDB 配置示例与最佳实践

PDB 支持两种定义方式:minAvailable(最少可用 Pod 数)和 maxUnavailable(最多不可用 Pod 数),两者互斥,只能选其一。

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 80%  # 或使用数量: 8
  selector:
    matchLabels:
      app: my-app
PDB 配置方式 示例 适用场景
minAvailable minAvailable: 80% 对服务容量有明确百分比要求,希望在任何干扰下至少保留 80% 的 Pod。
maxUnavailable maxUnavailable: 1 对中断敏感,希望最多只允许 1 个 Pod 同时不可用,适用于有状态服务或关键组件。

多集群环境下的 PDB 策略:

  • 全局 PDB + 局部覆盖: 在集群联邦层设置一个宽松的 PDB(如 minAvailable: 50%),允许单个集群在维护时大规模缩容;同时在每个集群内部设置严格的 PDB(如 minAvailable: 80%),保障日常运行稳定性。
  • PDB 与 HPA 联动: 当 HPA 触发缩容时,PDB 会限制缩容速率,防止一次性销毁过多 Pod 导致服务抖动。建议将 PDB 的 maxUnavailable 设置为 HPA 缩容步长的一半。

4.4 综合联动:滚动更新 + PDB 的协同工作流

下图展示了在一个生产集群中,滚动更新与 PDB 如何协同工作,共同保障服务在更新和节点维护期间的稳定性:

滚动更新与 PDB 协同工作流 滚动更新与 PDB 协同工作流 滚动更新流程(Deployment Controller) 1. 创建新 Pod(受 maxSurge 限制) 2. 等待 Readiness Probe 通过 3. 新 Pod 加入 Service Endpoint 4. 销毁旧 Pod(受 maxUnavailable 限制) PDB 保护流程(Eviction API) 1. 收到 Pod 驱逐请求(如 drain) 2. 检查 PDB:minAvailable 是否满足? 3. 满足 → 允许驱逐,Pod 被删除 4. 不满足 → 拒绝驱逐,等待重试 互不干扰 互不干扰 总结:滚动更新通过 DELETE 操作绕过 PDB 检查;节点维护通过 Eviction API 受 PDB 约束。两者独立运行,共同保障服务可用性。

4.5 常见陷阱与避坑指南

  • 陷阱 1:maxSurge 和 maxUnavailable 同时为 0:这会导致滚动更新无法进行,因为既不能创建新 Pod,也不能销毁旧 Pod。Kubernetes 会拒绝此配置。
  • 陷阱 2:PDB 设置过于严格导致节点维护卡死:例如,minAvailable: 100% 且副本数为 1,此时任何驱逐操作都会被拒绝,节点永远无法完成维护。建议为关键服务设置 minAvailable: 90% 或 maxUnavailable: 1,保留一定的弹性空间。
  • 陷阱 3:忽略 PDB 对 HPA 缩容的影响:当 HPA 触发缩容时,如果 PDB 限制了不可用 Pod 数,缩容操作可能会被阻塞,导致实际副本数高于目标值。建议将 PDB 的 maxUnavailable 设置为 HPA 缩容步长的 1~2 倍。
  • 陷阱 4:在多集群场景下,PDB 未考虑集群级故障:PDB 默认只作用于单个集群。如果整个集群宕机,PDB 无法提供跨集群保护。此时需要结合集群联邦或全局负载均衡器,在集群层面进行容灾。

核心结论:

  1. maxSurge 控制“创建新 Pod”的上限,影响更新速度的上限;maxUnavailable 控制“销毁旧 Pod”的上限,影响服务容量的下限。
  2. 滚动更新速率由 maxSurge、maxUnavailable、minReadySeconds 和 Readiness Probe 共同决定,是一个多参数协同的结果。
  3. PDB 是集群层面的保护机制,专门应对自愿中断(节点维护、缩容等),与滚动更新互不干扰但目标一致。
  4. 在生产环境中,推荐将滚动更新的 maxUnavailable 设为 0%(容量优先),同时为关键服务设置 PDB(如 minAvailable: 80%),形成“应用层主动替换 + 集群层被动保护”的双重防线。