Deployment 的滚动更新为什么不够用
一句话总结
Rollout 是替代 Deployment 的 workload resource。替代的理由只有一个:Deployment 的 rolling update 没有“暂时停下并观察”的概念。Rollout 在这里加入了 setWeight、pause 和 analysis step。
为什么需要它
Deployment 的 RollingUpdate 通过 maxSurge 与 maxUnavailable 两个数字决定替换速度。该模型的前提是“新 Pod 只要 Ready 就是正常”。但大多数部署事故并不是 Pod 无法启动,而是 Pod 顺利启动后响应错误。readinessProbe 返回 200 的同时,支付 API 仍可能大量产生 5xx,latency 也可能增加到三倍。Deployment 没有观察这些现象的能力,会把有问题的版本一直发布到底。
它也没有为人工介入预留位置。虽然有 kubectl rollout pause,但这是需要人工把握时机执行的命令,无法写入自动化。因此,实际工作往往依赖“部署后观察 Grafana,发现异常就 rollout undo”的手动流程,而流程质量取决于当天值班人员的专注程度。Rollout 把这套流程作为声明移入 object。
工作原理
Canary strategy 通过 steps 数组表达。典型 step 有三种。
| step | 含义 |
|---|---|
| setWeight | 将发送到新版本的流量比例(或 Pod 比例)提高到指定数值 |
| pause | 暂停。指定 duration 时暂停相应时长;未指定时无限等待人工 promote |
| analysis | 启动 AnalysisRun 测量指标,失败时停止并回滚 rollout |
没有 duration 的 pause 十分重要。这是把人工批准放入 graph 的方法,也是自动化 pipeline 中间设置 manual gate 的标准惯用方式。
analysis step 引用 AnalysisTemplate。其中包含 metrics 数组,每项指标具有 interval(多久测一次)、successCondition 或 failureCondition(如何判断成功)、failureLimit(允许失败多少次)和 provider(从哪里获取数据)。例如,将 successCondition 写为 result[0] >= 0.95,provider 设为 Prometheus,当成功率低于 95% 达到 failureLimit 次时,rollout 就会自行停止并回滚。原先依赖人工专注度的流程,在这里变成了声明。
真正分割流量需要 dataplane 配合。Rollout 也可以只调整 Pod 比例(例如 4 个 replica 中 setWeight 25 对应一个),但精确比例控制必须由 ingress controller 或 service mesh 完成。因此,trafficRouting 下有 nginx、istio、alb 等实现专用配置,并同时指定 canaryService 与 stableService。controller 调整两个 Service 的 selector,改变哪组 Pod 挂在哪个 Service 后面。
Blue-green 则采用另一种形态:先完整启动新版本,只通过 previewService 访问;在 promote 的瞬间,将 activeService 切换到新版本。把 autoPromotionEnabled 设为 false 后,会等待人工 promote;scaleDownDelaySeconds 决定 promote 后旧版本继续保留多少秒。该值不设为 0,是为了保留立即回滚的余地。
现场会遇到的情况
作者家庭实验室中,与本主题相关的一次事故发生在 GPU Operator。container runtime 配置存在偏差,状态却显示正常,直到真正启动 Pod 才暴露问题。部署工具显示的状态与服务实际行为之间的差距,是本课程反复出现的主题;Rollout 的 analysis step 正是为填补这道差距而设计。它关注的不是 Pod Ready,而是响应成功率。
还有一点:迁移到 Rollout 时,实际工作最常遇到的问题是与现有 Deployment 共存。如果 Deployment 与 Rollout 使用相同 selector,两个 controller 就会争相声称同一组 Pod 属于自己。因此,迁移时可以通过 workloadRef 引用现有 Deployment,或者先把 Deployment 缩容到 0,再启动 Rollout。回滚的基础能力仍由 Kubernetes 提供。Deployment 会把 ReplicaSet 作为 revision 保留,因此可以用 rollout undo 恢复到上一状态。如果不了解这套机制,使用 Rollout 时就会觉得回滚像魔法。
下一项实验要做什么
在 /root/capa-rollout/ 中编写 canary Rollout、AnalysisTemplate 和 blue-green Rollout,并将对应的两个 Service 与 Deployment 部署到真实集群。随后修改 image,再通过 rollout undo 回滚,亲自观察 revision 如何累积。