事故复盘(Postmortem)

指导 Agent 用时间线、影响指标、根因分析与改进行动填满复盘文档:坚持无指责文化,用五问法追问系统性因素而非个人;行动项可验收、可跟踪。

摘要段含开始/恢复时间、受影响用户或交易占比、是否数据损坏;敏感细节脱敏后仍可支撑内部学习。

根因区分直接原因与系统性因素(监控盲区、发布流程、容量规划);五问法内嵌为可验证链条,避免「问了五句空话」。

行动项须可跟踪:负责人、截止日期、验证方式;与已有工单或 epic 互链,防止复盘后石沉大海。

无指责原则(Blameless)

聚焦系统与流程

文档描述「什么机制失效」:告警是否迟到、Runbook 是否缺失、审批是否成瓶颈。不将根因写成某人「粗心」;若涉及人为操作,写清培训、工具或检查单缺口。

心理安全与责任

鼓励完整时间线与诚实记录;责任人用于行动项 owner推进改进,而非问责清单。对外沟通口径与内部学习材料可分层脱敏。

  • 检测:为何未能更早告警或自动缓解——从信号、阈值、on-call 路由追问。
  • 响应:升级路径是否顺畅;决策延迟是否因信息不全或权限不清。
  • 沟通:内外公告时间点与措辞是否恰当;是否避免指责性用语。

完整事故复盘文档模板(Markdown,可直接用于 Confluence / Notion):

# 事故复盘:[服务名] [简短描述]
**事故 ID**: INC-2024-0315
**严重等级**: P1
**起止时间**: 2024-03-15 14:02 UTC — 2024-03-15 16:48 UTC(2h 46min)
**撰写人**: @on-call-engineer
**复盘会议**: 2024-03-17 10:00 UTC

## 摘要
支付服务错误率在 14:02 突增至 12%,持续 2h46min,影响约 8% 的结账请求。
无数据损坏,所有失败请求均已向用户返回明确错误信息。

## 事故严重等级定义
| 等级 | 标准 |
|------|------|
| P0 | 核心服务全量不可用,影响 >50% 用户,无变通 |
| P1 | 核心路径严重降级,影响 >20% 用户,SLO 违约 |
| P2 | 局部功能受损,有变通,SLO 未违约 |
| P3 | 体验下降,无用户可见错误 |

## 时间线(UTC)
| 时间 | 事件 |
|------|------|
| 13:45 | 部署 payment-svc v2.4.1 至生产(滚动发布) |
| 14:02 | 错误率告警触发(阈值 >1% 持续 5min) |
| 14:08 | on-call 认领,开始排查 |
| 14:25 | 确认与新版本相关,决定回滚 |
| 14:35 | 回滚完成,错误率开始下降 |
| 14:48 | 错误率恢复正常,告警解除 |

## 影响评估
- 影响用户:~8% 的结账请求失败(约 2,400 笔交易)
- SLI 影响:成功率从 99.95% 降至 88%,违反 99.9% SLO
- 数据完整性:无数据损坏,幂等性设计保证无重复扣款

## 根因分析(见下方五问法)
**直接原因**:v2.4.1 引入的数据库连接池配置错误导致连接耗尽

## 行动项
见下方 SMART 格式

若组织仍需合规调查,与无指责复盘流程分离:复盘产学习,调查走独立通道,避免混写进同一份对外稿。

五问法(Five Whys)

可观察现象出发,每一层「为什么」应对应可核对的证据(日志、配置、变更记录、监控截图)。若某一问出现多个并列原因,分支记录或先收敛主路径再补「并列因素」小节。

真实事故案例:支付服务连接池耗尽,完整走完 5 步:

## 五问法根因分析

**现象(起点)**
支付 API 错误率在 14:02 突增至 12%,日志显示 "connection pool exhausted"

**Why 1**: 为什么连接池耗尽?
→ 数据库连接池 max_size 从 50 被错误设置为 5
  证据:`kubectl get configmap payment-db-config -o yaml | grep max_pool_size` → 输出 5
  变更记录:v2.4.1 PR #892 修改了 db_config.yaml

**Why 2**: 为什么配置错误未被发现?
→ PR 审查通过了,但 CI 没有对连接池参数做范围检查
  证据:CI 流水线日志显示 config validation 步骤跳过了 pool 参数验证

**Why 3**: 为什么 CI 没有验证连接池参数?
→ 配置校验脚本只检查必填字段,没有检查数值合理范围
  证据:scripts/validate-config.sh 中 max_pool_size 仅检查 is_set,未检查 >=10

**Why 4**: 为什么校验脚本不检查数值范围?
→ 该脚本最初只为检查必填字段,从未更新以覆盖业务约束
  证据:git log scripts/validate-config.sh 显示最后修改是 18 个月前

**Why 5**: 为什么配置变更没有 staging 环境的压测门禁?
→ 连接池配置被归类为"低风险变更",豁免了 staging 验证
  证据:发布策略文档中 db_config.yaml 变更级别标记为 "minor"

**系统性贡献因素**:
1. 配置参数缺少范围约束的自动化验证
2. 变更风险分类规则过于粗粒度
3. 连接池耗尽告警阈值(>1% 持续 5min)过于保守,应提前检测
  • 避免循环论证:下一问应比上一问更靠近系统设计或流程,而非同义反复。
  • 第五问左右宜落到可改项:监控、SLO、发布门禁、容量模型、文档或培训。
  • 与「直接原因」区分:直接原因往往是触发事件;五问链用于暴露贡献因素与防御层失效。

