KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

05 · 发布闭环:上线后的十分钟才是真正的考试 — keel 龙骨

这一章回答:点下发布按钮之后到底该盯什么、盯多久、什么情况立刻回滚。答案是"上线前 checks → 上线后冒烟 → 观测窗口 → 明确回滚"。

这一章回答:点下发布按钮之后到底该盯什么、盯多久、什么情况立刻回滚。答案是"上线前 checks → 上线后冒烟 → 观测窗口 → 明确回滚"。

绝大多数事故不是"没发布成功",而是"发布成功了但悄悄坏了半小时"。这一章给出可复制的发布前后检查清单。

一、上线前:把能提前发现的问题提前说完

□ 产物         版本号明确、digest 明确、来源 commit 明确
□ 门禁         所需检查全绿(不是"除了那个 flaky 的")
□ 变更范围     这次上线包含哪些 PR / 哪些改动(能说得出来)
□ 迁移         有没有 DB 迁移?是不是只做 expand 部分?有没有分批?
□ 配置         新增的环境变量已在目标环境就位(不是"上线时顺手加上")
□ 开关         新功能是否包在开关里?默认状态是什么?
□ 回滚         回滚命令/按钮在哪?旧版本号是什么?有迁移时怎么退?
□ 时机         是否避开业务高峰/大促/别人也在上线的窗口?
□ 人           谁负责盯、盯多久、谁有权决定回滚

最后两条经常被忽略,但它们是人为事故率最高的部分:发布窗口要避开别人(多个团队同时变更 = 故障归因变难),发布必须有人盯("发完就下班"是所有温水事故的起点)。

二、上线后冒烟:三分钟内能做完的检查

冒烟的逻辑是:先验证"系统活着",再验证"核心路径通",最后看指标。

第 0 分钟   健康检查通过?实例数回到预期?有没有 CrashLoop?
第 1 分钟   核心路径手动走一遍(登录 → 主流程 → 关键写操作)
第 3 分钟   看四条曲线:请求量、错误率、延迟 P99、资源使用(CPU/内存/连接)
检查项 具体动作 判据
实例健康 实例数 / restarts 计数 无重启、无 CrashLoop、数量回到目标值
版本正确 服务端暴露版本号接口 返回的正是刚发布的版本(这一步能防止"发了个寂寞")
核心路径 手动或自动化跑一次主流程 成功且结果正确
关键指标 错误率、延迟 P99、依赖调用成功率 与发布前基线相比在波动范围内

"版本正确"这一项最容易被跳过,但它揪出的问题比例不低:缓存导致部署没生效、镜像 tag 指错了、产物内容不是你以为的那个 commit。

三、观测四件套:盯什么、为什么是这四个

类型 回答的问题 最小内容
Metrics(指标) 现在还好吗?趋势在往哪走? 请求量、错误率、延迟分布(不是平均值)、饱和度(连接/队列/CPU)
Logs(日志) 具体发生了什么? 结构化日志 + trace_id + 版本字段
Traces(链路) 慢在哪一环? 关键路径埋点,能按版本过滤
Alerts(告警) 什么时候叫醒人? 基于症状(错误率/延迟)而非原因(CPU);每条告警都要有处置动作

两个通用纪律:

另外:延迟看 P99/P95,不看平均值。 平均值会被大量快请求拉平,用户的糟糕体验藏在长尾里——这也是为什么 SLO 通常写"P99 < 300ms"而不是"平均 < 100ms"。

四、发布窗口:盯多久算够

观察时长 ≥ max( 指标收敛时间, 一个完整业务周期, 慢任务最长耗时 )

五、回滚触发条件:把"判断"提前翻译成"数字"

立即回滚(不需要讨论):
  · 核心路径成功率跌破基线 2 个百分点以上,持续 ≥ 3 分钟
  · P99 延迟涨到基线的 2 倍以上且未回落
  · 出现发布前不存在的新错误类型,且量级在上升
  · 数据正确性受损(哪怕量很小)
继续观察(但准备回滚):
  · 指标在阈值边缘抖动
  · 影响范围仅限非核心路径
  · 已经定位到原因,且修复时间小于回滚时间

"这条该不该回滚"的讨论,一定要发生在事故之前。 线上争论三分钟,就是在让用户承担三分钟的风险。

六、发布后的收尾:最容易被漏掉,也最容易埋雷

动作 为什么
更新发布记录(版本/时间/人/变更范围) 未来排查时第一个要看的东西
清理临时开关(feature flag 债) 开关堆积是长期的复杂度债(有些团队会专门做"开关清理"的工作流)
补一条发布后校验到流水线 让下一次发布自动做这次手动做的事
复盘数据留档(该次发布的四个指标曲线) 后来的人能知道"当时发生了什么"
若回滚过,补一个 RCA(根因分析) 复盘的目的是让下一次错误更早被流水线挡住

动手:可观察结果

动作 产出物 判断标准
写一份本项目的检查清单 一页 checklist 清单能贴在 PR 模板里,新同事照做不遗漏
给版本暴露一个端点 /version 或等价指标 发布后能立刻确认线上的确实是新版本
给日志加版本与 trace 字段 日志样例 发布期间的报错能按版本筛出来
定义回滚阈值 一份数字化的触发条件 任意两个人看同一张图能得出相同结论
做完一次完整的发布 + 观察 + 收尾 一次记录 三步都留档,下次可复盘

故障注入

注入方式 观察什么 说明的现象
发布后只看健康检查 是否能发现业务级错误 健康检查通过但核心路径已坏——最常见的一类事故
故意发布带 bug 的版本(限演练环境) 多久被检测到 这个时长就是你的实际 MTTR 下限
去掉日志里的版本字段 发布期故障能否定位版本 不能 → 只能"全量回滚"这种昂贵判断
把告警阈值改成 CPU > 30% 团队反应 噪声告警会让所有人开始屏蔽它
异步任务发布后不看 是否漏掉失败 定时任务要等下次触发才炸,往往是隔夜事故

自测题

  1. 为什么"确认线上版本正确"这一项要单独作为发布后检查?
  2. 观测四件套各自的职责是什么?为什么告警要基于症状而不是基于原因?
  3. 发布后的观察时长由哪三个时间量的最大值决定?
  4. 回滚触发条件为什么要在事故之前就定好?
  5. 为什么说"延迟要看 P99 而不是平均值"?

进入 keel 阅读