5 招降低 Prometheus 告警噪音,让 Alertmanager 只发有用的通知


目录:

告警风暴一来,真正的故障反而被淹没。运维不是不需要告警,而是需要"有效告警"。


痛点:告警太多 = 没有告警

场景很熟悉:Prometheus + Alertmanager 部署完毕,规则写了几十条,结果每天收到上百条通知——CPU 短暂飙高、磁盘波动、网络抖动……真正的故障告警混在噪音里,值班同学看到通知直接划掉,形成"狼来了"效应。

某团队统计过:80% 的告警在 5 分钟内自动恢复,真正需要人工介入的不到 10%。问题不在 Prometheus 不好用,而在告警规则和 Alertmanager 路由没调好。

方案:5 步降噪,只保留有价值的告警

核心思路:抬高触发门槛 + 智能分组 + 抑制联动 + 静默窗口 + 分级路由

实操步骤

第 1 招:用 for 过滤瞬时抖动

90% 的噪音来自瞬时波动。一条 for: 5m 就能干掉大量无意义告警:

# prometheus/rules/node.yml
groups:
  - name: node-alerts
    rules:
      - alert: HighCpuUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 10m          # 持续 10 分钟才触发,过滤短暂毛刺
        labels:
          severity: warning
        annotations:
          summary: "CPU 持续高负载 {{ $labels.instance }}"
          value: "{{ $value | printf \"%.1f\" }}%"

经验值: - CPU / 内存告警:for: 10m - 磁盘空间:for: 5m - 服务不可达:for: 2m(这个不能太长,否则影响 MTTR)

第 2 招:Alertmanager 分组聚合

同一批机器同时挂了 10 台,你不需要收 10 条通知。用 group_by 聚合:

# alertmanager.yml
route:
  receiver: default
  group_by: ['alertname', 'cluster']
  group_wait: 30s        # 等 30 秒收集同类告警
  group_interval: 5m     # 同组告警合并发送间隔
  repeat_interval: 4h    # 未恢复告警重复通知间隔(别设太短!)

repeat_interval 是降噪关键——设成 1m 等于自己给自己搞 DDoS。建议 warning 设 4h,critical 设 1h

第 3 招:inhibit_rules 抑制关联告警

节点宕机了,上面跑的服务肯定也挂。不需要同时收到"节点不可达"和"服务 5xx 飙升"两条告警:

# alertmanager.yml
inhibit_rules:
  - source_match:
      alertname: NodeDown
    target_match_re:
      alertname: '(HighErrorRate|ServiceUnavailable|HighLatency)'
    equal: ['instance']

NodeDown 触发时,自动抑制同一 instance 上的服务级告警,只发根因通知。

第 4 招:time_intervals 静默维护窗口

每周二凌晨有批量更新?提前配置静默,不用手动 silence:

# alertmanager.yml
time_intervals:
  - name: maintenance-window
    time_intervals:
      - weekdays: ['tuesday']
        times:
          - start_time: '02:00'
            end_time: '04:00'

route:
  routes:
    - match:
        severity: warning
      mute_time_intervals:
        - maintenance-window

注意:critical 级别不建议静默——维护窗口也可能出真故障。

第 5 招:分级路由,该叫谁叫谁

不是所有告警都需要发到钉钉群。按严重级别分流:

route:
  receiver: default
  routes:
    - match:
        severity: critical
      receiver: pagerduty-oncall    # 电话 + 短信,必须响应
      repeat_interval: 30m
    - match:
        severity: warning
      receiver: dingtalk-ops        # 钉钉群,工作时间处理
      repeat_interval: 4h
    - match:
        severity: info
      receiver: slack-log           # 仅记录,不打扰
      repeat_interval: 12h

3 个常见坑

坑 1:for 设太长导致漏报

磁盘快满设了 for: 30m,结果写满了才告警。磁盘类告警建议 for: 5m,同时加一条 predict_linear 预测规则:

- alert: DiskWillFull24h
  expr: predict_linear(node_filesystem_avail_bytes{fstype!="tmpfs"}[6h], 24*3600) < 0
  for: 10m
  labels:
    severity: warning

坑 2:group_by 用了太多 label

group_by: ['alertname', 'instance', 'job', 'env'] ——分得太细等于没分组,每台机器单独一条。通常 ['alertname', 'cluster']['alertname', 'env'] 就够了。

坑 3:repeat_interval 设太短被通知轰炸

默认值是 4h,有人改成 5m 想"确保不漏",结果一个未恢复的告警一天发了 288 条。warning 用 4h,critical 用 1h,足够了。

总结

降噪五步:

  1. for 过滤瞬时:大多数告警加 5-10 分钟持续条件
  2. group_by 聚合:同类告警合并,减少通知条数
  3. inhibit_rules 抑制:根因告警触发时,自动压制衍生告警
  4. time_intervals 静默:维护窗口自动 mute
  5. 分级路由:critical 叫人,warning 群通知,info 只记日志

做完这五步,告警量通常能降 60%-80%,剩下的每一条都值得看。告警系统的目标不是"全覆盖",而是"每条都有人响应"。