复盘主流程(skill-flow-block)

  [ 检测:告警 / 用户报告 / 内部发现 ]
        │
        ▼
  ┌─────────────┐     止血优先:限流、回滚、开关、隔离坏实例
  │ 稳定与缓解  │──── 记录:时间戳、操作者、命令或工单链接
  └─────────────┘
        │
        ▼
  ┌─────────────┐     UTC + 本地时区;关键决策、升级、对外公告
  │ 时间线      │──── 变更、部署、配置、依赖方事件对齐到同一时间轴
  └─────────────┘
        │
        ▼
  ┌─────────────┐     影响:用户/交易比例、SLI、数据完整性
  │ 影响评估    │──── 无指责措辞:失效模式与检测缺口
  └─────────────┘
        │
        ▼
  ┌─────────────┐     直接原因 + 五问链 → 系统性贡献因素
  │ 根因分析    │──── 区分「触发」与「为何未更早发现/未自动恢复」
  └─────────────┘
        │
        ▼
  ┌─────────────┐     owner / due / 验收标准 / 工单链接
  │ 行动项      │──── 预防复发 + 缩短检测/恢复时间(可选优先级)
  └─────────────┘
        │
        ▼
  ┌─────────────┐     内部分享;敏感细节脱敏;可选对外摘要
  │ 传播学习    │
  └─────────────┘

行动项与跟踪

每条行动对应「如何证明做完」:合并 PR、监控面板更新、Runbook 修订编号、演练通过记录。Agent 起草时应显式写「无 owner 则标 TBD + 建议角色」,避免悬空句。

SMART 格式行动项示例(对应上方事故):

## 行动项(SMART 格式)

### 短期(1周内)
| # | 行动 | 负责人 | 截止日 | 验收标准 | 工单 |
|---|------|--------|--------|----------|------|
| 1 | 为 max_pool_size 添加范围校验(≥10)到 CI | @backend-dev | 2024-03-22 | CI 对 max_pool_size<10 的配置返回非零退出码 | #1456 |
| 2 | 修订发布策略:db_config 变更升级为"中风险"需 staging 验证 | @release-eng | 2024-03-22 | 策略文档 PR 合并,release captain 确认知悉 | #1457 |

### 中期(1个月内)
| # | 行动 | 负责人 | 截止日 | 验收标准 | 工单 |
|---|------|--------|--------|----------|------|
| 3 | 添加连接池使用率告警(>80% 持续 2min → warning) | @sre-team | 2024-04-15 | Grafana 面板中可见,测试告警触发并通知 on-call | #1460 |
| 4 | 为所有 DB 配置参数补充 JSON Schema 校验规则 | @platform | 2024-04-15 | schema 文件 PR 合并,CI 集成通过 | #1461 |

### 未决问题(需进一步讨论)
- 是否引入 canary 发布对连接池耗尽的快速检测?(下次架构评审讨论)
- staging 环境是否配置足够的连接压测负载?(@infra 评估)
  • 与 epic / 工单互链;复盘会议结论与评论引用同一 ID。
  • 设复查日期:短期修复与长期结构性改进分栏。
  • 模板底部保留「未决问题」列表,防止口头结论丢失。

复盘会议 Facilitation 指南:

# 复盘会议引导规则

## 角色分工
- 主持人(Facilitator):控制节奏,确保讨论聚焦系统而非个人
- 记录人(Scribe):实时记录时间线、根因、行动项
- 技术 Lead:补充技术细节,不主导结论
- 所有参与者:对事不对人,鼓励诚实表达

## 会议结构(60min 为例)
- 0-5min:  主持人声明"无指责"基调与会议目标
- 5-15min: 共同确认时间线(不辩论,只补充)
- 15-30min: 影响评估与数据确认
- 30-45min: 五问法走完根因链(主持人控制深度)
- 45-58min: 起草行动项,每条确认 owner 与截止日
- 58-60min: 总结,约定复盘文档发布时间

## 禁止用语(主持人介入)
- "是你的错" / "你不应该" → 改为"该流程/工具如何改进"
- "总是这样" / "从来不" → 基于本次事实,不泛化
- "很简单,就是..." → 避免事后诸葛亮效应

五问链草稿器

填写现象与连续五个「为什么」,生成可粘贴进复盘稿的 Markdown 片段;用于 war room 后快速整理,再与证据交叉核对。

五个连续的为什么输入框

空行会自动跳过;生成后请用日志与变更记录验证每一层,避免臆造链条。可与上方「无指责原则」对照:措辞描述机制失效,不指向个人道德评判。

---
name: incident-postmortem
description: 从时间线与日志起草无指责复盘稿
model: claude-sonnet-4-5
---

# 复盘文档必含章节
sections:
  - 摘要(时间窗口、影响用户比例、是否数据损坏)
  - 事故等级(P0/P1/P2/P3 定义与本次判定)
  - 时间线(UTC,含部署/配置变更节点)
  - 影响评估(SLI 数据、用户/交易比例)
  - 根因分析(直接原因 + 五问链 + 系统因素)
  - 行动项(SMART 格式:owner/due/验收标准/工单)
  - 未决问题

# 无指责写作规则
blameless_rules:
  - 描述机制失效,不指向个人过失
  - 人为操作 → 分析培训/工具/检查单缺口
  - 行动项 owner 推进改进,非问责

# 五问法要求
five_whys:
  - 每问附可核查证据(日志/配置/变更记录)
  - 第五问落到可改项(监控/流程/文档)
  - 避免循环论证和同义反复

返回技能库 更多技能入口