灰度发布、金丝雀发布与快速回滚

生产发布不是把新版本复制到全部服务器,而是一个持续验证风险的过程。灰度发布通过控制影响范围、观察关键指标并设置自动停止条件,让错误尽可能早暴露在少量流量中。快速回滚则要求旧版本、配置、数据结构和流量入口都具备可恢复路径。

本文适用于 Web 服务、API、微服务和 Kubernetes 工作负载。它不能替代单元测试、集成测试与安全评审,而是上线前最后一道生产保护。

一、发布方式怎么选

方式 核心思路 优点 主要风险
滚动发布 分批替换旧实例 资源需求较低 新旧版本同时存在,回退可能较慢
蓝绿发布 两套完整环境切换流量 切换和回退快 资源成本高,数据库仍需兼容
金丝雀发布 少量实例或流量先使用新版本 控制影响范围,可量化比较 指标和流量分配设计复杂
Feature Flag 发布代码后再逐步启用功能 功能上线与二进制发布解耦 标志长期不清理会形成复杂分支
影子流量 复制真实请求到新系统,不返回结果 接近真实流量且不影响响应 有状态写入必须隔离,成本较高

同一系统可以组合使用。例如先用蓝绿环境准备新版本,再把 5% 流量导向绿色环境形成金丝雀。

二、建立发布准入条件

发布前应满足:

  • 构建产物可追溯到提交、流水线和依赖清单;
  • 自动化测试和安全检查通过;
  • 配置差异已审阅,敏感信息不进入代码仓库;
  • 数据库变更具备前向和后向兼容性;
  • 监控可以区分版本、实例、区域和流量组;
  • 回滚产物仍然可用,回滚命令经过测试;
  • 发布负责人、观察人和停止权限明确;
  • 已知风险、用户影响和客服口径已记录。

如果无法区分新旧版本的指标,就无法判断金丝雀是否更差,只能称为“分批发布”。

三、选择金丝雀人群

金丝雀流量应具有代表性,同时限制爆炸半径。常用维度包括:

  • 内部员工或测试账号;
  • 单个租户、地区、可用区或机房;
  • 特定设备、客户端版本或请求头;
  • 随机百分比流量;
  • 无状态只读接口优先;
  • 风险较低但请求模式完整的业务路径。

不要只选“最简单、最稳定”的请求,否则无法覆盖新版本的真实风险。涉及支付、删除、消息发送的写路径,应先验证幂等和数据隔离。

四、设计发布阶梯

典型阶梯不是固定答案,可以从以下结构开始:

阶段 0:0% 用户流量,完成启动、健康检查和合成探测
阶段 1:1% 流量,观察 10~15 分钟
阶段 2:5% 流量,观察一个短业务周期
阶段 3:20% 流量,覆盖主要请求类型
阶段 4:50% 流量,确认依赖与容量变化
阶段 5:100% 流量,继续保留回退窗口

低流量系统可能需要更长时间才能获得有效样本;高频系统可以缩短时间,但不能短到队列、缓存和定时任务尚未表现。批处理、结算和日终任务应按业务周期观察。

五、定义自动判断指标

至少比较新版本和对照组,而不是只检查固定阈值:

维度 指标示例 停止条件示例
正确性 业务失败率、结果一致性 相对对照组上升 20%
可用性 HTTP 5xx、超时率 连续 5 分钟超过 SLO
性能 P95、P99、队列等待 P99 高于对照组 30%
资源 CPU、内存、GC、连接 资源斜率持续异常
依赖 数据库、缓存、第三方错误 下游错误或限额显著增加
业务 登录成功率、支付成功率 核心转化出现统计显著下降

固定阈值用于防止绝对故障,对照组比较用于发现新版本回归。样本太少时不要得出“新版本正常”的结论。

六、把 SLO 和错误预算接入发布

发布判断应优先使用用户体验指标。可以用短窗口和长窗口燃尽率组合:短窗口快速发现严重回归,长窗口避免瞬时噪声。若服务错误预算已经接近耗尽,应降低发布速度、缩小批次或暂停非必要变更。

发布流水线可以实现以下门禁:

若核心 SLI 达标,且新版本相对对照组无显著恶化:继续
若数据不足:延长观察,不自动判定成功
若触发硬性安全阈值:立即停止并回退
若只触发软阈值:暂停,要求人工评估

七、数据库变更必须可兼容

应用回滚失败最常见的原因之一,是数据库已经变成旧版本无法理解的结构。建议使用 Expand—Migrate—Contract:

  1. Expand:先添加新字段或新表,不删除旧结构;
  2. Deploy:新旧应用同时兼容两种结构;
  3. Migrate:后台迁移历史数据并校验;
  4. Switch:逐步切换读写路径;
  5. Contract:确认回滚窗口结束后再删除旧结构。

