首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >事故复盘不是写检讨,而是让团队变强的一次机会

事故复盘不是写检讨,而是让团队变强的一次机会

原创
作者头像
Echo_Wish
发布2026-09-15 08:11:06
发布2026-09-15 08:11:06
580
举报

事故复盘不是写检讨,而是让团队变强的一次机会

凌晨 2 点,监控突然开始报警。

接口 P99 从 200ms 飙到 5s,错误率一路上涨。值班同学冲进群里,开始查日志、重启服务、扩容、回滚。

两个小时后,服务终于恢复。

第二天上午,大家坐在会议室里开事故复盘。

然后有人问:

“这次事故到底是谁改的?”

如果复盘最后变成了这句话,那我觉得这次事故基本算白出了。

真正成熟的运维团队,应该慢慢完成一个转变:

从“事故发生了以后怎么解释”,走向“事故发生以后组织怎么变强”。

这也是我越来越认同的一件事情:

Postmortem 的终点,不应该是一份复盘文档,而应该是一次组织学习的开始。


一、很多公司的事故复盘,其实只是“事故作文”

我见过一些非常典型的事故复盘。

标题:

《XX系统 9月15日生产事故复盘报告》

内容大概是:

事故时间: 02:13

事故恢复: 03:47

事故影响: XX用户

事故原因: 某同学发布配置错误

处理方式: 回滚

责任人: XXX

整改措施: 加强发布审核

看起来特别完整。

但是过了三个月,同样的事故又发生了。

只是这次换了个人。

为什么?

因为这种复盘回答的是:

“上一次是谁做错了?”

而不是:

“为什么一个正常工作的工程师,能够这么容易把系统搞挂?”

这两个问题看起来差不多,实际上完全不同。


二、真正应该复盘的,不是“谁犯错”,而是“系统为什么允许错误发生”

假设生产环境有这样一条命令:

代码语言:bash
复制
kubectl delete deployment payment-service -n prod

一个新人拿到了生产权限。

凌晨三点,他本来想删除测试环境 Deployment,结果 namespace 写错了。

系统挂了。

如果你的复盘结论是:

“新人操作失误,生产操作不规范。”

那你下一步大概率会做:

代码语言:txt
复制
加强培训
加强教育
加强审批
加强责任意识

听起来都对。

但其实没有解决核心问题。

因为真正值得问的是:

为什么一个人的一个命令,就能让生产系统直接进入不可用状态?

成熟一点的改进可能是:

代码语言:txt
复制
生产环境禁止直接 kubectl delete
        ↓
必须通过发布平台操作
        ↓
平台识别生产环境
        ↓
高危操作二次确认
        ↓
权限最小化
        ↓
操作审计
        ↓
异常行为自动告警

这时候,事故才真正产生了价值。

因为你不是要求:

“以后大家千万别犯错。”

而是让系统变成:

“即使有人犯错,也不至于造成灾难。”

这才是工程思维。


三、Postmortem 最重要的一个词:Blameless

很多人第一次听到 Blameless Postmortem(无责复盘),会产生一个误解:

“无责复盘是不是出了事故也不用追责?”

不是。

Blameless ≠ 不承担责任。

它真正想表达的是:

复盘的时候,不要把人的错误当成分析终点。

比如:

代码语言:python
复制
def deploy(config):
    if config.env == "prod":
        deploy_to_production(config)

这里最大的风险是什么?

不是某个人粗心。

而是:

代码语言:txt
复制
代码允许任何人直接部署生产

那我们真正应该修改的,是系统。

例如:

代码语言:python
复制
def deploy(config, operator):
    if config.env == "prod":
        if not operator.has_permission("prod_deploy"):
            raise PermissionError("没有生产发布权限")

        if not config.approved:
            raise PermissionError("生产发布未审批")

    return deploy_to_environment(config)

再进一步:

代码语言:python
复制
def deploy(config, operator):
    validate_config(config)

    if config.env == "prod":
        check_permission(operator)
        check_approval(config)
        check_change_window(config)
        create_audit_record(operator, config)

    return deploy_to_environment(config)

你会发现:

真正优秀的复盘,最后一定会落到系统、流程、工具和组织机制上。


四、事故不是“坏事”,重复事故才是真正的坏事

我特别喜欢一个判断事故价值的方法:

第一次事故叫问题,第二次同类事故叫管理问题。

比如第一次 Redis 把内存打爆。

大家发现:

代码语言:txt
复制
没有内存告警
没有容量预测
没有淘汰策略
没有压测

然后补上。

半年后,又因为 Redis 内存爆了。

这时候就不能再简单说:

“又一次 Redis 内存事故。”

真正应该问的是:

为什么第一次事故留下的知识,没有进入组织?

