bigywater.tech
Kubernetes · 51

Deployment 滚动更新:maxSurge 与 maxUnavailable

滚动更新时到底会多出几个 Pod、最少剩几个可用?百分比是怎么取整的?Recreate 的停机有多长?minReadySeconds 又拖慢多少?这篇用同一个 Deployment 换四组参数,把 Pod 总数的峰值、可用数的谷值和耗时全部量了出来。

8 / 5
6 个副本、默认 25%/25% 时更新过程中 Pod 总数的峰值与 Ready 数的谷值
7.9 秒 vs 23.9 秒
默认参数与 maxSurge 1 / maxUnavailable 0 的更新耗时
15.9 → 31.9 秒
4 个副本把 minReadySeconds 从 0 改成 5 之后的更新耗时

参数怎么算

实测 · 本机执行输出
  默认(25% / 25%):Pod 总数峰值 8(期望 6,多出 2);Ready 的最低值 5(少了 1);全部换完用了 7.9 秒
  maxSurge 1 / maxUnavailable 0:Pod 总数峰值 7(期望 6,多出 1);Ready 的最低值 6(少了 0);全部换完用了 23.9 秒
  maxSurge 0 / maxUnavailable 1:Pod 总数峰值 6(期望 6,多出 0);Ready 的最低值 5(少了 1);全部换完用了 24.0 秒
  maxSurge 100% / maxUnavailable 0:Pod 总数峰值 12(期望 6,多出 6);Ready 的最低值 6(少了 0);全部换完用了 4.0 秒
  默认的 25% 在 6 个副本上:maxSurge 向上取整 = ceil(1.5) = 2,maxUnavailable 向下取整 = floor(1.5) = 1,所以峰值 8、谷值 5

maxSurge 与 maxUnavailable 的百分比取整方向相反:6 个副本的 25%,maxSurge 向上取整得 2,maxUnavailable 向下取整得 1,所以默认更新时 Pod 总数最多 8 个、Ready 最少 5 个,7.9 秒完成。maxSurge 1 / maxUnavailable 0(一次只加一个、不允许少)用时 23.9 秒但始终保持 6 个 Ready;maxSurge 0 / maxUnavailable 1(不多起、一次停一个)24.0 秒;maxSurge 100% 一次性把新版本全起来,只要 4.0 秒,代价是 Pod 总数翻到 12。

一次更新的过程

实测 · 本机执行输出
    +  0.2s 总数=8 Ready=5 旧=5 新=3
    +  3.8s 总数=8 Ready=7 旧=4 新=4
    +  4.0s 总数=8 Ready=5 旧=2 新=6
    +  7.9s 总数=6 Ready=6 旧=0 新=6
  更新后的 ReplicaSet:5bcdbc4848 replicas=0 版本=1; 656cfb5ff7 replicas=6 版本=2

默认参数:+0.2 秒新旧 Pod 并存(8 个,5 个 Ready,旧 5 个新 3 个),+3.8 秒 7 个 Ready,+4.0 秒旧的缩到 2 个,+7.9 秒 6 个全是新的。两个 ReplicaSet 一边扩一边缩;更新完后旧 ReplicaSet(revision 1)replicas=0 但保留着,为回滚留下记录(下一篇)。

Recreate

实测 · 本机执行输出
  Recreate:Pod 总数峰值 6(没有多出来的),Ready 最低值 0;Ready=0 的状态从 +0.2s 持续到 +6.0s 附近;全部换完用了 6.0 秒
  时间线(总数, Ready, 旧, 新):(0, 0, 0, 0)@0.2s → (6, 0, 0, 6)@2.3s → (6, 6, 0, 6)@6.0s

strategy.type: Recreate 先把旧 Pod 全部停掉(+0.2 秒总数为 0),再创建 6 个新 Pod(+2.3 秒,Ready=0),+6.0 秒全部 Ready。大约 6 秒里一个可用的 Pod 都没有,总数则从不超过 6。只有“新旧版本绝不能同时运行”时才值得用。

minReadySeconds

实测 · 本机执行输出
  minReadySeconds=0、4 个副本、maxSurge 1 / maxUnavailable 0:全部换完用了 15.9 秒
  minReadySeconds=5、4 个副本、maxSurge 1 / maxUnavailable 0:全部换完用了 31.9 秒

新 Pod Ready 之后还要连续 Ready minReadySeconds 秒才算 available,才会继续杀旧的。4 个副本、maxSurge 1 / maxUnavailable 0:minReadySeconds=0 用了 15.9 秒,=5 用了 31.9 秒——每个批次多等 5 秒。用它可以挡住“刚 Ready 就崩”的坏版本把旧副本全换光。

分步演示

滚动更新
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0);Pod 是 busybox:1.36 sleep,就绪探针 initialDelaySeconds=3,terminationGracePeriodSeconds=2,环境变量 V 从 v1 改成 v2 触发更新;每 0.15 秒轮询一次 Pod 列表统计(总数、Ready、旧、新),时间线在计数变化时记录,峰值与谷值取自这些记录(可能漏掉不足 0.15 秒的瞬时状态);每组参数各一次;“Recreate 窗口约 6 秒”取自时间线中 Ready=0 的区间
    • 没有验证:progressDeadlineSeconds 与更新卡住时的 Progressing 条件;kubectl rollout status 的输出;百分比为小数时 maxSurge 与 maxUnavailable 同时为 0 的校验(会被拒绝);HPA 与滚动更新同时发生时的副本数;PodDisruptionBudget 与滚动更新的关系(本文没有测 PDB 是否影响 Deployment 控制器缩旧 ReplicaSet);Deployment 暂停(pause)
    京ICP备2026067502号-1京公网安备11010502063487号