别跟我讲什么上周被告警吵醒了三次这种故事,直接进入正题。你要治理告警,先把这四条红线记住,碰一条就翻车:
严禁操作清单:
处置总原则,刻在脑门上:
先分级定责,再逐条降噪;先保关键告警,再减无效告警。
意思是:你得先搞清楚哪些告警是要命的,保住它们别漏;然后回头去砍那些天天响但没人管的。顺序不能反。
第一步:正确开局——先盘家底,别急着调规则
很多兄弟上来就改阈值、加抑制,改完发现更乱了。不对。你得先知道自己有多少烂摊子。
1. 盘清楚这些数字
- 当前一共有多少条告警规则?
- 每天产生多少条告警?
- 这里面多少是误报?多少是有效告警?
- 哪些告警从配置那天起就没人处理过?
- 值班工程师处理一条告警平均花多久?
怎么查?命令直接拿走。
导出Prometheus所有告警规则:
curl -s http://<prometheus-addr>:9090/api/v1/rules \\
| jq '.data.groups[].rules[] | {name: .name, state: .state, health: .health, query: .query}' \\
> alert_rules_export.json
# 看看一共多少条
cat alert_rules_export.json | jq -s 'length'
导出Alertmanager当前活跃告警:
amtool –alertmanager.url=http://<alertmanager-addr>:9093 alert query -o json > active_alerts.json
统计过去7天告警触发次数TOP20(Prometheus侧):
curl -s 'http://<prometheus-addr>:9090/api/v1/query?query=ALERTS{alertstate="firing"}[7d]' \\
| jq -r '.data.result[].metric.alertname' \\
| sort | uniq -c | sort -rn | head -20
如果你用的是Grafana告警,走API:
curl -s -H "Authorization: Bearer <your-token>" \\
http://<grafana-addr>:3000/api/alert-rules \\
| jq '.[] | {title: .title, uid: .uid, state: .state}' > grafana_alert_rules.json
2. 定优先级
拿到数据以后,按这个顺序排:
3. 按四类收敛
把所有告警规则归到四个桶里:
| 可用性 | 服务挂了、接口5xx、健康检查失败 |
| 性能 | 接口响应时间过长、数据库慢查询 |
| 容量 | 磁盘快满了、内存不足、连接池耗尽 |
| 安全 | 异常登录、权限变更、漏洞扫描 |
别混在一起。安全告警和性能告警走不同的通知通道,看的人不一样。
4. 区分三种告警
- 有效告警:真出故障了,需要人去处理。
- 误报:规则写得有问题、阈值不合理,实际上没事。
- 无效告警(僵尸告警):配了但没人能处理、没人负责,或者对应的服务早就下线了。
僵尸告警最恶心,天天响,值班划掉,下周继续响。这种直接标记"待废弃",走审批删掉。
第二步:实施主链路——一步步走
环节一:导出告警规则 + 命中次数
上面命令已经给了。重点看什么?看health字段。如果大量规则health是err,说明你的PromQL写错了或者数据源有问题,告警根本没在工作,属于"你以为你在监控,其实你在裸奔"。
环节二:按告警类型/对象/时间聚合统计TOP
# 按告警名统计
cat active_alerts.json | jq -r '.[].labels.alertname' | sort | uniq -c | sort -rn | head -20
# 按实例/机器统计,看是不是某台机器在疯狂报警
cat active_alerts.json | jq -r '.[].labels.instance' | sort | uniq -c | sort -rn | head -10
# 按时间段统计(需要结合日志或者告警历史接口)
# 这里用alertmanager的api查最近24h
amtool –alertmanager.url=http://<alertmanager-addr>:9093 alert query –active
现象对应问题:
- 某个alertname占了80%的量 → 这条规则阈值或表达式有问题,重点查。
- 某台instance告警特别多 → 可能是单机问题,也可能是采集异常。
- 凌晨2-5点告警集中爆发 → 大概率是定时任务、备份、日志轮转引起的,不是真故障。
环节三:分析单条告警完整链路
一条告警从产生到关闭,链路是这样的:
指标采集(Prometheus/Agent) → 规则评估(Recording/Alerting Rule)
→ 触发条件满足 → Alertmanager接收 → 去重/分组/抑制/静默
→ 通知通道(Webhook/邮件/钉钉/飞书/电话) → 值班人收到
→ 确认 → 处理 → 关闭 → 复盘记录
每一环都可能出问题:
- 采集断了 → 告警漏报
- 规则评估间隔太长(evaluation_interval设了5分钟) → 告警延迟
- Alertmanager没配对路由 → 告警发了但没人收
- 通知通道挂了(钉钉token过期、邮件SMTP不通) → 告警到了门口进不来
- 值班人收到没确认 → 没有闭环
检查Alertmanager路由是否正常:
amtool –alertmanager.url=http://<alertmanager-addr>:9093 config routes
检查通知通道是否通畅(手动触发测试告警):
amtool –alertmanager.url=http://<alertmanager-addr>:9093 alert add \\
alertname=TestAlert severity=critical instance=test-01 \\
summary="告警通道测试,请忽略"
看到值班群里收到消息了,说明通道没问题。收不到,先去查webhook地址、token、防火墙。
环节四:阈值合理性评估
别拍脑袋。拿历史数据说话。
# 查某个指标过去30天的P99值
curl -s 'http://<prometheus-addr>:9090/api/v1/query?query=quantile_over_time(0.99, http_request_duration_seconds[30d])'
# 查CPU过去7天的最大值
curl -s 'http://<prometheus-addr>:9090/api/v1/query?query=max_over_time(node_cpu_seconds_total{mode!="idle"}[7d])'
原则: 阈值要基于你业务自己的基线。别人的80%跟你没关系。你的服务常年跑在75%CPU,那你告警线至少得85%以上。你的服务平时5%,突然到30%就该叫了。
环节五:告警分级配置
按严重程度分P1-P4:
| P1 | 核心业务不可用 | 电话 + 短信 + IM | 5分钟内响应 |
| P2 | 核心业务降级/性能严重劣化 | 短信 + IM | 15分钟内响应 |
| P3 | 非核心业务异常 | IM | 工作时间处理 |
| P4 | 信息类/趋势预警 | 邮件 | 有空看就行 |
Alertmanager路由配置示例:
route:
receiver: 'default'
group_by: ['alertname', 'cluster']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
– match:
severity: critical
receiver: 'oncall-phone'
group_wait: 10s
repeat_interval: 15m
– match:
severity: warning
receiver: 'oncall-im'
repeat_interval: 1h
– match:
severity: info
receiver: 'dev-email'
repeat_interval: 12h
receivers:
– name: 'oncall-phone'
webhook_configs:
– url: 'http://<phone-gateway>/call'
– name: 'oncall-im'
webhook_configs:
– url: 'https://oapi.dingtalk.com/robot/send?access_token=<your-token>'
– name: 'dev-email'
email_configs:
– to: 'dev-team@company.com'
现象对应问题:
- P1告警用的是邮件通知 → 半夜没人看邮件,漏了。
- P4告警用了电话 → 值班被你骂死。
- 所有告警都走了同一个receiver → 没分级,等于没配。
环节六:抑制与聚合规则
聚合(group_by): 同一个alertname、同一个集群的告警合并成一条通知,别一条一条发。
route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s # 等新告警凑一凑,30秒内同组的一起发
group_interval: 5m # 同组告警有更新时,至少等5分钟再发下一波
repeat_interval: 4h # 同一条告警没恢复,4小时后再提醒一次
抑制(inhibit_rules): 比如整个机房网络断了,那机房里所有机器的"主机不可达"告警就不要再发了。
inhibit_rules:
– source_match:
alertname: 'DatacenterDown'
severity: 'critical'
target_match:
alertname: 'HostUnreachable'
equal: ['datacenter']
静默窗口(Silence): 已知维护时间段,提前设静默。
# 给某个告警设2小时静默
amtool –alertmanager.url=http://<alertmanager-addr>:9093 silence add \\
alertname="DiskSpaceLow" instance="prod-db-01" \\
–comment="计划扩容磁盘" \\
–duration="2h"
# 查看当前静默
amtool –alertmanager.url=http://<alertmanager-addr>:9093 silence query
⚠️ 生产环境风险提醒: 抑制规则写错了会把关键告警也吞掉。加完抑制一定要用amtool check-config验证配置,再reload。
环节七:告警接收人/值班组配置
别把告警发给离职的人、别发给不负责这块业务的人。
如果你用Grafana OnCall或者PagerDuty,直接在上面排值班表。如果没有,最简单的方式是用钉钉/飞书群机器人的webhook,配合一个定时脚本换webhook地址。
# 示例:通过crontab每周日切换值班webhook
# crontab -e
0 0 * * 0 /opt/scripts/rotate_oncall_webhook.sh
环节八:告警闭环流程
一条告警的生命周期必须走完这四步:
确认(Acknowledge) → 处理(处理中状态) → 关闭(Resolved) → 复盘(记录根因和处理动作)
如果你用的Alertmanager原生能力有限,建议接一个工单系统或者用Grafana OnCall。至少做到:
- 收到告警 → 在群里回复"收到,在处理"(确认)
- 处理完 → 在告警平台点Resolved或者回复"已处理,原因xxx"(关闭)
- 每周值班交接 → 把本周未关闭的告警过一遍(复盘)
现象对应问题:
- 告警自动恢复了但没人确认 → 不知道是误报还是自愈,下次再响照样慌。
- 告警挂了一周没关闭 → 值班列表里全是历史告警,新告警淹没在里面。
第三步:高频现场逐个拆
场景1:同一告警每小时轰炸几十条
现象: 值班手机一直在震,打开一看全是同一个HighMemoryUsage,50台机器每台一条。
原因: 没配聚合,或者group_by没包含alertname。
处理:
# alertmanager.yml
route:
group_by: ['alertname', 'cluster']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
改完reload:
curl -X POST http://<alertmanager-addr>:9093/-/reload
改完50条变成1条汇总消息:“HighMemoryUsage 在 cluster-prod 集群有50个实例触发”。
场景2:深夜误报警
现象: 凌晨3点DiskIOHigh告警,值班爬起来一看,是定时备份在跑,磁盘IO本来就会高。
原因: 阈值没考虑定时任务的基线波动,或者维护窗口没设。
处理:
方案A:改PromQL,排除备份时段:
# 原始
– alert: DiskIOHigh
expr: rate(node_disk_io_time_seconds_total[5m]) > 0.9
# 改后:只在非备份时间(6:00-23:00)报警
– alert: DiskIOHigh
expr: rate(node_disk_io_time_seconds_total[5m]) > 0.9
and ON() (hour() > 6 and hour() < 23)
方案B:设静默窗口(上面amtool silence add命令,或者Alertmanager的mute_time_intervals)。
# alertmanager.yml
time_intervals:
– name: backup–window
time_intervals:
– times:
– start_time: '02:00'
end_time: '04:00'
route:
routes:
– match:
alertname: 'DiskIOHigh'
mute_time_intervals:
– backup–window
场景3:告警发给了不值班的人
现象: 周六告警发给了周一到周五值班的老王,老王在外面带娃,没看到。
原因: 接收人写死了,没跟排班表联动。
处理: 引入值班轮换。如果不想上Grafana OnCall这种平台,最低成本方案是用一个变量webhook:
receivers:
– name: 'oncall-im'
webhook_configs:
– url: 'http://<internal-service>/get-current-oncall-webhook'
后端服务根据当天日期返回当前值班人的webhook地址。
场景4:关键故障没人收到告警
现象: 支付接口挂了20分钟,客户投诉了才知道。查告警平台,没有告警记录。
原因: 漏配规则、路由配错、或者通知通道token过期。
处理:
# 1. 确认规则存不存在
curl -s http://<prometheus-addr>:9090/api/v1/rules | jq '.data.groups[].rules[] | select(.name == "PaymentServiceDown")'
# 2. 确认Alertmanager路由能不能匹配
amtool –alertmanager.url=http://<alertmanager-addr>:9093 config routes
# 3. 手动触发测试(上面给过的amtool alert add命令)
逐个排查,八成是路由没匹配到正确的receiver,或者webhook地址404了。
场景5:告警太多干脆全关
现象: 值班被搞崩溃了,直接在Alertmanager把所有告警静默了,或者直接stop了Alertmanager进程。
原因: 告警疲劳到了临界点。
处理: 这就是开篇说的红线第一条。先恢复,然后用第一步的方法盘TOP误报,先把前5个高频误报处理掉,告警量通常能降50%以上。别走极端。
场景6:安全告警和性能告警混在一起
现象: 值班群里同时出现"CPU使用率超80%“和"检测到异常SSH登录”,值班运维看到CPU告警去查了,安全告警被刷过去了。
原因: 没分级、没分路由。
处理: 按前面说的四类(可用性、性能、容量、安全)加label区分,Alertmanager里配不同route走不同receiver。安全告警走安全团队,性能告警走运维团队。
route:
routes:
– match:
category: 'security'
receiver: 'security-team'
– match:
category: 'performance'
receiver: 'ops-team'
场景7:告警处理了没人记录
现象: 同一个告警每周响一次,每次都"看一眼没事",从来没记录过为什么没事。三个月后真出事了,查历史记录一片空白。
原因: 没有闭环流程。
处理: 强制要求每条告警必须有处理记录。最简方案:在钉钉/飞书群里用固定格式回复:
【告警闭环】
告警名:HighMemoryUsage
触发时间:2026-09-01 03:00
处理人:张三
处理结果:误报,原因是定时任务内存峰值
后续动作:调整阈值为85% / 加入静默窗口
嫌麻烦就上Grafana OnCall或者接Jira自动建工单。
第四步:落地与推广——分场景给策略
三个阶段,别想一步到位
| 止血 | 降噪高频误报 | 1-2周 | 干掉TOP10误报,加聚合,设静默 |
| 治理 | 分级+聚合+路由 | 1-2月 | 全量告警分级P1-P4,配路由,配值班 |
| 运营 | 定期复盘 | 持续 | 每周看告警统计,每月复盘,持续优化 |
先止血。值班兄弟快被搞疯了,你上来就搞分级体系,人家没空配合你。先帮他把每天200条降到50条,他才会支持你后面做的事。
核心业务 vs 边缘业务
- 核心业务(支付、订单、登录): 宁可多报,不可漏报。阈值可以敏感一点,P1级别,电话通知。
- 边缘业务(内部后台、报表导出): 阈值放宽,P3/P4级别,IM或邮件。没人半夜爬起来修报表系统。
7×24值班 vs 工作时间值班
- 7×24值班: P1/P2走电话/短信,任何时间都通知。P3/P4走IM,可以设夜间静默。
- 工作时间值班: 所有告警都走IM/邮件,P1可以加电话但仅限工作时间。非工作时间P1告警发到群里,依赖第二天早上处理。
什么时候宁可保留冗余告警
关键业务的可用性告警。你不确定ServiceDown和HealthCheckFailed是不是重复了?都留着。 关键业务少报一个告警的代价是线上事故,多报一个的代价是值班多看一眼。你自己选。
告警规则变更走审批留痕
改阈值、加抑制、删规则,都要走审批。最简单的办法:所有告警规则用Git管理(Grafana的provisioning或者Prometheus的rules文件放在Git仓库),改规则提PR,至少一个人review。别直接上去改配置文件,出了问题说不清谁改的。
# 示例:告警规则Git仓库结构
alert-rules/
├── core/
│ ├── payment.yml
│ └── order.yml
├── infra/
│ ├── node.yml
│ └── database.yml
└── security/
└── auth.yml
第五步:根因分析——告警疲劳到底怎么来的
干了几年,告警疲劳的根因翻来覆去就这几个:
规则没有按业务基线配置。 从网上抄了一套Prometheus告警规则直接导入,阈值是人家业务的,不是你的。你的服务CPU常年70%,人家设的阈值75%,你天天报警。
阈值拍脑袋定。 “CPU超过80%就告警吧。” 为什么80%?不知道。没有任何数据支撑。
没有聚合抑制。 50台机器同一秒触发同一个告警,发50条消息。这不是监控,这是DDoS值班工程师。
没有分级。 P1和P4一样响、一样发通知。狼来了喊多了,真狼来了也没人动。
告警与值班脱节。 规则配好了,通知发给一个固定邮箱,值班的人从来不看那个邮箱。
缺少复盘机制。 告警响了就处理,处理完就忘。没有人回头看哪些告警是误报、哪些规则需要调整。
怎么定位清楚? 把告警统计数据(哪些规则触发最多、什么时间段集中)和值班记录(哪些告警处理了、哪些标记为误报、哪些没管)对照着看。触发100次、值班标记误报95次的规则,就是你需要治理的第一优先级。
第六步:事后加固要点
治理完不是结束。你得有机制防止退回原样。
| 告警规则按业务基线重设 | 每季度用quantile_over_time拉一次历史数据,校准阈值 |
| 分级+分路由 | 新加告警必须带severity和category label,否则合并不进主干配置 |
| 聚合抑制与静默窗口 | 所有维护操作必须提前加silence,写进SOP |
| 值班表自动化 | 值班轮换与通知通道联动,别手动改webhook |
| 告警闭环SLA | 明确P1五分钟响应、P2十五分钟响应,写进值班手册 |
| 定期告警复盘会 | 每周五花15分钟过一遍本周告警清单 |
| 告警质量指标 | 每周统计:误报率(误报数/总告警数)、漏报率(事故数-告警数/事故数)、平均响应时长 |
⚠️ 生产环境风险提醒: 改完Alertmanager配置一定要先check再reload:
amtool check-config /etc/alertmanager/alertmanager.yml
curl -X POST http://<alertmanager-addr>:9093/-/reload
别直接reload,配置有语法错误Alertmanager会拒绝加载,但旧配置还在跑。你以为你生效了新规则,其实还在用旧的。
第七步:踩坑清单
最后总结,治理告警过程中我踩过和看别人踩过的坑:
| 为了安静关告警 | 线上挂了没人知道,你背锅 |
| 阈值全调高 | 真实故障来了没触发,客户先发现 |
| 不分级全推给值班 | 值班三天就辞职 |
| 告警没闭环处理 | 同一个问题反复响,浪费所有人时间 |
| 深夜误报没人管 | 值班被折腾到崩溃,开始关告警(回到第一个坑) |
| 安全告警被性能告警淹没 | 被入侵了三天后才发现 |
| 加了抑制把关键告警也吞了 | 机房断网了,你因为配了"网络异常时抑制主机告警",连主机不可达都收不到,以为一切正常 |
最后一个坑最阴。加抑制的时候一定要想清楚:source_match条件会不会过于宽泛。建议先在测试环境用amtool test-routing验证路由和抑制效果。
# 测试一条告警会走哪个路由
amtool –alertmanager.url=http://<alertmanager-addr>:9093 test-routing \\
–labels alertname=HighMemoryUsage severity=warning cluster=prod
写在最后
告警治理这事不是一次性的项目,是持续运营的活。你今天把误报率从60%降到20%,下个月业务上了新功能,又冒出一堆新告警。正常的。关键是你要把"盘现状→分级→降噪→闭环→复盘"这个流程跑起来,变成习惯。
值班工程师是人,不是告警接收器。你少发一条垃圾告警,他就多一分精力去看那条真正要命的P1。
就这样,希望这篇能帮你少熬几个夜。
觉得有用的话,点个赞👍 收藏⭐ 一下,下次告警轰炸的时候翻出来照着做。有问题评论区聊,看到都会回。关注博主,后续更新SRE实战系列。



