起因
服务挂了。监控告警发到 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-lagcert-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:
- SRE 故意触发"假 incident"(kill pod / 切 DB / 灌错配)
- oncall 跟 runbook 处理
- 后 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 是为最坏情况写的,假设阅读者一无所知。
踩过的坑
-
runbook 跟实际不符:服务改了配置 runbook 没更新 → 命令报错。
review 加"runbook 改了吗"。 -
太长:5 页 runbook 凌晨没人读完。TL;DR + 第一屏放 mitigation。
-
依赖外部知识:"找 platform team Slack 沟通" 但 Slack 名变了。
绝对路径 / 永久 link。 -
不演练:以为 runbook 写完就够 → 真出事步骤不通。季度演练。
-
没人 own:runbook 谁更新?每服务 owner 负责。新 alert 设
"DRI"。
登录后参与评论。