你是否也有过这样的经历?某个凌晨,手机被上千条告警短信轰炸,爬起来一看,只是机房网络的一次轻微抖动。更糟糕的是,真正关键的数据库切换告警被淹没在噪音里,直到第二天才被发现。
这就是告警泛滥的典型后果。对于运维和 SRE 团队而言,无效告警不仅让人疲于奔命,更会延误真正故障的处理时机。本文将基于 Prometheus 和 Alertmanager,分享一套经过实战检验的告警收敛方案,通过去重、聚合、抑制、静默、分级五个核心步骤,将告警量从每天上千条降至几十条,并且每一条都值得关注。
一、告警收敛的核心思路
在优化具体配置之前,我们首先要理解告警收敛的五大核心机制:
- 去重(Deduplication):对相同或高度相似的告警,在一段时间内只发送一次通知。
- 聚合(Grouping):将逻辑上相关的告警(如来自同一服务的多个实例)合并为一条通知发送,大幅减少信息量。
- 抑制(Inhibition):当高级别、根源性告警触发时,自动抑制由其引发的低级别或衍生告警,避免“告警风暴”。
- 静默(Silence):在计划内的维护窗口或已知问题期间,临时屏蔽特定告警,防止干扰。
- 分级与路由(Routing):根据告警的严重级别、影响范围,将其路由到不同的通知渠道(如电话、即时通讯、邮件),并匹配不同的响应时效要求。
这套方案主要应用于以下场景:
- 告警量过大,导致运维人员疲劳甚至忽略告警。
- 夜间非关键告警频繁,严重影响值班人员休息。
- 重要告警被大量无关告警淹没,造成漏处理。
- 新建监控体系时,需要一套合理的告警设计范式。
| 环境要求 |
组件 |
版本要求 |
说明 |
| Prometheus |
2.30+ |
监控数据源与告警规则定义 |
| Alertmanager |
0.24+ |
核心告警管理组件,实现收敛逻辑 |
| Grafana |
9.0+ |
可选,用于可视化和告警配置 |
| 通知渠道 |
- |
钉钉/飞书/企业微信/邮件/短信等 |
二、详细配置与优化步骤
2.1 优化告警规则:从源头减少噪音
在配置收敛之前,首先要确保告警规则本身是合理的。过于敏感的规则是告警泛滥的主要根源。
合理设置阈值与持续时间
一个常见的错误是阈值设置过低且没有持续时间缓冲。对比以下好坏示例:
# 反面教材:阈值过于敏感
- alert: HighCPU
expr: node_cpu_usage > 50 # 50%就告警,太敏感
for: 1m # 1分钟就告警,太短
# 推荐配置:合理阈值 + 缓冲时间
- alert: HighCPU
expr: node_cpu_usage > 85 # 85%才告警
for: 5m # 持续5分钟才触发
labels:
severity: warning
annotations:
summary: "CPU使用率过高"
description: "{{ $labels.instance }} CPU使用率 {{ $value }}%,持续5分钟"
for 字段至关重要,它能过滤掉指标的瞬时抖动,避免为短暂波动发送告警。
为告警添加丰富的 Labels
Labels 是后续进行分组、抑制、路由的基础。设计良好的 Labels 能让收敛策略更加灵活。
groups:
- name: node-alerts
rules:
- alert: NodeDown
expr: up{job="node"} == 0
for: 2m
labels:
severity: critical
team: infrastructure # 负责团队
env: production # 环境
annotations:
summary: "节点宕机: {{ $labels.instance }}"
2.2 配置 Alertmanager:实现核心收敛逻辑
Alertmanager 是 Prometheus 生态中负责告警管理的组件,上述收敛能力均由其提供。
基本配置结构
# /etc/alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.example.com:587'
smtp_from: 'alertmanager@example.com'
route:
receiver: 'default-receiver'
group_by: ['alertname', 'cluster', 'service'] # 分组字段
group_wait: 30s # 首次等待时间,用于聚合
group_interval: 5m # 同一分组发送新告警的间隔
repeat_interval: 4h # 重复发送同一告警的间隔
routes: # 子路由,用于分级
- match:
severity: critical
receiver: 'critical-receiver'
continue: true
- match:
severity: warning
receiver: 'warning-receiver'
receivers:
- name: 'default-receiver'
webhook_configs:
- url: 'http://dingtalk-webhook/send'
- name: 'critical-receiver'
webhook_configs:
- url: 'http://dingtalk-webhook/send'
pagerduty_configs:
- service_key: 'xxx'
- name: 'warning-receiver'
email_configs:
- to: 'ops@example.com'
分组聚合(Grouping)
这是减少告警数量的最有效手段。group_by 定义了如何将告警分组。例如,当3台服务器同时 CPU 过高时,不分组会收到3条告警。配置 group_by: ['alertname', 'cluster'] 后,只会收到一条聚合告警:
[FIRING:3] HighCPU
- server1: 95%
- server2: 92%
- server3: 88%
告警抑制(Inhibition)
用于处理告警之间的因果关系。当根源问题触发时,抑制其表现现象告警。
inhibit_rules:
# 当出现Critical告警时,抑制同一目标的Warning告警
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'instance']
# 当节点宕机时,抑制该节点上的所有其他告警
- source_match:
alertname: 'NodeDown'
target_match_re:
alertname: '.+'
equal: ['instance']
告警静默(Silence)
用于计划内维护或处理已知问题。可以通过 UI 或 API 创建。
# 通过API创建静默
curl -X POST http://alertmanager:9093/api/v2/silences \
-H "Content-Type: application/json" \
-d '{
"matchers": [
{"name": "alertname", "value": "HighCPU", "isRegex": false},
{"name": "instance", "value": "server1:9100", "isRegex": false}
],
"startsAt": "2024-03-15T00:00:00Z",
"endsAt": "2024-03-15T06:00:00Z",
"createdBy": "admin",
"comment": "服务器维护"
}'
2.3 实施分级通知策略
不是所有告警都需要电话呼叫。合理的分级能确保正确的人通过正确的渠道,在正确的时间收到告警。
| 告警分级定义 |
级别 |
定义 |
响应时间 |
通知渠道 |
| Critical (P0) |
服务不可用、数据丢失风险 |
5分钟内 |
电话 + 短信 + 钉钉 |
| Warning (P1/P2) |
性能下降、资源紧张 |
30分钟-1小时 |
钉钉 + 邮件 |
| Info (P3) |
一般信息、趋势预警 |
工作时间处理 |
邮件 |
基于时间的智能路由
可以通过 mute_time_intervals 或 active_time_intervals 实现工作时间和非工作时间的不同路由策略,这是保障夜间睡眠的关键。
route:
routes:
- match:
severity: info
receiver: 'info-receiver'
repeat_interval: 12h
mute_time_intervals: # 在以下时间段静默此路由
- nights-and-weekends
time_intervals:
- name: nights-and-weekends
time_intervals:
- times:
- start_time: '00:00'
end_time: '09:00'
- start_time: '18:00'
end_time: '24:00'
weekdays: ['monday:friday']
- weekdays: ['saturday', 'sunday'] # 周末全天
三、完整示例与实战案例
3.1 完整的 Alertmanager 配置参考
# /etc/alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.example.com:587'
smtp_from: 'alertmanager@example.com'
route:
receiver: 'default-receiver'
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- match:
severity: critical
priority: p0
receiver: 'p0-receiver'
group_wait: 10s
repeat_interval: 30m
- match:
severity: warning
receiver: 'p2-receiver'
repeat_interval: 4h
receivers:
- name: 'p0-receiver'
webhook_configs:
- url: 'http://phone-alert:8080/call'
- url: 'http://dingtalk-webhook:8060/dingtalk/critical/send'
email_configs:
- to: 'oncall@example.com'
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'cluster', 'service']
- source_match:
alertname: 'NodeDown'
target_match_re:
alertname: '.+'
equal: ['instance']
3.2 实战案例:夜间告警优化
问题:夜间大量 Warning 级别告警(如磁盘空间预警、CPU 小幅度波动)频繁打扰值班人员。
解决方案:配置时间窗口路由,夜间只将 Critical 告警发送给值班电话,Warning 告警延迟至工作日工作时间再发送给相应团队。
效果:夜间告警通知量下降 90% 以上,值班人员能获得连续睡眠,白天团队也能在上班后集中处理积累的非紧急告警。
四、最佳实践与注意事项
- 从简开始,逐步调优:不要一开始就配置复杂的抑制规则。先从合理的告警规则和基础分组做起,根据实际告警情况逐步增加抑制和静默规则。
- 定期回顾告警:每月或每季度分析告警触发频率。对于那些频繁触发又无需立即行动的“狼来了”告警,考虑调整阈值或改为信息类通知。
- 监控告警系统自身:为 Alertmanager 设置健康监控,确保告警链路可靠。也可以监控
alertmanager_notifications_failed_total 等指标,及时发现通知渠道故障。
- 避免过度抑制:抑制规则配置不当可能导致重要告警被意外屏蔽。每条抑制规则都应有明确的、经过验证的业务逻辑支撑。
- 高可用部署:生产环境的 Alertmanager 应集群化部署,避免单点故障导致告警丢失。
总结
一套有效的告警收敛方案,本质上是将监控系统从“噪声发生器”转变为“精准的行动指南”。通过 Prometheus 与 Alertmanager 的组合,我们可以系统性地实现告警的去重、聚合、抑制、静默和分级。这不仅大幅降低了运维人员的负担,更能确保每一个触发的告警都能得到应有的关注和及时的处理,真正提升系统的稳定性和团队的有效性。
希望这篇基于实战的告警收敛方案能为你构建更优雅的监控体系提供清晰的路径。如果你在实施过程中遇到问题,或者有更好的实践经验,欢迎在云栈社区的运维/DevOps/SRE板块与其他开发者交流讨论。