Prometheus告警风暴问题
监控系统上线运行一段时间后,告警风暴是最常见的运维痛点。一次机房网络抖动可能触发数百条告警同时发出,值班人员被淹没在告警洪水中,真正的核心故障反而被忽略。统计显示,大型集群中超过60%的告警是重复或无效的,有效告警不足10%。
Prometheus Alertmanager提供了丰富的告警路由和抑制机制,但仅有工具不够,还需要在规则设计层面做降噪处理。以下是从告警规则编写到Alertmanager路由配置的完整实践。
告警规则编写规范
一条好的告警规则应满足三个条件:可操作性(收到后知道怎么处理)、低误报率(不频繁触发)、明确严重等级。以下是规范化的规则模板:
# groups: alert_rules.yml
groups:
- name: node_alerts
rules:
# 高CPU使用率告警
- alert: NodeHighCPUUsage
expr: |
100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 10m
labels:
severity: warning
team: infra
annotations:
summary: "CPU使用率过高 {{ $labels.instance }}"
description: "实例 {{ $labels.instance }} CPU使用率持续10分钟超过85%,当前值: {{ $value }}%"
# 磁盘空间不足告警
- alert: NodeDiskSpaceLow
expr: |
(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}
/ node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100 < 10
for: 5m
labels:
severity: critical
team: infra
annotations:
summary: "磁盘空间不足 {{ $labels.instance }} {{ $labels.mountpoint }}"
description: "挂载点 {{ $labels.mountpoint }} 可用空间不足10%,当前: {{ $value }}%"
关键字段说明:
expr:PromQL表达式,注意使用rate()而非irate()来平滑短期波动for:持续时间,给系统自愈的时间窗口。CPU类告警建议10分钟以上,磁盘类可以缩短到5分钟labels.severity:严重等级,通常分critical、warning、info三级labels.team:责任团队,用于路由到不同的通知渠道
告警分组与抑制机制
Alertmanager的核心降噪能力在于分组(grouping)和抑制(inhibition)。当同一故障触发多条告警时,分组合并发送;当高级别告警触发时,自动抑制关联的低级别告警。
alertmanager.yml配置示例:
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s # 首次告警等待时间,让同组告警合并
group_interval: 5m # 同组告警再次发送间隔
repeat_interval: 4h # 未恢复告警重复通知间隔
receiver: 'default-webhook'
routes:
# critical级别走电话+短信
- matchers:
- severity = critical
receiver: 'critical-pager'
group_wait: 0s # critical立即发送不等分组
continue: false
# warning级别走企业微信
- matchers:
- severity = warning
receiver: 'warning-wechat'
continue: false
inhibit_rules:
# 节点宕机时抑制该节点上的所有服务告警
- source_matchers:
- alertname = NodeDown
target_matchers:
- severity =~ "warning|info"
equal: ['instance']
# 服务不可用时抑制该服务的延迟和错误率告警
- source_matchers:
- alertname = ServiceDown
target_matchers:
- alertname =~ "HighLatency|HighErrorRate"
equal: ['service']
receivers:
- name: 'default-webhook'
webhook_configs:
- url: 'http://localhost:9099/alert'
- name: 'critical-pager'
webhook_configs:
- url: 'http://localhost:9099/critical'
- name: 'warning-wechat'
webhook_configs:
- url: 'http://localhost:9099/wechat'
上述配置实现了两个关键降噪逻辑:
- 分组:相同
alertname+cluster+service的告警合并为一条通知,30秒等待窗口内新到达的同组告警一并打包 - 抑制:当NodeDown告警触发时,同一instance上的所有warning和info级别告警被自动抑制,避免告警风暴
使用PromQL减少误报
很多告警误报源于PromQL表达式编写不当。以下是常见的优化模式:
使用预测函数提前预警,而非等到阈值才触发:
# 预测4小时后磁盘将满
- alert: DiskWillFillIn4h
expr: |
predict_linear(
node_filesystem_avail_bytes{fstype!~"tmpfs"}[1h],
4 * 3600
) < 0
for: 5m
labels:
severity: warning
排除计划内维护窗口,避免维护期间产生的告警噪音:
# 使用维护时间标记排除
- alert: ServiceHighErrorRate
expr: |
rate(http_requests_total{status=~"5.."}[5m])
/ rate(http_requests_total[5m]) > 0.05
and on(service)
maintenance_active{service!=""} == 0
for: 3m
labels:
severity: critical
多维聚合避免单实例抖动误报:
# 错误:单个实例抖动就触发告警
expr: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1
# 正确:聚合后超过60%的实例都慢才触发
expr: |
count(
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1
) by (service)
/ count(up) by (service) > 0.6
告警质量度量与持续优化
告警规则不是写完就结束,需要持续度量告警质量并迭代优化。关键指标:
# 告警统计查询(Prometheus UI中执行)
# 每日告警总数趋势
sum by (day) (
changes(ALERTS_FOR_STATE{alertstate="firing"}[1d])
)
# 平均告警持续时间
avg_over_time(
ALERTS{alertstate="firing"}[1d]
) * 24 * 3600
# 最频繁触发的告警规则TOP10
topk(10,
sum by (alertname) (
increase(ALERTS_FOR_STATE{alertstate="firing"}[7d])
)
)
优化策略:
- 高频低修告警降级:每周触发超过20次但无实际处理的告警,将severity从warning降为info,或直接静默
- 短时高频告警增加for窗口:频繁抖动触发的告警,将
for从1m提高到5m或10m - 关联告警引入抑制规则:发现固定的上下游告警关联模式时,配置inhibit_rules让上游告警抑制下游
- 定期Review:每月对告警进行一次Review会议,下线无效规则,新增遗漏场景
告警通知模板定制
Alertmanager支持Go template定制通知内容,让告警信息更有可读性:
# 在alertmanager.yml的templates段引用模板文件
templates:
- '/etc/alertmanager/templates/*.tmpl'
模板文件示例(wechat.tmpl):
{{ define "wechat.default.message" }}
{{- if gt (len .Alerts.Firing) 0 -}}
【告警触发】共 {{ len .Alerts.Firing }} 条
{{ range .Alerts.Firing }}
━━━━━━━━━━━━━━━━
告警: {{ .Labels.alertname }}
级别: {{ .Labels.severity }}
实例: {{ .Labels.instance }}
详情: {{ .Annotations.description }}
触发时间: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
{{- end }}
{{- if gt (len .Alerts.Resolved) 0 -}}
【告警恢复】共 {{ len .Alerts.Resolved }} 条
{{ range .Alerts.Resolved }}
━━━━━━━━━━━━━━━━
告警: {{ .Labels.alertname }}
实例: {{ .Labels.instance }}
恢复时间: {{ .EndsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
{{- end }}
{{ end }}
在receiver中引用该模板:
receivers:
- name: 'warning-wechat'
webhook_configs:
- url: 'http://localhost:9099/wechat'
send_resolved: true
# 企微/钉钉通过webhook的message字段传递模板内容
send_resolved: true确保告警恢复时也发送通知,方便值班人员确认问题已解决。模板中通过.Alerts.Firing和.Alerts.Resolved分别处理触发和恢复的告警列表。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/prometheus-gao-jing-jiang-zao-shi-zhan-alertmanager-fen-zu/