Alertmanager 告警降噪实战:抑制器 + 路由树 + 静默配置四步降噪法
2024 年冬天,我们线上发生过一次事故:Prometheus 监控到了 300+ 条告警,运维群里 5 分钟内刷了 2000 多条消息。值班人看了 10 分钟才发现真正的问题——磁盘满,其余 299 条都是衍生告警。这件事之后,我们花了两周把 Alertmanager 告警降噪做了一遍,现在每天活跃告警不到 10 条,重要告警秒级触达。
告警风暴的根因:三层失控
一个健康的告警系统应该做到:重要告警不漏,次要告警不烦。生产环境告警失控,本质是三层出了问题:
下面按这四步走,把告警从几百条降到个位数。
步骤一:给告警规则加 for 时窗
告警规则的 for 字段是最简单的降噪手段,很多人忘了加。
groups:
- name: host-alerts
rules:
- alert: HighCpu
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m # ← 必须加!没有 for 就是瞬时抖动也报警
labels:
severity: warning
annotations:
summary: "CPU 使用率超过 80% 持续 10 分钟"
原则:
| 指标类型 | 建议 for 时窗 | 理由 |
|---|---|---|
| CPU / 内存 | 5-10m | 短时尖峰是正常的 |
| 磁盘使用率 | 5m | 磁盘增长是渐变过程 |
| 进程存活 | 1m | 进程崩了不能等 |
| 网络延迟 | 5m | 网络抖动常见 |
| 错误率 | 3m | 瞬时 500 不一定是问题 |
踩坑实录:我们把 HighCpu 的 for 从 0 改成 10m 之后,告警数量从每天 40 条降到 3 条——因为 90% 的 CPU 告警都是Deployment 启动时的短暂尖峰。
步骤二:正确设置 group_by
group_by 决定了同类告警如何合并。配错了,同一故障会产生几十条独立告警。
route:
group_by: ['alertname', 'cluster', 'service'] # 按业务维度分组
group_wait: 10s # 等 10 秒收集同类告警一起发
group_interval: 5m # 同组告警 5 分钟内不重复发
repeat_interval: 4h # 未恢复告警每 4 小时提醒一次
group_by 错误示例(翻车):
# ❌ 按 instance 分组 → 同一 alert 在 10 个实例上各发一条,完全独立
group_by: ['instance']
# ✅ 按业务分组 → 同一故障的多个实例合成一条告警
group_by: ['alertname', 'cluster', 'service']
踩坑实录:有一次 Kubernetes 集群扩容,Alertmanager 因为 group_by: ['instance'] 给每台新 Pod 发了独立的 HighMemory 告警,30 台 Pod 瞬间 30 条告警。改成 group_by: ['alertname', 'namespace'] 后,整个 namespace 只报一条。
步骤三:配置 Inhibit 抑制器
抑制器是告警降噪的核心武器。它的逻辑是:当 A 告警存在时,自动屏蔽 B 告警,前提是 B 是 A 的衍生告警。
inhibit_rules:
# 磁盘满时,抑制 inode 告警(磁盘满了 inode 肯定也满)
- source_matchers:
- severity = critical
- alertname = DiskFull
target_matchers:
- alertname = DiskInodeFull
equal: ['instance']
# 节点 NotReady 时,抑制该节点上的所有 Pod 告警
- source_matchers:
- alertname = NodeDown
target_matchers:
- severity = warning
equal: ['instance']
# 集群级别的网络分区,抑制所有单实例告警
- source_matchers:
- alertname = NetworkPartition
- severity = critical
target_matchers:
- severity = warning
equal: ['cluster']
抑制器设计原则:
- 只在因果关系明确时配置,不要为了少报而抑制
equal字段必须精确,不然会误抑制其他实例的正常告警- 先开 Inhibit,再验证——每天检查一次"被抑制的告警"列表,确认没有误伤
踩坑实录:我们配置过一条 NodeDown 抑制所有 warning 告警的规则,结果某次节点故障时,一条真正的 warning 级别磁盘告警被抑制了——那条磁盘告警其实和节点故障无关,是另一块磁盘的问题。后来把 equal: ['instance'] 加上,才修正了这个问题。
步骤四:路由树按 severity 分发
路由树解决的是"谁在什么情况下该收到什么通知"。
route:
receiver: 'default-receiver'
group_by: ['alertname', 'cluster', 'service']
group_wait: 10s
group_interval: 5m
repeat_interval: 4h
# P0 告警:直接电话 + 企业微信,30 分钟重复
routes:
- matchers:
- severity = critical
receiver: 'p0-oncall'
repeat_interval: 30m
continue: false
# P1 告警:企业微信,4 小时重复
- matchers:
- severity = warning
receiver: 'p1-wechat'
repeat_interval: 4h
continue: false
# P2 告警:邮件,24 小时重复
- matchers:
- severity = info
receiver: 'p2-email'
repeat_interval: 24h
continue: false
** receivers 配置示例 **:
receivers:
- name: 'p0-oncall'
webhook_configs:
- url: 'http://alert-router:8080/p0' # 转发到电话回调系统
wechat_configs:
- corp_id: 'your-corp-id'
agent_id: 'your-agent-id'
to_party: 'oncall-team'
api_secret: '{{ secret }}/wechat_secret'
- name: 'p1-wechat'
webhook_configs:
- url: 'http://alert-router:8080/p1'
- name: 'p2-email'
email_configs:
- to: '[email protected]'
send_resolved: true
- name: 'default-receiver'
webhook_configs:
- url: 'http://alert-router:8080/default'
四个翻车案例复盘
案例 1:Silence 配错导致真告警被屏蔽
现象:维护窗口加了 Silence,结果维护结束后 Silence 还在,正常告警全被吞了。
根因:Silence 到期时间配错了——配的是维护开始时间而不是结束时间。
教训:加 Silence 时 double-check 到期时间,养成习惯:维护结束前手动验证 Silence 是否还在生效。
案例 2:Inhibit 误伤导致漏报
现象:节点故障时,所有 warning 告警被抑制,包括一块与节点故障无关的磁盘告警。
根因:Inhibit 规则 equal 字段不够精确,缺少 service 维度。
教训:每条 Inhibit 规则必须经过"反向验证"——问自己"这条规则在什么情况下会误抑制正常告警?"
案例 3:group_wait 太长导致告警延迟
现象:P0 告警发出时已经过了 5 分钟,值班人员说"等我看完这条再处理,结果第一条已经过时了"。
根因:group_wait: 30s 对于 P0 太长了,P0 应该 5s 内发出。
教训:不同 severity 的 group_wait 要分开配,P0 用 5s,P1 用 10s,P2 用 30s。
案例 4:repeat_interval 太短导致告警疲劳
现象:一条 P1 告警每 30 分钟重复发一次,值班人员看了两天后直接屏蔽了通知。
根因:repeat_interval: 30m 太短,告警疲劳导致忽略。
教训:P1 至少 2h,P2 至少 12h。告警疲劳比告警缺失更危险——人习惯了不处理。
降噪效果对比
| 指标 | 降噪前 | 降噪后 |
|---|---|---|
| 日均告警数 | 350+ | 8-12 |
| P0 告警发现时间 | 平均 15 分钟(在噪音中找) | < 2 分钟 |
| 误报率(无效告警) | ~40% | < 5% |
| 值班人员告警疲劳 | 高(每天刷几百条) | 低(每天处理不到 10 条) |
写在最后
告警系统的核心目标不是"报得全",而是"报得准"。降噪不是一次性工程,是需要持续维护的——每加一条告警规则,都要问自己:这条规则会不会产生噪音?会不会被其他规则覆盖?会不会和现有抑制器冲突?
把告警当成产品来做,降噪就是它最重要的用户体验。