好的告警是「不打扰」,坏的通知是「狼来了」。 当 PagerDuty 每天响 50 次,团队 3 周内就会学会忽略所有告警——包括真正重要的那个。告警设计的终极目标是:每一次通知都值得被打断。
一、告警设计的黄金法则
1.1 可行动性(Actionable)
❌ 坏告警:"CPU 高"
→ 高到多少?什么时候?哪个服务?我该做什么?
✅ 好告警:"prod-web-01 CPU 使用率 95%(阈值 85%),
过去 10 分钟持续上升,已触发自动扩容,
如 5 分钟后未恢复请检查部署日志: https://..."
→ 包含:指标、上下文、自动动作、下一步指引
1.2 告警四要素
| 要素 | 要求 | 示例 |
|---|---|---|
| What | 明确的问题描述 | “订单服务 P99 延迟 > 2s” |
| Where | 精确的位置/范围 | “生产环境 /api/checkout 路由” |
| When | 时间窗口 | “从 14:32 持续到现在” |
| Action | 建议的操作 | “查看支付服务日志 / 回滚到 v1.2.2” |
二、告警方法论
2.1 Four Golden Signals
Google SRE 推荐的四个黄金信号:
Latency(延迟)
├── 它是服务有多慢的衡量
├── 区分成功请求和失败请求的延迟
└── 失败请求可能立即返回,拉低平均值
Traffic(流量)
├── 系统承受了多少需求
├── HTTP QPS、消息队列消费速率、网络带宽
└── 用于衡量容量和负载
Errors(错误)
├── 多少请求失败
├── 显式(HTTP 500)和隐式(HTTP 200 但返回错误)
└── 用于衡量可靠性
Saturation(饱和度)
├── 服务有多"满"
├── CPU、内存、磁盘、连接池、队列长度
└── 通常最预示即将发生的故障
2.2 USE 方法(资源层)
| 指标 | CPU | 内存 | 磁盘 I/O | 网络 | 连接池 |
|---|---|---|---|---|---|
| Utilization | 使用率 | 使用率 | 带宽使用率 | 吞吐量 | 活跃连接 |
| Saturation | 队列/负载 | swap 频率 | IO 队列 | 丢包率 | 等待队列 |
| Errors | 指令错误 | OOM | IO 错误 | CRC 错误 | 超时连接 |
2.3 RED 方法(服务层)
| 指标 | 说明 |
|---|---|
| Rate | 每秒请求数 |
| Errors | 每秒错误数 |
| Duration | 请求延迟分布 |
USE 用于资源(机器/容器),RED 用于服务(API/微服务),Four Golden Signals 是更通用的框架。三者互补。
三、告警分级
3.1 P0-P3 分级体系
| 级别 | 名称 | 响应时间 | 通知方式 | 升级条件 |
|---|---|---|---|---|
| P0 | 紧急(Critical) | 15 分钟内 | 电话+短信+Slack | 自动升级 |
| P1 | 高(High) | 1 小时内 | 短信+Slack | 2 小时未处理升级 |
| P2 | 中(Medium) | 4 小时内 | Slack | 次日处理 |
| P3 | 低(Low) | 1 个工作日内 | 邮件/工单 | 无需升级 |
P0 场景示例:
- 全部用户无法访问主站
- 支付成功率 < 90%
- 数据库主库宕机
- 安全事件(数据泄露)
P1 场景示例:
- 核心功能降级(如搜索不可用)
- 非核心地区访问慢
- 单实例故障但服务仍可用
P2 场景示例:
- 监控数据缺失
- 容量接近阈值(预计 3 天内满)
- 单节点日志异常
P3 场景示例:
- 证书 30 天后过期
- 依赖版本有安全补丁
- 非紧急优化建议
3.2 Prometheus 告警分级
# alerting_rules.yml
groups:
- name: service_critical
rules:
- alert: PaymentServiceDown
expr: up{job="payment-service"} == 0
for: 1m
labels:
severity: p0
team: backend
annotations:
summary: "Payment service is down"
runbook_url: "https://wiki.example.com/runbooks/payment-down"
- alert: HighPaymentErrorRate
expr: |
sum(rate(http_requests_total{job="payment-service",status=~"5.."}[5m])) /
sum(rate(http_requests_total{job="payment-service"}[5m])) > 0.1
for: 5m
labels:
severity: p0
annotations:
summary: "Payment error rate > 10%"
- name: service_warning
rules:
- alert: HighPaymentLatency
expr: |
histogram_quantile(0.95,
rate(http_request_duration_seconds_bucket{job="payment-service"}[5m])
) > 2
for: 10m
labels:
severity: p1
annotations:
summary: "P95 payment latency > 2s"
四、告警降噪
4.1 告警疲劳根因
告警疲劳的典型原因:
├── 阈值设置不当(太敏感)
├── 缺少 for 持续时间(毛刺触发)
├── 重复通知(未分组/路由)
├── 无意义的告警(无法行动)
├── 依赖服务故障导致级联告警
├── 非工作时间通知非紧急问题
└── 告警恢复时也通知(噪音)
4.2 降噪手段
| 手段 | 实现 | 效果 |
|---|---|---|
| 分组 | Alertmanager group_by | 同类告警合成一条通知 |
| 抑制 | inhibit_rules | 高优告警抑制低优 |
| 静默 | Scheduled silences | 维护窗口静默 |
| 延迟 | for: 5m | 持续一段时间才触发 |
| 聚合 | aggregation | 按维度汇总 |
| 升级 | escalation | 超时不处理升级组长 |
| 值班表 | rotation | 非值班时间不通知 |
4.3 Alertmanager 降噪配置
# alertmanager.yml
route:
group_by: ['alertname', 'job', 'severity']
group_wait: 30s # 等 30s 聚合同类告警
group_interval: 5m # 每 5min 发送一次组内更新
repeat_interval: 4h # 4h 内不重复发送同一告警
routes:
# P0 → 立即电话
- match:
severity: p0
receiver: pagerduty-p0
group_wait: 0s
continue: false
# P1 → Slack,1h 后升级到 PagerDuty
- match:
severity: p1
receiver: slack-alerts
routes:
- match:
status: "unresolved"
group_interval: 1h
receiver: pagerduty-p1
# 抑制:数据库宕机时,抑制所有依赖数据库的告警
inhibit_rules:
- source_match:
alertname: DatabaseMasterDown
target_match_re:
alertname: .*
equal: ['datacenter', 'environment']
# 静默:计划维护
# 通过 API 创建:
# curl -X POST alertmanager:9093/api/v1/silences \
# -d '{"matchers":[{"name":"alertname","value":"HighCPULoad","isRegex":false}],"startsAt":"...","endsAt":"...","createdBy":"ops","comment":"planned maintenance"}'
五、值班制度(On-Call)
5.1 值班设计原则
理想的 On-Call:
├── 频率:每人每 4-6 周一次
├── 时长:一周(自然周)
├── 响应:P0 立即响应,P1 1h 内
├── 补偿:调休或津贴
├── 交接:周五下午交接,同步未处理事项
└── 兜底:升级经理 → VP → CEO(P0 长时间未响应)
糟糕的 On-Call:
├── 频率太高(每周)→ 疲劳、倦怠
├── 没有补偿 → 抵触情绪
├── 响应不及时无惩罚 → 无责任感
└── 告警不真实 → 狼来了
5.2 PagerDuty 配置示例
# escalation_policy.yml
escalation_policy:
name: Backend On-Call
description: Backend service escalation
escalation_rules:
- escalation_rule:
targets:
- type: user_reference
id: user_1 # 当前值班人
escalation_delay_in_minutes: 15 # 15 分钟未响应升级
- escalation_rule:
targets:
- type: user_reference
id: user_2 # 备用值班人 / 组长
escalation_delay_in_minutes: 15
- escalation_rule:
targets:
- type: user_reference
id: user_3 # 经理
escalation_delay_in_minutes: 30
六、事件响应 SOP
6.1 事件生命周期
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Detect │ → │ Assess │ → │ Mitigate │ → │ Resolve │ → │ Review │
│ 检测 │ │ 评估 │ │ 缓解 │ │ 解决 │ │ 复盘 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │ │ │ │
↓ ↓ ↓ ↓ ↓
告警触发 影响范围评估 止损措施 根因修复 Postmortem
监控发现 用户影响量化 回滚/限流 验证恢复 改进措施
用户反馈 快速分类 P0/P1 降级服务 关闭事件 Action Items
6.2 检测阶段
检测来源优先级:
1. 自动化监控告警(最快速)
2. 用户反馈/客服工单
3. 值班巡检
4. 业务指标下降(转化率、收入)
关键动作:
- 确认事件真实存在(非误报)
- 创建事件工单(incident channel)
- 启动事件响应流程
6.3 评估阶段
评估清单:
□ 影响范围:多少用户?哪些功能?哪些地区?
□ 严重程度:P0/P1/P2/P3
□ 开始时间:何时开始?持续多久了?
□ 相关变更:最近是否有部署/配置变更?
□ 是否已知:是否在 Runbook 中有记录?
6.4 缓解阶段
缓解 ≠ 修复。缓解是让系统恢复可用,根因修复可以后面做。
常见缓解措施:
├── 回滚到上一个版本
├── 重启故障实例
├── 切换流量到备用集群
├── 降级/关闭非核心功能
├── 扩容
├── 开启熔断
└── 切换数据库只读模式
原则:先止血,后手术。
七、事后复盘(Postmortem)
7.1 无责文化(Blameless)
Postmortem 的目标不是「抓出谁犯了错」,而是:
- 理解系统为什么会允许这个错误发生
- 识别流程和工具中的漏洞
- 制定可落地的改进措施
禁止:
❌ "XX 为什么不..."
❌ "XX 提交了这个有 bug 的代码"
改为:
✅ "自动化测试为什么没有捕获这个场景?"
✅ "代码审查流程为什么没发现这个问题?"
✅ "架构设计上有什么可以改进的地方?"
7.2 Postmortem 模板
# Postmortem: [事件ID] [简要描述]
## 基本信息
- **事件 ID**: INC-2024-0813-001
- **日期**: 2026-08-13
- **持续时间**: 14:32 - 15:15 (43 分钟)
- **影响**: 支付功能不可用,约 12,000 用户受影响
- **严重级别**: P0
## 时间线(精确到分钟)
| 时间 | 事件 |
|------|------|
| 14:28 | v1.3.0 部署到生产 |
| 14:32 | 支付错误率开始上升 |
| 14:35 | PagerDuty P0 告警触发 |
| 14:37 | 值班工程师响应 |
| 14:42 | 确认是 v1.3.0 引入的 bug |
| 14:45 | 回滚到 v1.2.9 |
| 14:50 | 错误率开始下降 |
| 15:15 | 确认全部恢复 |
## 根因分析
5 Whys:
1. 为什么支付失败?→ 银行 API 超时
2. 为什么超时?→ v1.3.0 将超时从 10s 改为 30s,银行侧拒绝连接
3. 为什么改了超时?→ 产品经理要求支持慢银行
4. 为什么没测试到?→ 集成测试环境用的 mock 银行,不模拟超时场景
5. 为什么 mock 不够?→ 缺乏真实第三方依赖的集成测试
## 影响评估
- **用户影响**: 12,000 用户无法完成支付
- **业务影响**: 约 ¥450,000 订单流失
- **SLA 影响**: 支付可用性从 99.95% → 99.2%(月度)
## 已采取的措施
- [x] 回滚到 v1.2.9
- [x] 通知受影响用户
- [x] 补偿优惠券发放
## 改进措施
| 优先级 | 措施 | Owner | 截止日期 |
|--------|------|-------|----------|
| P0 | 增加银行 API 沙箱集成测试 | @dev-a | 2024-08-20 |
| P0 | 部署后自动 Canary 验证 | @dev-b | 2024-09-01 |
| P1 | 支付服务增加熔断降级 | @dev-c | 2024-08-30 |
| P1 | 超时参数改为配置化,无需发版 | @dev-d | 2024-08-25 |
## 经验教训
- 第三方依赖变更需要真实环境验证
- 超时等关键参数应配置化
- Canary 部署应成为强制流程
八、ChatOps 与 Runbook
8.1 ChatOps
ChatOps = 在聊天工具(Slack/Discord)中执行运维操作
示例:
/incident create payment-service-down P0
→ 创建事件频道 #incident-2024-0813-payment
→ 引入值班工程师 + 相关团队
→ 自动生成时间线
→ 关联最近的部署变更
/rollback payment-service v1.2.9
→ 执行回滚
→ 在频道中更新状态
→ 记录操作人
好处:
- 所有操作可审计
- 团队实时可见
- 减少上下文切换
8.2 Runbook 模板
# Runbook: Payment Service 不可用
## 检测
- 告警: `PaymentServiceDown` 或 `HighPaymentErrorRate`
- 验证: `kubectl get pods -l app=payment-service`
## 评估
- 检查最近部署: `kubectl rollout history deployment/payment-service`
- 检查 pod 状态: `kubectl describe pod <pod-name>`
- 检查日志: `kubectl logs -l app=payment-service --tail=100`
## 缓解(按优先级)
1. 如果最近有部署 → 回滚
```bash
kubectl rollout undo deployment/payment-service
- 如果 pod CrashLoop → 检查配置/密钥
kubectl get configmap payment-config -o yaml - 如果是 OOM → 临时扩容内存
kubectl patch deployment payment-service -p '{"spec":{"template":{"spec":{"containers":[{"name":"payment","resources":{"limits":{"memory":"1Gi"}}}]}}}}'
升级
如果 15 分钟内无法缓解,@backend-lead
验证恢复
- 错误率 < 1%
- P99 延迟 < 500ms
- 支付成功率 > 99%
---
## 九、SLA 相关指标
| 指标 | 全称 | 计算 | 意义 |
|------|------|------|------|
| **MTTR** | Mean Time To Recovery | 故障开始到恢复的平均时间 | 团队响应效率 |
| **MTBF** | Mean Time Between Failures | 两次故障间的平均时间 | 系统稳定性 |
| **MTTF** | Mean Time To Failure | 系统正常运行到故障的平均时间 | 可靠性 |
可用性计算公式:
Availability = MTBF / (MTBF + MTTR)
示例:
MTBF = 720h, MTTR = 1h
Availability = 720 / 721 = 99.86%
目标:提高 MTBF(防故障)+ 降低 MTTR(快恢复)
---
## 参考与延伸阅读
- [Google SRE Book — Handling Interrupts](https://sre.google/sre-book/handling-interrupts/)
- [PagerDuty Incident Response](https://response.pagerduty.com/)
- [Awesome Postmortems](https://github.com/danluu/post-mortems)
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。