文章

无指责复盘与故障分析方法论

无指责复盘与故障分析方法论

一句话:无指责复盘(Blameless Postmortem)的核心理念是——每个故障都是系统设计缺陷的暴露,而非个人失误。复盘的产出不是”谁犯了错”,而是”系统哪里缺了防护”。

概述

你的 02-Issues/ 目录有 6 篇实战故障记录(502、MySQL 死锁、Docker 构建、K8s Ingress、cgroup v1/v2、阿里云 NAT),说明你有排查和记录的能力。但从”故障记录”到”系统性复盘”还差一层——需要标准化的复盘模板、根因分析方法论、和 Action Items 闭环跟踪。

故障记录 = 发生了什么 + 怎么修的
无指责复盘 = 为什么发生 + 怎么防止再发生 + 谁来落实 + 什么时候验证

无指责原则

核心理念

原则含义违反的例子
对事不对人分析系统漏洞,不追究个人责任❌ “张三改错了配置” → ✅ “变更流程缺少配置校验”
假设善意当事人在当时的上下文下做了合理决策❌ “为什么不测试就上线” → ✅ “当时的测试环境不具备复现条件”
关注改进每个发现都要转化为可执行的改进措施❌ “以后注意” → ✅ “CI 增加 XX 校验,owner: 李四,due: 8/10”
欢迎所有人任何人都可以参与复盘,不受层级限制避免”领导说了算”
公开透明复盘文档全员可见,不藏着掖着存到公共知识库,不存个人文件夹

为什么”无指责”有效

指责文化:
  故障 → 找人背锅 → 当事人下次隐瞒故障 → 问题无法暴露 → 更大故障

无指责文化:
  故障 → 找系统漏洞 → 改进系统防护 → 当事人下次主动报告 → 问题被消灭在早期

Google SRE 的经验:无指责文化让 MTTR 显著降低——因为人们不再害怕被惩罚,故障发现更早、报告更快、复盘更深入。

复盘模板

标准模板

# Postmortem: [故障标题]

## 基本信息

| 字段 | 内容 |
|------|------|
| 故障 ID | INC-2026-XXX |
| 严重程度 | SEV1 / SEV2 / SEV3 |
| 开始时间 | 2026-08-XX HH:MM |
| 恢复时间 | 2026-08-XX HH:MM |
| 持续时间 | XX 分钟 |
| 影响范围 | [受影响的服务/用户数/业务] |
| 故障作者 | [复盘撰写人] |
| 复审人 | [技术负责人] |

## 摘要(一段话)

[一句话描述故障:什么时间、什么服务、出了什么问题、影响什么、持续多久、怎么恢复的]

## 影响评估

- 用户影响:[受影响用户数 / 请求失败数 / 业务损失]
- 服务影响:[SLI 违反情况 / SLO 预算消耗]
- 数据影响:[是否有数据丢失 / 数据不一致]
- 上下游影响:[级联故障情况]

## 时间线

| 时间 | 事件 | 来源 |
|------|------|------|
| HH:MM | [事件描述] | [信息来源] |

## 根因分析

### 直接原因(触发原因)
[直接导致故障的操作/事件]

### 根本原因(系统原因)
[用 5-Whys 或故障树分析的结论,可参考 [[根因定位方法论]]]

### 根因列表
1. [根因 1]
2. [根因 2]
3. [根因 3]

## 修复过程

### 缓解措施(短期)
[故障发生时做了什么来恢复服务]

### 根治措施(长期)
[针对根因的长期改进]

## Action Items

| ID | 类型 | 描述 | Owner | Due Date | 优先级 | 状态 |
|----|------|------|-------|----------|--------|------|
| AI-001 | 短期修复 | [描述] | [] | [日期] | P1 | Open |
| AI-002 | 长期改进 | [描述] | [] | [日期] | P1 | Open |
| AI-003 | 流程改进 | [描述] | [] | [日期] | P2 | Open |

## 经验教训

- [做对了什么]
- [做错了什么]
- [运气成分(碰巧了)]
- [下次怎么做得更好]

## 附录

- [监控截图]
- [日志片段]
- [变更记录链接]
- [相关工单链接]

5-Whys 实战

示例:MySQL 连接数超限

现象:MySQL 连接数超限,应用大面积超时

Why 1: 为什么连接数超限?
→ 应用创建了过多数据库连接

Why 2: 为什么应用创建了过多连接?
→ 连接池配置 max_open_conns=200,实际实例数 × 200 超过 MySQL max_connections

Why 3: 为什么连接池配置没有和 MySQL 容量对齐?
→ 扩容时只扩了应用实例,没评估 DB 连接数

Why 4: 为什么扩容流程没评估 DB 容量?
→ 扩容 checklist 中没有 DB 连接数检查项

Why 5: 为什么没有这个检查项?
→ 容量规划流程缺少依赖服务容量评估环节

根因:
  1. 扩容 checklist 缺少 DB 连接数检查(流程缺陷)
  2. 连接池配置未和 MySQL max_connections 做容量对齐(架构缺陷)
  3. 缺少连接数预警告警(监控缺陷)

Action Items:
  AI-001: 扩容 checklist 新增 DB 连接数检查项 [Owner: XX] [Due: 8/10] [P1]
  AI-002: 连接池配置改为从配置中心动态读取,按实例数自适应 [Owner: XX] [Due: 8/15] [P1]
  AI-003: 增加连接数 > 80% 预警告警 [Owner: XX] [Due: 8/08] [P1]

鱼骨图分析

核心思路

将可能的根因按维度分类,从多个角度系统排查。