这就涉及一个很容易被忽略的问题:

事故复盘 ≠ 组织学习

复盘只是:

代码语言:txt
复制
发生了什么?
为什么发生?
怎么恢复?
以后怎么办?

而组织学习则是:

代码语言:txt
复制
事故
 ↓
知识
 ↓
行动
 ↓
机制
 ↓
标准
 ↓
工具
 ↓
自动化
 ↓
组织能力

这是完全不同的层次。


五、不要只写“整改措施”,要给整改措施加上生命周期

很多 Postmortem 最大的问题,是整改项写得特别漂亮。

例如:

代码语言:txt
复制
1. 增加监控
2. 优化发布流程
3. 加强代码审核
4. 完善应急预案

然后一个月以后:

代码语言:txt
复制
TODO
TODO
TODO
TODO

最后谁都不知道做到什么程度了。

我更推荐把事故 Action Item 做成类似下面这种结构:

代码语言:python
复制
action_items = [
    {
        "problem": "数据库连接池耗尽",
        "action": "增加连接池使用率监控",
        "owner": "张三",
        "priority": "P0",
        "deadline": "2026-09-20",
        "status": "DOING",
        "verify": "模拟连接池耗尽,确认告警5分钟内触发"
    }
]

注意最后那个:

代码语言:txt
复制
verify

非常重要。

因为:

没有验证方式的整改措施,很容易只是“写过了”。

比如:

代码语言:txt
复制
增加数据库监控

不够。

应该变成:

代码语言:txt
复制
数据库连接池 > 80%
    ↓
触发 Warning

数据库连接池 > 95%
    ↓
触发 Critical

模拟连接池耗尽
    ↓
确认告警
    ↓
确认通知
    ↓
确认值班人员收到

这时候,它才从一句话变成真正的工程能力。


六、事故复盘真正应该关注的是“控制点”

举个大家都熟悉的例子。

一次线上发布导致 CPU 100%。

最开始调查发现:

代码语言:txt
复制
某次代码提交引入了死循环

如果到这里就结束了:

“开发写代码不严谨。”

那意义其实不大。

继续往下问:

第一层

为什么有死循环?

代码语言:txt
复制
代码 Bug

第二层

为什么测试没发现?

代码语言:txt
复制
测试场景覆盖不足

第三层

为什么测试场景覆盖不足?

代码语言:txt
复制
没有针对大数据量做测试

第四层

为什么没有大数据量测试?

代码语言:txt
复制
性能测试没有纳入发布门禁

第五层

为什么发布可以绕过性能测试?

代码语言:txt
复制
CI/CD 没有强制检查

你看。

一开始是:

代码语言:txt
复制
一个 Bug

最后变成:

代码语言:txt
复制
CI/CD质量门禁缺失

这就是典型的 从个人错误走向系统性原因


七、真正高级的运维,不是“救火快”,而是“让火越来越少”

传统运维经常有一种英雄主义:

“这个问题只有我能解决。”

凌晨服务器挂了。

某个大佬上线。

代码语言:bash
复制
ssh production
tail -f xxx.log
grep ERROR xxx.log
kill -9 xxx
systemctl restart xxx

然后:

“好了。”

群里:

“牛逼。”

确实牛逼。

但从组织能力角度来看,这其实不一定是好事。

因为如果:

代码语言:txt
复制
只有 A 知道怎么处理

那么组织能力其实是:

代码语言:txt
复制
A = 100
其他人 = 0

真正成熟之后应该变成:

代码语言:txt
复制
A知道
 ↓
A写下来
 ↓
形成Runbook
 ↓
自动化
 ↓
新人也能执行

最终:

代码语言:python
复制
if service_down:
    detect()
    diagnose()
    execute_runbook()
    verify()
    record()

这时候,原来只有一个人会的“绝活”,变成了整个团队的基础能力。


八、我特别建议把事故沉淀成“可执行知识”

很多公司的 Wiki 有几十万字。

但真正出事故的时候,没人看。

为什么?

因为知识写成了:

代码语言:txt
复制
第一章 系统介绍
第二章 架构说明
第三章 网络拓扑
第四章 数据库设计
……

半夜三点的时候,你根本没心情看。

真正有价值的运维知识应该长这样:

代码语言:txt
复制
【现象】
接口 5xx > 10%

【第一步】
检查:
kubectl get pods

【第二步】
查看:
kubectl logs xxx

【第三步】
如果出现:
OOMKilled

【处理】
kubectl rollout restart deployment xxx

【验证】
错误率恢复 < 1%

【升级】
超过10分钟无法恢复,通知DBA

这才叫:

Runbook。

它的价值不是“记录历史”。

而是:

让下一次事故处理得更快。


