题干与适用场景
这是一个发布控制面问题,不只是把 Deployment 的副本数改几次。控制器要记录期望版本、当前阶段、流量权重、分析结果和人工决策,并把动作可靠地反映到数据面。Google SRE 将金丝雀定义为部分且有时间限制的部署与评估;Kubernetes 原生 RollingUpdate 提供基础可用性,渐进式控制器还要补足按流量分析、暂停、批准和自动回滚。
面试官考察点
- 能否区分控制面状态、工作负载状态、流量路由和指标分析状态。
- 能否把阶段推进建模为幂等状态机,而不是一串不可恢复脚本。
- 能否定义可比较的 canary/control 窗口、样本量、保护指标和统计延迟。
- 能否处理新发布覆盖旧发布、控制器重启、指标源不可用和跨地域部分成功。
- 能否保留谁批准、何时暂停、为何回滚以及最终版本的审计链。
回答前需要澄清的问题
- 流量按请求、用户、地域还是实例分配?是否需要稳定分桶?
- 哪些指标是硬门禁,哪些只是观察项?错误预算和最小样本如何定义?
- 回滚只切流量,还是也要停止并缩容 canary?数据库和消息格式如何兼容?
- 阶段由自动策略推进,还是每阶段都需人工批准?批准权限如何授权?
- 多地域是统一推进、独立推进,还是一个地域失败就全局停止?
30 秒回答框架
“我会把发布建模成持久化状态机:一个发布版本包含阶段、目标权重、暂停策略、分析模板、超时和回滚版本。控制器通过幂等 reconcile 把期望状态写入工作负载和流量路由,再读取实际状态和按版本分组的指标。只有样本量和窗口满足门槛,且错误率、尾延迟和业务护栏都通过,才推进下一阶段;指标源失联默认暂停。每次动作带版本和幂等键,控制器重启后可恢复,所有批准、暂停、回滚和路由变更写入审计日志。”
分步骤深入解答
第一步:定义资源与状态机
发布资源至少包含 release_id、候选版本、稳定版本、阶段列表、当前阶段、目标流量、分析模板、暂停原因、超时和回滚策略。状态可包括 PENDING、RUNNING、PAUSED、PROMOTING、ABORTING、SUCCEEDED、FAILED。每个状态转换都要有前置条件和幂等动作。
第二步:拆分控制面与数据面
控制面保存期望状态和分析结论;数据面运行 Pod、Service、Ingress 或服务网格路由。控制器不把“写入 API 成功”当作发布成功,必须观察可用副本、实际权重、就绪探针和版本标签。Kubernetes Deployment 的 maxUnavailable 与 maxSurge 只约束滚动替换,不等于按用户流量的金丝雀。
第三步:设计稳定的流量分配
按用户或请求键做一致分桶,避免同一用户在 canary 与 control 间频繁跳转。路由层应返回实际权重和版本命中计数。跨地域要记录每个地域的目标权重与实际权重,不能用全局平均掩盖一个地域 100% 失败。
第四步:定义分析窗口与护栏
分析模板声明查询、采样周期、最小样本、允许误差、连续失败次数和最大等待时间。指标至少覆盖可用性、尾延迟、资源饱和与关键业务结果;每个指标绑定版本、地域和流量分母。窗口不足时保持等待,数据源超时或返回不完整时暂停,不要把缺失当作通过。
第五步:实现可恢复 reconcile
控制器周期性读取发布资源、工作负载、路由和分析结果,计算下一动作。每个外部写入带 release_id 与阶段版本;重复执行不会重复创建流量规则或重复记录批准。控制器重启后从持久化状态和实际状态重新收敛,发现实际权重偏离时先暂停并修复,而不是盲目推进。
第六步:处理暂停、批准和超时
阶段可以自动暂停、按时长暂停或无限等待人工批准。批准必须包含身份、作用域和当前阶段版本;旧批准不能推进新版本。超时默认暂停或回滚,不能继续扩大流量。手动强制推进要经过权限检查并写明原因。
第七步:设计回滚与兼容性边界
应用回滚通常先把流量切回稳定版本,再决定是否缩容 canary。数据库迁移、事件 schema 和缓存格式要满足新旧版本重叠窗口;只回滚二进制并不能撤销不可逆数据写入。回滚动作也要幂等、可观测并保留前一稳定版本。
第八步:验证、审计与演练
验证阶段推进、路由权重、指标分组、暂停、控制器重启、指标源故障、区域故障、重复 webhook 和新版本覆盖。审计记录期望状态、实际状态、操作者、时间、原因和指标快照。Google SRE 强调金丝雀应以小影响获取生产证据,演练要证明失败会停止扩大而不是只证明 API 返回 200。
设计取舍与边界
原生 RollingUpdate 与渐进式控制器
RollingUpdate 适合只需要副本逐步替换和就绪检查的服务。按流量、业务指标、人工批准和自动回滚要求出现时,需要额外控制器或平台能力;不能把副本比例当成请求比例。
自动回滚与人工决策
硬门禁适合高置信度、可快速检测的故障;业务指标延迟大或解释成本高时,自动动作应先暂停并通知负责人。策略必须明确谁拥有最终停止权。
全局统一与地域独立
统一推进简单但放大单地域风险;地域独立推进更安全却需要更多状态和容量。选择取决于流量隔离、数据驻留和故障域边界。
失败演练与演进计划
失败:把 canary 副本比例当作流量比例
实例数不等于请求数,连接复用和地域流量会让实际权重偏离。用路由层按请求键分配并记录命中计数。
失败:指标缺失时继续推进
查询延迟、标签错误或小样本可能返回空结果。缺失默认暂停,恢复后重新建立完整窗口。
失败:只回滚应用镜像
不可逆 schema、事件或缓存写入可能让旧版本无法读取。发布前做兼容性门禁,回滚先切流量,再按数据策略处理。
常见误区与追问
误区:状态机写在控制器内存里
重启会丢失阶段、批准和回滚版本。持久化发布资源与审计事件,内存只做缓存。
追问:如何防止旧控制器覆盖新发布?
用资源版本、阶段版本和条件更新;reconcile 写入前重新读取,发现版本变化就停止旧动作。
追问:如何处理两个发布同时进行?
按服务或路由建立互斥策略,或显式定义多候选流量预算;不能让两个控制器独立修改同一权重。
追问:为什么 p99 变差但平均延迟正常?
平均值会隐藏少量严重慢请求。护栏应按相同版本、地域和分母比较尾延迟与错误率。
追问:指标系统挂了怎么办?
暂停推进并标记 ANALYSIS_UNAVAILABLE,保留当前权重;恢复后重新跑窗口,不把缺失数据当成功。
追问:如何衡量发布控制器本身?
监控阶段停留时间、实际与目标权重偏差、误回滚率、检测延迟、恢复时间、审计完整性和人工覆盖次数。