graph LR
    EFFECT[连接数超限] --> PEOPLE[人员]
    EFFECT --> PROCESS[流程]
    EFFECT --> TECH[技术]
    EFFECT --> ENV[环境]
    
    PEOPLE --> P1[扩容未评估 DB 容量]
    PEOPLE --> P2[对连接池配置理解不足]
    
    PROCESS --> PR1[无容量对齐流程]
    PROCESS --> PR2[扩容 checklist 缺失]
    PROCESS --> PR3[变更评审走过场]
    
    TECH --> T1[连接池硬编码]
    TECH --> T2[无连接数告警]
    TECH --> T3[MySQL max_connections 未优化]
    
    ENV --> E1[业务量突增]
    ENV --> E2[实例数翻倍]

鱼骨图维度(6M 法)

维度全称检查方向
Man人员认知不足、培训不够、沟通不畅
Method方法/流程流程缺失、流程不合理、评审走过场
Machine技术/工具工具缺陷、配置不当、架构不合理
Material材料/数据数据质量、依赖版本、配置内容
Measurement度量监控缺失、告警阈值不当、指标定义错误
Environment环境流量突增、基础设施变更、外部依赖变化

Action Items 闭环

闭环流程

graph LR
    POST[复盘产出 AI] --> ASSIGN[分配 Owner + Due]
    ASSIGN --> TRACK[跟踪执行]
    TRACK --> VERIFY[验证落地]
    VERIFY -->|有效| CLOSE[关闭 AI]
    VERIFY -->|无效| POST
    CLOSE --> REVIEW[定期回顾]
    REVIEW -->|同类故障减少?| YES[成功]
    REVIEW -->|同类故障仍发生?| POST

AI 跟踪规范

from dataclasses import dataclass
from enum import Enum
import datetime

class AIPriority(Enum):
    P1 = "P1"  # 紧急,1 周内完成
    P2 = "P2"  # 重要,2 周内完成
    P3 = "P3"  # 一般,1 个月内完成

class AIType(Enum):
    IMMEDIATE = "短期修复"    # 直接修复故障的直接原因
    ARCHITECTURE = "架构改进" # 从架构层面防止同类故障
    PROCESS = "流程改进"      # 改进流程/规范/checklist
    MONITORING = "监控改进"   # 增加监控/告警/看板
    TOOLING = "工具改进"      # 开发工具/自动化

class AIStatus(Enum):
    OPEN = "Open"
    IN_PROGRESS = "In Progress"
    DONE = "Done"
    VERIFIED = "Verified"
    WONT_FIX = "Won't Fix"

@dataclass
class ActionItem:
    id: str
    type: AIType
    description: str
    owner: str
    due_date: datetime.date
    priority: AIPriority
    status: AIStatus = AIStatus.OPEN
    created_at: datetime.datetime = None
    verified_at: datetime.datetime = None
    verification_note: str = ""
    
    def is_overdue(self) -> bool:
        return datetime.date.today() > self.due_date and self.status != AIStatus.DONE
    
    def needs_verification(self) -> bool:
        return self.status == AIStatus.DONE and self.verified_at is None

AI 审查节奏

频率审查内容参与人
每日站会到期 AI 进度AI Owner
每周 SRE 例会所有 Open AI 状态SRE 团队
每月回顾AI 关闭率 + 验证有效率 + 同类故障趋势SRE + 开发
每季度AI 覆盖分析(哪些根因类型没有 AI)技术负责人

复盘分级

级别触发条件参与范围深度产出
轻量复盘SEV3 / Near-Miss当事人 + 直属同事10 行时间线 + 3 个 AI记录在工单
标准复盘SEV2当事团队 + SRE完整模板 + 5-WhysPostmortem 文档
深度复盘SEV1 / 跨团队多团队 + 技术委员会完整模板 + FTA + 鱼骨图全员分享

与现有 02-Issues 的联动

你已有的 6 篇故障记录可以回溯套用本模板:

现有笔记建议回溯练习
502排查总结补充 5-Whys 根因分析 + Action Items
MySQL 连接数超限与死锁排查实战补充鱼骨图分析 + 扩容 checklist 改进
老Docker构建Bookworm报NO_PUBKEY与内存错误补充 CI 流程改进 AI
Ingress_reload_失败_health_api-tpa补充配置变更评审流程 AI
K8s 容器启动失败 cgroup v1-v2 不匹配排查实战补充节点准入检查 AI
阿里云NAT网关SNAT入方向流量异常排查补充网络监控覆盖 AI

常见问题 / 坑点

问题原因解决方案
复盘变甩锅大会文化问题 + 主持人引导不当指定中立主持人,禁止出现人名,只说角色/流程
AI 永远 Open没有 owner 或 owner 不认账复盘会上当场认领,写进会议纪要
复盘写完就归档没有跟踪和验证机制用工单系统跟踪 AI,定期 review
每次复盘都发现新问题只修了直接原因没修根因强制 5-Whys 到流程/制度层
复盘太长没人看什么都往里塞摘要一段话 + 时间线 + 根因 + AI,细节进附录
同类故障反复发生AI 没落地或落地无效追踪同类故障趋势,无效 AI 重开复盘

关联知识

参考资源

  • Google SRE Book: Postmortem Culture: Learning from Failure
  • Google SRE Workbook: Postmortems
  • blamelesspostmortem.com 模板
  • Etsy 的 Postmortem 实践博客

学习时间

内容日期状态
复盘方法论2026-08-03完成:无指责原则、模板、5-Whys、鱼骨图、AI 闭环
回溯练习待用 02-Issues 素材练习

状态

  • 无指责原则
  • 标准复盘模板
  • 5-Whys 实战
  • 鱼骨图分析
  • Action Items 闭环
  • 复盘分级
  • 回溯练习