九、事故还可以反过来喂给监控、测试和AI

这也是我认为未来 AIOps 特别有价值的一点。

一次事故发生:

代码语言:txt
复制
事故
 ↓
日志
 ↓
指标
 ↓
Trace
 ↓
人工判断
 ↓
根因

如果只是写一份 Postmortem:

代码语言:txt
复制
事故结束

就结束了。

但如果继续做:

代码语言:txt
复制
事故
 ↓
提取特征
 ↓
形成规则
 ↓
加入监控
 ↓
加入测试
 ↓
加入知识库
 ↓
AI学习

那事故就开始产生复利。

例如以前:

代码语言:txt
复制
数据库连接数 > 90%

没人特别关注。

发生一次事故以后发现:

代码语言:txt
复制
连接数 > 90%
+
慢SQL增加
+
CPU > 80%
+
请求量持续上涨

是一个非常危险的组合。

那么就可以形成:

代码语言:python
复制
if (
    db_connections > 0.9
    and slow_sql_rate > 0.2
    and cpu_usage > 0.8
):
    alert(
        level="critical",
        message="数据库资源耗尽风险"
    )

下一次事故甚至可能还没发生,系统已经告诉你:

“这个事故正在形成。”

这就是从:

事故响应

走向:

事故预防。


十、最终要建立的是一条“事故 → 能力”的流水线

如果让我给一个真正落地的模型,我会这样设计:

代码语言:txt
复制
                ┌──────────────┐
                │    生产事故   │
                └──────┬───────┘
                       ↓
                ┌──────────────┐
                │   快速恢复    │
                └──────┬───────┘
                       ↓
                ┌──────────────┐
                │   Postmortem │
                └──────┬───────┘
                       ↓
              ┌────────┴────────┐
              ↓                 ↓
          技术原因            系统原因
              ↓                 ↓
          修复Bug             修机制
              ↓                 ↓
          加测试              加监控
              ↓                 ↓
          加告警              自动化
              └────────┬────────┘
                       ↓
                ┌──────────────┐
                │   Runbook     │
                └──────┬───────┘
                       ↓
                ┌──────────────┐
                │   知识库      │
                └──────┬───────┘
                       ↓
                ┌──────────────┐
                │   团队培训    │
                └──────┬───────┘
                       ↓
                ┌──────────────┐
                │ 组织能力提升  │
                └──────────────┘

这才是真正意义上的:

从 Postmortem 到组织学习。


十一、最后,我越来越觉得:事故本身不是最可怕的

运维工作有一个很残酷的现实:

复杂系统一定会出事故。

你再努力,也不可能做到:

代码语言:txt
复制
事故率 = 0

真正应该追求的可能是:

代码语言:txt
复制
事故发生
 ↓
影响越来越小
 ↓
发现越来越快
 ↓
恢复越来越快
 ↓
重复事故越来越少
 ↓
团队越来越不依赖个人

所以我不太喜欢把 Postmortem 翻译成简单的“事故总结”。

它更像是一种组织的记忆机制

人会忘记。

新人会加入。

老员工会离职。

系统会重构。

代码会重写。

但是,如果一次事故最终变成了:

代码语言:txt
复制
一条监控
一个测试
一个Runbook
一个自动化脚本
一个发布门禁
一条工程规范
一套培训材料

那么这场事故就没有白发生。

最好的事故复盘,不是让大家记住“谁搞砸了”。

而是让组织记住:

“我们曾经在这里摔倒过,所以以后不会再用同样的姿势摔第二次。”

这才是 Postmortem 最有价值的地方。

也是我理解的运维真正的成长:

从“我能把系统救回来”,到“我能让这个团队以后更不容易把系统搞挂”。

前者是运维能力。

后者,才是组织能力。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 事故复盘不是写检讨,而是让团队变强的一次机会
    • 一、很多公司的事故复盘,其实只是“事故作文”
  • 二、真正应该复盘的,不是“谁犯错”,而是“系统为什么允许错误发生”
  • 三、Postmortem 最重要的一个词:Blameless
  • 四、事故不是“坏事”,重复事故才是真正的坏事
    • 事故复盘 ≠ 组织学习
  • 五、不要只写“整改措施”,要给整改措施加上生命周期
  • 六、事故复盘真正应该关注的是“控制点”
    • 第一层
    • 第二层
    • 第三层
    • 第四层
    • 第五层
  • 七、真正高级的运维,不是“救火快”,而是“让火越来越少”
  • 八、我特别建议把事故沉淀成“可执行知识”
  • 九、事故还可以反过来喂给监控、测试和AI
  • 十、最终要建立的是一条“事故 → 能力”的流水线
  • 十一、最后,我越来越觉得:事故本身不是最可怕的
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档