禁止在同一发布步骤中直接重命名字段、删除列并切换全部应用。大表 DDL 还要评估锁、复制延迟、日志量和磁盘空间。

八、配置和功能开关

Feature Flag 应有:

  • 所有者、用途和影响范围;
  • 默认值及失效行为;
  • 启用条件和紧急关闭方式;
  • 创建日期、计划清理日期;
  • 访问审计和权限控制;
  • 服务端兜底,不能只依赖前端隐藏。

开关不是永久配置中心。发布完成后应删除过期开关和分支逻辑,否则测试组合呈指数增长。

九、快速回滚的真实要求

回滚不只是执行 kubectl rollout undo。完整回滚需要检查:

  • 旧镜像或安装包仍存在且签名可验证;
  • 旧配置可以恢复,且密钥版本仍有效;
  • 数据库结构允许旧版本运行;
  • 消息格式、缓存键和 API 合约向后兼容;
  • 流量入口、DNS、CDN 和负载均衡能恢复;
  • 后台任务不会由两个版本重复执行;
  • 回滚后执行业务探测,而不是只看 Pod Ready。

定义回滚时间目标,例如从决定回滚到用户核心路径恢复不超过 10 分钟,并在非生产环境演练。

十、Kubernetes发布示例思路

一个受控流程可以是:

steps:
  - setWeight: 5
  - pause: {duration: 10m}
  - analysis: {templates: [service-slo-check]}
  - setWeight: 20
  - pause: {duration: 20m}
  - analysis: {templates: [service-slo-check, dependency-check]}
  - setWeight: 50
  - pause: {duration: 30m}

此片段只表达策略。实际字段以所使用的渐进式交付控制器版本为准。分析模板应查询与该版本、该服务相关的指标,并处理监控无数据、查询失败和样本不足。

十一、一次完整发布案例

某查询服务准备发布缓存策略变更:

  1. 预发布环境使用生产脱敏流量回放;
  2. 新版本启动后只接受合成探测;
  3. 导入 2% 真实读流量,比较命中率、P99 与数据库 QPS;
  4. 发现缓存命中率提升,但数据库连接创建速率异常;
  5. 自动门禁暂停发布,确认新客户端未复用连接;
  6. 修复后重新构建制品,从 2% 重新开始;
  7. 20%、50% 阶段均通过,最终全量;
  8. 保留旧版本和开关 24 小时,再结束回退窗口。

关键点是发现问题后重新生成可追溯制品,而不是直接进入容器临时修改。

十二、发布期间的职责

角色 主要职责
发布负责人 推进阶段、记录决定、发起暂停或回退
服务负责人 判断业务正确性和已知风险
观察人员 监控 SLI、依赖和资源变化
数据库负责人 审核结构变更、迁移和复制状态
值班人员 接收用户侧异常,避免信息断层

高风险发布不应由一个人同时操作、观察和决定。夜间发布也不天然更安全;低流量可能导致样本不足,且人员响应能力更弱。

十三、发布记录模板

变更编号:CHG-2026-001
制品版本及摘要:app:v2.4.1 / sha256:...
数据库变更:新增可空字段,无破坏性删除
灰度维度:随机用户 + 单可用区
阶段:2% → 10% → 25% → 50% → 100%
核心指标:成功率、P99、数据库 QPS、队列长度
硬停止条件:错误率 > 1% 或关键业务失败
回滚操作:恢复流量权重并部署上一签名制品
回滚验证:登录、查询、写入、异步任务
负责人和观察人:...

十四、常见失败方式

  • 只按实例数量灰度,但负载均衡没有真正导入流量;
  • 观察 CPU 正常就继续,不检查业务错误和长尾延迟;
  • 新旧版本写入不兼容消息,回滚后无法消费;
  • 数据库迁移与应用全量发布同时进行;
  • 监控查询无数据时被当作“通过”;
  • 发生异常后继续扩大流量,等待更多证据;
  • 发布完成立即删除旧制品和功能开关;
  • 回滚只恢复应用,不验证缓存、队列和定时任务。

十五、上线检查清单

  • [ ] 发布制品可追溯且不可在服务器上临时修改;
  • [ ] 金丝雀与对照组指标能够分开查询;
  • [ ] 定义了阶段、观察时长、硬停止和软暂停条件;
  • [ ] 数据库、消息和 API 具备双向兼容窗口;
  • [ ] 监控无数据不会被误判为成功;
  • [ ] 回滚覆盖应用、配置、流量和数据兼容性;
  • [ ] 发布完成后继续观察一个业务周期;
  • [ ] Feature Flag 有所有者和清理日期;
  • [ ] 发布记录可用于事故复盘和效果改进。

十六、参考资料

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-10-18 22:49:34

results matching ""

    No results matching ""