第九章 生产级硬化
9.4 灰度发布与回滚
承前:可观测性让你"看得见",灰度发布让你"错得起"。上线那一刻不是风险结束,是风险最集中的一刻——新版本的真实表现只有生产流量能检验。这一节讲怎么把"全量一把梭"变成"按比例、分组、分模块的渐进放量",以及出事之后怎么快速退回来:代码回滚、数据回滚、配置回滚,三条退路都要提前修好。
9.4.1 为什么 AI 应用更需要灰度
传统软件的发布风险是"新代码有 bug"——可测试、可预判。AI 应用发布多两类独有的风险:行为漂移(模型更新、prompt 调整导致大面积输出风格/质量变化,单测抓不到)和成本突变(某次改动让 token 消耗翻倍,功能上一切正常,账单爆炸)。这两类风险的共同点是:**只有真实流量才能暴露,且暴露有延迟。**灰度发布就是为"延迟暴露的风险"设计的:先让一小部分流量用新版本,观察期过了再放量。
9.4.2 灰度的三个切分维度
按用户比例。最基础的形态:新版本先接 1%→5%→25%→100% 的流量,每步之间设观察期与指标门禁。云原生的 Argo Rollouts、Flagger 这类工具支持"百分比金丝雀 + 指标分析 + 自动回退"的完整闭环;不上 K8s 的团队用网关权重或功能开关(feature flag)也能实现。门禁指标就来自 9.3 的大盘:灰度组 vs 基线组的采纳率、兑现率、P95 延迟、拦截率、单次成本——任一指标显著劣化,放量自动停止。
按分组。比例是随机的,分组是选择的。青禾上执行通道时(8.3 沙盘),先开放的 10 家门店就是分组灰度——选组的标准是有讲究的:选数字化程度高的门店(反馈质量好),同时包含 1-2 家"困难门店"(老系统、双轨 ID 问题重的那批),**只选好门店的灰度是自我欺骗,等于只把考试题换成自己会的。**分组维度还可以是用户角色(先督导后店员)、地域(先非一线城市)、模块(先唤回场景后补偿场景)。
按模块。AI 应用特有的维度:系统由多个能力模块组成(检索、推理、护栏、执行),可以单独灰度某一个。典型用法:模型升级时只切推理模块(A/B 两个模型版本跑同一流量,对比输出质量),检索策略调整时只切检索层。模块化灰度的前提是 9.5/9.6 会讲的模型抽象层与配置化架构——能被独立切换的东西才能被独立灰度。
灰度放量节奏(示意)
1% ──→ 5% ──→ 25% ──→ 50% ──→ 100%
│ │ │ │
观察期 观察期 观察期 观察期
24h 48h 72h 72h
门禁:采纳率差 < 2pt, 延迟差 < 10%, 成本差 < 5%
│
└─ 指标劣化 → 权重归零,自动回退(分钟级)9.4.3 回滚的三条退路
灰度解决"少错",回滚解决"错了之后"。三条退路必须在上线前各自演练一次,没演练过的回滚方案等于没有。
代码回滚。重新部署上一个版本。AI 应用要注意版本不只是你的代码:模型版本、prompt 版本、护栏配置版本要跟着代码版本一起被管理。9.1 沙盘里"模型升级后采纳率跌 4 个点"的事故,回滚动作是把推理配置里的模型版本号改回去——因为 9.3 的日志记了版本,定位快,因为配置化了模型路由,回退快。建议用语义化版本把"应用代码 + 模型 + prompt + 护栏配置"打包成一个可回滚单元,任何一项变更都是一次"发布"。
数据回滚。最难的一条。AI 应用的数据副作用有两层:一是 Agent 执行动作写进客户业务系统的数据(发出去的券、打上的标签),二是 AI 系统自身的数据(评估集新增 bad case、采纳记录)。后者好办(加版本、可重放),前者要回到 8.2 的可逆性设计:标签这类完全可逆动作,回滚脚本按审计日志反操作;已核销的券这类不可逆副作用,回滚预案是补偿流程而不是数据操作(作废+人工客诉通道+对账),这个流程要提前和客户的运营/客服团队约定,别等事故时现场发明。
配置回滚。AI 应用里最高频的回滚形态:prompt 改坏了、护栏阈值调严了、灰度比例设错了、HITL 分层改了。所以配置变更要走和代码发布一样的纪律:版本化、可一键回到上一版、变更留审计记录。很多团队的 AI 系统事故复盘最后都指向同一句话:"prompt 是昨晚在配置后台里直接改的,没有备份。"——把配置后台当数据库用,而不是当代码发布流程管理,是 AI 运维最常见的反模式。
9.4.4 监控指标与告警阈值:放量决策的裁判
灰度期间,谁是"继续放量还是回退"的裁判?必须是 9.3 建立的指标体系,不是人的感觉。给一套 AI 灰度的最小门禁模板(阈值示例,按项目校准):
| 指标 | 基线 | 门禁 | 触发动作 |
|---|---|---|---|
| 采纳率(7 日滑窗) | 85% | 组间差 > 3pt | 停止放量,人工介入 |
| 兑现率(事后 7 日) | 92% | 组间差 > 2pt | 停止放量 |
| 拒答率 | 8% | 绝对值 > 15% 或 < 2% | 停止放量(幻觉或检索风险) |
| P95 延迟 | 2.4s | 超 1.5× | 停止放量 |
| 单次对话 token 成本 | ¥0.03 | 超 1.3× | 停止放量(成本突变) |
| 输出拦截率 | 3% | 突增 > 3× | 停止放量(攻击或误报) |
注意"停止放量"和"自动回退"是两档:门禁触发先停,人来看了再决定回退还是修了继续——全自动回退留给明确灾难信号(错误率、延迟熔断),语义指标让人做终审,因为语义指标的劣化原因需要人判断(可能恰恰是新版本更严格地拒绝了不该发的券,拦截率涨是好事)。
9.4.5 沙盘:青禾执行通道的上线夜
把本节机制串成沙盘。青禾执行通道正式上线的当夜:
- 22:00 新版本部署完成,灰度比例 5%(5 家门店,含一家"困难门店");
- 22:00-24:00 观察期:大盘盯 6 项门禁指标。23:10 拦截率从 3% 跳到 11%——门禁自动停止放量,值班 FDE 拉起 trace 采样发现是发券 reason 字段太长触发新护栏的长度规则,误报,调整阈值(配置回滚到上一版护栏配置 + 热更新规则),拦截率回落 4%;
- 次日人工复核后放量到 25%;
- 三天后 25% 档兑现率正常,一路放到 100%,全程零客诉。
这次上线之所以平淡,是因为每一个异常(拦截率突跳)都有:trace 能定位(9.3)、配置能秒回滚(本节)、放量有门禁挡着(本节)、事后有人工终审(HITL 分层的运维版)。生产级硬化的目的不是消灭事故,是把事故的粒度压到"一个配置项、一次观察期"的大小。
9.4.6 回滚演练:上线前的"消防演习"
三条退路"各自演练一次"怎么演?给一个 60-90 分钟的演练脚本,上线评审会上把演练记录当证据物提交:
演练剧本(上线前一周,生产环境照常运行)
T+0 注入故障:把灰度组 prompt 切到"故意写坏的版本"(建议话术混乱版)
T+2m 门禁触发:采纳率组间差 > 3pt → 自动停止放量(验证告警链路)
T+5m 值班执行:①配置回滚——prompt 库一键回到 v1.4(验证配置回滚 < 1 分钟)
T+8m ②代码回滚——触发发布系统回退上一应用版本(验证发布单元完整性:
代码+模型+prompt+护栏配置是否真的打包可回退)
T+15m ③数据回滚——沙盘一笔测试发券,走审计日志反操作脚本作废(验证
可逆动作的反操作链路);再沙盘一张"已核销券",走补偿流程工单
T+30m 复盘:记录每步耗时、断点、谁签字演练暴露的问题通常集中在三处:配置回滚快但护栏配置忘了进版本管理(回滚了 prompt、护栏还是新的,误报继续);数据反操作脚本从没在生产权限下跑过(数据库只读账号,脚本失败);补偿流程没有责任人(券作废了,客诉没人接)。都是 10 分钟就能修的洞,不演练就留到真实事故里修。
演练还有一个组织价值:客户侧值班人(IT 负责人指派的运维对接人)一起参加,TA 亲眼看到"5 分钟回退",比任何 SLA 条款都更能建立对系统的信心。这也是 9.7 运营交接的一部分——回滚操作手册不能只在你团队脑子里,要落在客户能执行的文档上。
9.4.7 发布纪律:把"每次变更"变成"每次发布"
回滚演练背后还有一个更根本的机制——发布纪律。AI 系统里"变更"的形态比传统软件多得多:代码、模型版本、prompt、护栏阈值、灰度比例、HITL 分层,任何一项都可能昨晚被某个人顺手改了。统一的原则是:凡影响生产行为的变更,一律走同一条发布管线:
变更请求(谁提的、改什么、为什么)
→ 变更评审(影响面: 行为? 成本? 安全? 自动分类打标)
→ 版本化打包(应用代码+模型+prompt+护栏配置为一个发布单元)
→ 灰度上线(按影响等级走 9.4.2 的比例/分组/模块)
→ 观察期与门禁
→ 归档(变更记录进审计日志)一个自检问题判断你的项目有没有发布纪律:"昨晚到现在,生产系统的 prompt 被谁改过、改了什么?"——如果答不出来,说明变更没有版本化;如果答案是"某人直接在后台改的",说明没有发布管线。这两者都是等着出事的形态,而且出事时你连"改回什么"都不知道。
变更分级也要做:低影响(告警阈值微调)走快速通道,当天生效;高影响(换模型、改护栏规则、调 HITL 分层)必须走完整评审 + 灰度。分级标准提前和客户 IT 约定并写进运维手册——否则每次小改都开评审会,两周后大家就开始绕过流程了。纪律的敌人不是混乱,是过重的流程逼人绕路——分级就是让纪律可持续的泄压阀。
9.4.8 要点总结
- AI 发布有传统软件没有的两类风险:行为漂移与成本突变,都靠真实流量才暴露——灰度是唯一对策。
- 三个灰度维度:用户比例(配门禁自动停)、分组(故意包含困难样本)、模块(模型/检索/护栏独立切换,前提是架构可切换)。
- 三条回滚退路提前修好并演练:代码(代码+模型+prompt+护栏配置打包成一个发布单元)、数据(可逆动作按审计日志反操作,不可逆副作用走补偿流程)、配置(配置变更走发布纪律,别把配置后台当数据库)。
- 门禁表 6 项指标做裁判;"停止放量"和"自动回退"分两档,语义劣化由人终审。
- 上线的目标不是零事故,是把事故粒度压到配置项级别。
参考资料
- Progressive Delivery: Canary, Blue-Green, and Feature Flags — System Design Space — 灰度/金丝雀/功能开关的系统化综述,含 Argo Rollouts、Flagger 的自动化回退机制。
- Feature Toggles (Feature Flags) — Martin Fowler — Martin Fowler 官方文章,功能开关的四类分类与生命周期管理,配置化灰度的理论底座。
- Argo Rollouts — Progressive Delivery for Kubernetes — 开源渐进式交付控制器文档,setWeight 分步放量与指标分析自动回退。
- OWASP Top 10 for LLM Applications — OWASP 清单,LLM09 不实信息等风险的上线前验证要求,支撑门禁指标设计。