写 incident runbook:让凌晨 3 点的 oncall 能跟着做

起因

服务挂了。监控告警发到 oncall 手机。

理想:oncall 知道怎么处理。
现实:oncall 是新人 / 不熟这服务 / 凌晨 3 点头脑不清 → 慌。

runbook(操作手册):每个服务 / 每类 alert 一份明确步骤文档。
不需要 oncall 思考根因,跟着步骤恢复 → 后续 owner 来 root cause。

一份 runbook 包含什么

# Runbook: API service down

## TL;DR
1. Check status: `kubectl get pods -n api`
2. If pod CrashLoopBackOff → restart: `kubectl rollout restart deploy api -n api`
3. If still bad → check dashboard: <url>
4. If beyond 15 min → page tech lead: <name>

## 告警含义
什么触发的:API 5xx > 5% 持续 5 min
影响:用户 login / 主要功能不可用

## 快速 mitigation
[5 个具体命令 / 步骤]

## diagnose
[查日志 / metric 怎么看]

## 升级路径
mitigation 没用 → 找谁 + 怎么联系

关键:第一行就告诉怎么做,不是先 5 段背景介绍。

模板

# Runbook: <Alert Name>

## 紧急 mitigation (< 5 分钟)
具体命令 / 步骤,复制粘贴能跑。

## 影响
- 用户感知:xxx
- 受影响服务:xxx

## 何时升级
- 5 分钟内未解决 → 找 oncall #2
- 15 分钟内未解决 → page tech lead
- 影响数据完整性 → 拉 incident commander

## diagnose
1. Grafana: <link>
2. 日志查询:<link Loki / ELK>
3. trace:<link Jaeger>

## 已知场景
- 场景 A:症状 → 处理
- 场景 B:症状 → 处理

## 相关链接
- 架构图:<link>
- 设计文档:<link>
- post-mortem:<link to history>

实例:DB connection pool 满

# Runbook: PG connection pool exhausted

## 5 分钟 mitigation

```bash
# 1. 看 pool 状态
psql -h pgbouncer -U admin pgbouncer -c "SHOW POOLS;"
# 如果 cl_waiting > 0 → 有客户端排队

# 2. 重启 app(释放可能 leak 的连接)
kubectl rollout restart deploy/api -n api
kubectl rollout restart deploy/worker -n api

# 3. 临时扩 pool
kubectl edit configmap pgbouncer-config -n db
# default_pool_size: 30 → 50
kubectl rollout restart deploy/pgbouncer -n db

# 4. 5 分钟内未恢复 → 升级

影响

  • 所有 API 请求 timeout / 慢
  • 后台 worker 失败

diagnose

  • Grafana "PG conn pool":
  • log: {service="api"} |= "connection refused"
  • trace 看慢 query:

已知场景

  • 长 transaction leak(应用 bug):找 long-running query:
    sql SELECT pid, now() - xact_start, query FROM pg_stat_activity WHERE state != 'idle' ORDER BY 2 DESC;
    kill 长跑:SELECT pg_terminate_backend(pid);

  • 流量 spike:HPA 没跟上 → 手动扩
    kubectl scale deploy/api --replicas=20 -n api

升级

  • 第 5 分钟 → @oncall-secondary
  • 第 15 分钟 → @platform-lead
  • 数据损坏迹象 → @dba @cto

历史

  • 2025-02-12 incident: long tx leak in checkout flow
  • 2024-11-03 incident: traffic spike from marketing
## 让 runbook 持续有用

死的 runbook = 没 runbook。
每 incident 后 update:

- 这步骤管用 → 强化
- 不管用 → 删 / 改
- 新 case → 加"已知场景"

post-mortem 写完必须更新 runbook(强制 process)。

## alert 跟 runbook 关联

```yaml
# Prometheus alert rule
- alert: ApiHighErrorRate
  expr: rate(api_errors[5m]) > 0.05
  annotations:
    summary: "API error rate > 5%"
    runbook_url: "https://wiki.example.com/runbook/api-error-rate"

PagerDuty / Slack alert 自动带 runbook 链接 → oncall 一键点开。

命名

  • api-5xx-spike(不是"api-bad")
  • pg-replica-lag
  • cert-expiring-soon

具体 + 可搜。每个 alert name 对应一个 runbook URL slug。

存哪

  • Confluence / Notion:好搜索 + 版本
  • GitHub repo: ops/runbooks/.md:跟 code 一起 review
  • 内置 Grafana annotation

我们用 git repo + 工具自动 publish 到 web view。
PR review 强制:alert 新增必须有 runbook PR。

decision tree 模式

复杂场景画决策树:

alert: api-down

start
  │
  ▼
pod 是否 running?
  │
  ├─ 否 → kubectl describe pod → 是否 ImagePullBackOff?
  │        ├─ 是 → registry 故障,看 <link>
  │        └─ 否 → 看 events,可能 OOMKilled → 扩 memory
  │
  └─ 是 → 是否 5xx?
            ├─ 是 → 看 dependency (DB / Redis),看 <link>
            └─ 否 → ingress 问题,看 <link>

mermaid 图直接渲染。复杂场景帮助新人按图索骥。

演练 (game day)

每季度模拟 incident:

  1. SRE 故意触发"假 incident"(kill pod / 切 DB / 灌错配)
  2. oncall 跟 runbook 处理
  3. 后 retro:runbook 哪步含糊 / 缺步骤

新人参与多 → 暴露 runbook 不足。
不演练 = runbook 锈了。

没 runbook 的 alert 怎么办

不应该。
原则:"no runbook, no alert"。
如果没人知道收到这 alert 该干啥 → 这 alert 没意义,删了或者写 runbook。

避免"alert 海":每天 100 个 alert 没人看 → 真出事漏。

与 chaos engineering

chaos engineering 主动制造小故障验证系统韧性。
runbook 是被动响应文档。
两者互补:chaos 找出 weakness → 加 runbook + 修系统。

工具

  • PagerDuty:alert → oncall + runbook
  • Opsgenie:类似
  • Atlassian Statuspage:状态页给客户
  • Linear / Jira:incident ticket 跟踪

真实 case

某 prod incident 凌晨 2 点:

  • API 5xx 飙
  • oncall (新人,3 个月)收到 alert
  • runbook 链接:5 步 mitigation
  • 第 2 步 (rollout restart) 没好
  • 第 4 步 (扩 pool) 缓解
  • 5 分钟用户感知恢复
  • 早上 team 看到 → root cause: third-party API timeout,加更长 timeout

完整 incident 30 分钟解决,影响 < 5 分钟。
没 runbook 的话新人可能就先 page 一堆人,影响时间几倍。

反模式

  • "看监控就知道了":监控不告诉你怎么修
  • "去问 X 老员工":X 出差 / 离职
  • "看代码就知道":凌晨 3 点没人看 code
  • "再 alert 一次看看":用户 already 受影响

runbook 是为最坏情况写的,假设阅读者一无所知。

踩过的坑

  1. runbook 跟实际不符:服务改了配置 runbook 没更新 → 命令报错。
    review 加"runbook 改了吗"。

  2. 太长:5 页 runbook 凌晨没人读完。TL;DR + 第一屏放 mitigation。

  3. 依赖外部知识:"找 platform team Slack 沟通" 但 Slack 名变了。
    绝对路径 / 永久 link。

  4. 不演练:以为 runbook 写完就够 → 真出事步骤不通。季度演练。

  5. 没人 own:runbook 谁更新?每服务 owner 负责。新 alert 设
    "DRI"。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。