凌晨三点,手机响了。你迷迷糊糊拿起来一看——“CPU 使用率超过 80%”。你打开监控看了一眼,业务完全正常,流量高峰而已。你叹了口气,把告警静音,继续睡。第二天,你又收到 30 条类似的告警。第三天,你把通知关了。恭喜你,你的告警系统已经“脑死亡”了。不是告警不够多,而是告警不够好。这篇文章聊聊怎么设计让人愿意认真对待的告警。
一、告警疲劳:比没有告警更可怕的事
“告警疲劳”(Alert Fatigue)是运维领域的经典术语。它的逻辑很简单:
告警太多 → 假告警太多 → 不再相信任何告警 → 错过真正的故障
这跟“狼来了”是同一个故事。区别在于,狼来了是小孩在喊,你的告警是机器在喊——机器不会觉得愧疚,它只会按照规则触发。
告警疲劳的典型症状:
- 团队聊天群里每天几十上百条告警,没人回复
- 值班人员把告警通知调到静音
- 出了大故障后复盘:“告警不是报警了吗?”——“是吗?我没看到。”
如果你的团队有以上任何一种症状,那你的告警策略需要大修。
二、告警的黄金法则
法则一:告警必须能触发行动
这是告警设计的最高原则。如果一个告警响了,接收者不知道该做什么,那这个告警就不应该存在。
不该告警的例子:
- CPU 使用率超过 80%(可能只是正常流量波动,不需要人工干预)
- 磁盘使用率超过 70%(还有 30%,不需要半夜把人叫起来)
- 某个定时任务执行超过 10 秒(可能只是数据量变大了)
应该告警的例子:
- 用户支付成功率从 99.5% 降到 95%(用户正在受影响,需要立即介入)
- API 返回 5xx 错误数连续 3 分钟超过阈值(服务出问题了)
- 磁盘使用率超过 95% 且仍在快速增长(很快就要宕机了)
一个好的测试方法:每次加一条告警规则时,问自己“这条告警如果半夜响了,接收者应该做什么?” 如果答案不清楚,这条规则就不该存在。
法则二:告警应该是“症状”,不是“病因”
这个原则来自 Google SRE 的最佳实践。告警应该告的是“用户正在受影响”这个症状,而不是“可能存在问题的某个内部指标”。
告警"用户支付失败" ✓ —— 症状,用户已经受影响了
告警"数据库连接池达到 80%" ✗ —— 病因,用户可能还没受影响
为什么?因为“数据库连接池 80%”可能自己就好了,也可能不会影响用户,告这个只是在制造噪音。告警的目的不是让你知道“系统内部在干什么”,而是告诉你“用户正在遭遇什么”。
法则三:区分紧急程度
不是所有问题都需要凌晨三点把人叫起来。告警必须分级:
| 级别 | 含义 | 通知方式 | 响应要求 |
|---|---|---|---|
| P0 / Critical | 用户正在受影响,服务不可用 | 电话 + 短信 + IM | 5 分钟内响应 |
| P1 / Warning | 有风险但尚未影响用户 | IM + 邮件 | 30 分钟内处理 |
| P2 / Info | 值得关注但不紧急 | 邮件 或 不通知 | 工作时间处理 |
很多团队一上来所有告警都是 P0,结果就是没有 P0。
三、一个好告警的五个要素
当你写一条告警规则时,检查这五个点:
1. 明确的触发条件
不能是一个简单阈值,要有持续性判断:
# 不好的告警规则:瞬时触发
- alert: HighErrorRate
expr: error_rate > 5%
# 好的告警规则:持续 5 分钟才触发
- alert: HighErrorRate
expr: error_rate > 5%
for: 5m
加一个 for 条件可以过滤掉大量的瞬时抖动,让告警的可信度大幅提升。
2. 清晰的告警标题
标题要告诉接收者“什么服务、什么问题、有多严重”:
- 差:“告警:错误率过高”
- 好:“[P0] 订单服务 - 支付接口错误率 12%(阈值 5%)- 持续 6 分钟”
3. 有用的告警详情
告警信息里应该包含排错所需要的关键信息:
- 哪个服务
- 什么指标异常
- 当前值 vs 阈值
- 持续时间
- 相关的 dashboard 链接
- 相关的 runbook(操作手册)链接
4. 合理的通知策略
不是一个告警就发给所有人。告警要发给“该知道的人”和“能处理的人”。
- 应用相关告警 → 研发值班人员
- 基础设施告警 → 运维值班人员
- 严重 P0 告警 → 升级到技术负责人
5. 静默和抑制机制
这个经常被忽视但非常重要。告警应该支持:
- 静默:计划内维护期间,不让告警骚扰人
- 抑制:如果“服务器宕机”已经报警了,那“该服务器上的服务不可用”就不用再报了——前者已经包含了后者
- 聚合:同类告警合并成一条,不要发 100 条
四、Alertmanager:Prometheus 生态的告警中枢
Prometheus 的告警通过 Alertmanager 来管理。它的核心流程是:
Prometheus 触发告警规则 → Alertmanager 接收 → 分组/抑制/静默 → 发送通知
一个简单的 Alertmanager 配置示例:
# alertmanager.yml
route:
group_by: ['alertname', 'severity']
group_wait: 30s # 等 30 秒,同组告警一起发
group_interval: 5m # 同组告警有新告警时,间隔 5 分钟再通知
repeat_interval: 4h # 未恢复的告警每 4 小时提醒一次
receiver: 'default'
routes:
- match:
severity: critical
receiver: 'oncall-phone'
- match:
severity: warning
receiver: 'team-im'
receivers:
- name: 'oncall-phone'
webhook_configs:
- url: 'http://phone-call-service/alert'
- name: 'team-im'
webhook_configs:
- url: 'http://wechat-bot/alert'
关键参数说明:
group_wait:同一组告警等 30 秒再发,避免告警风暴中一个接一个的通知group_interval:同一组告警中追加的新告警,至少间隔 5 分钟才通知repeat_interval:持续未恢复的告警,每 4 小时提醒一次
这三个参数,精准控制了“告警的频率”,是避免骚扰的关键配置。
五、实践中常见的坑
坑一:白天配的规则,晚上才暴露问题
白天业务高峰可能很正常,晚上低峰时段那些“波动型”告警规则就炸了。任何新告警规则至少跑一个完整的业务周期(24h)再正式启用。
坑二:告警了但没人知道怎么处理
很多团队配了告警但没有 runbook。告警响了,值班人员打开信息一看:错误率超过阈值。然后就不知道该干嘛了。
每条告警规则都应该对应一个 runbook——一个简单的文档,告诉你这个告警意味着什么、第一步排查什么、第二步排查什么、谁可以帮忙。
坑三:恢复通知比告警还重要
很多团队只关注“什么时候报警”,完全忽略了“什么时候恢复”。恢复通知的意义是:你不用一直盯着监控了,已经好了。
Alertmanager 默认会发恢复通知,不要关掉它。
小结
告警的本质是让机器帮人“值班”,不是让机器替人“焦虑”。好的告警系统应该让值班人员信任它——每条告警都值得认真对待,每条告警都知道该做什么。如果你的告警系统做不到这一点,那它不是帮手,是负担。
从今天起,审查一下你现有的告警规则。删掉那些“响了也不知道该做什么”的,给剩下的加上 for 条件,补上 runbook。告警少了,但每一条都真正有用——这才是正确的方向。
下一篇,也是本系列的最后一篇,我们聊聊分布式链路追踪——当一次请求经过十几个微服务时,你该怎么知道它到底经历了什么。
每天前进一小步,就是一个新的高度!