alertmanager / amtool —— 告警分组、抑制、路由
一句话定义
alertmanager 是 Prometheus 全家桶的告警分发组件:接收 prometheus 发来的告警,按规则分组、抑制、静默、路由到不同接收方(PagerDuty / 钉钉 / Slack / 邮件 / Webhook)。amtool 是它的命令行客户端,比 web UI 更适合自动化。
典型场景
- 看当前 firing 告警:
amtool alert - 创建临时静默(升级窗口):
amtool silence add - 验证配置:
amtool check-config - 路由测试(哪条 receiver 会收到):
amtool config routes test - 批量管理 silence
Prometheus 触发 alert,alertmanager 分发。两个分开理解。
装
amtool 装:
# 单机
apt install prometheus-alertmanager # Ubuntu
# 容器 / K8s 里 alertmanager pod 自带 amtool
kubectl exec -n monitoring alertmanager-xxx-0 -- amtool --help
# 单独下载
curl -L https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz | tar xz
mv alertmanager-*/amtool /usr/local/bin/
amtool 配置(让它知道 alertmanager 在哪)
# 选项 1:每次命令行加
amtool --alertmanager.url http://amgr:9093 alert
# 选项 2:写配置文件
mkdir -p ~/.config/amtool
cat > ~/.config/amtool/config.yml <<'EOF'
alertmanager.url: http://amgr:9093
EOF
amtool alert # 自动读 config
K8s 里通常 port-forward:
kubectl port-forward -n monitoring svc/alertmanager 9093:9093 &
看 firing 告警
amtool alert
# Alertname Starts At Summary
# KubeNodeNotReady 2026-05-27 14:00:00 UTC Node m4 not ready
# HighMemoryUsage 2026-05-27 14:05:00 UTC Pod memory > 80%
# ...
amtool alert --inhibited # 含被抑制的
amtool alert --silenced # 含被静默的
amtool alert --active # 只看 active(默认)
amtool alert -o extended # 详细输出
按 label 过滤:
amtool alert alertname=HighMemoryUsage
amtool alert severity=critical
amtool alert namespace=my-app
label=value 是 selector 语法。
静默(silence)
升级窗口、计划维护、误报抑制 —— 都靠 silence。
添加 silence
# 静默某 alert 4 小时
amtool silence add alertname=HighMemoryUsage --duration=4h --comment="维护中"
# 静默某 ns 所有 alert 1 小时
amtool silence add namespace=my-app --duration=1h --comment="升级"
# 静默某 severity 30 分钟
amtool silence add severity=warning --duration=30m --comment="噪音过滤"
# 多 label
amtool silence add severity=warning namespace=test --duration=1h
看现有 silence
amtool silence query
amtool silence query --within=1h # 1 小时内创建的
amtool silence query expired # 过期的
amtool silence query <id> # 看单个
删 silence
amtool silence expire <silence-id> # 让它立即过期
amtool silence expire $(amtool silence query -q) # 删所有(小心)
-q quiet 模式只输出 ID(管道用)。
验证配置
amtool check-config /etc/alertmanager/alertmanager.yml
# Checking '/etc/alertmanager/alertmanager.yml'
# SUCCESS
# Found:
# - global config
# - route
# - 5 inhibit rules
# - 10 receivers
# - 5 templates
改完 amgr 配置必跑这条——避免 reload 失败。
CI 流水线里:
amtool check-config alertmanager.yml || exit 1
路由测试 —— 哪个 alert 会去哪个 receiver
这是 amtool 最强大的功能:给定一组 label,告诉你这个 alert 会走到哪条 receiver。
amtool config routes test alertname=HighMemoryUsage severity=critical
# Matches the following routes:
# default-route → critical-pagerduty
或者交互式:
amtool config routes
# 显示路由树
写完复杂 route 必跑这个验证。
看 receiver 列表
amtool config show
# 输出整个 alertmanager 配置(mask 敏感字段)
Alertmanager 配置心智模型
# /etc/alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.example.com:587'
# 模板(用于消息渲染)
templates:
- '/etc/alertmanager/templates/*.tmpl'
# 路由树:从 root 开始匹配 → 命中 → receiver
route:
receiver: default-email
group_by: ['alertname', 'cluster']
group_wait: 10s
group_interval: 5m
repeat_interval: 4h
routes:
- matchers:
- severity=~"critical|emergency"
receiver: pagerduty
continue: false # 默认不 continue
- matchers:
- team=infra
receiver: slack-infra
# 接收方定义
receivers:
- name: default-email
email_configs:
- to: 'oncall@example.com'
- name: pagerduty
pagerduty_configs:
- service_key: 'xxx'
- name: slack-infra
slack_configs:
- api_url: 'https://hooks.slack.com/...'
# 抑制规则(某 alert 触发时压制其它 alert)
inhibit_rules:
- source_matchers: ['severity=critical']
target_matchers: ['severity=warning']
equal: ['alertname', 'instance'] # 同 alertname + instance 时
核心机制
- 分组(group_by)—— 把相同 group 的多个 alert 聚合成一个通知
- 抑制(inhibit)—— 某 alert 在 firing 时压制其它 alert
- 静默(silence)—— 临时关闭某些 alert(amtool silence add)
- 路由(route)—— 把 alert 分配给合适的 receiver
reload 配置
# 通过 HTTP(要启动时加 --web.enable-lifecycle)
curl -X POST http://amgr:9093/-/reload
# 或者 send SIGHUP
kubectl exec -n monitoring alertmanager-xxx-0 -- kill -HUP 1
HTTP API(用 curl 调)
# 看 alerts
curl -s http://amgr:9093/api/v2/alerts | jq
# 看 silences
curl -s http://amgr:9093/api/v2/silences | jq
# 创建 silence
curl -X POST http://amgr:9093/api/v2/silences \
-H 'Content-Type: application/json' \
-d '{
"matchers": [{"name":"alertname","value":"HighMem","isRegex":false}],
"startsAt": "2026-05-27T14:00:00Z",
"endsAt": "2026-05-27T18:00:00Z",
"createdBy": "alice",
"comment": "维护"
}'
# 删 silence
curl -X DELETE http://amgr:9093/api/v2/silence/<id>
# 看状态
curl -s http://amgr:9093/api/v2/status | jq
集群模式(HA)
生产 alertmanager 都跑 2-3 副本(防单点)。它们之间用 gossip 同步状态(silence、notification log),避免重复发:
# alertmanager Deployment args
- --cluster.listen-address=0.0.0.0:9094
- --cluster.peer=alertmanager-0.alertmanager:9094
- --cluster.peer=alertmanager-1.alertmanager:9094
kube-prometheus-stack helm 默认装 3 副本 + 自动配 peer。
看集群状态:
amtool cluster show
# Cluster Status: ready
# Peers:
# 10.244.0.5:9094
# 10.244.1.6:9094
实战场景
1. 升级集群前批量 silence
# 静默 monitoring 整个 ns 2 小时
amtool silence add namespace=monitoring \
--duration=2h \
--comment="K8s upgrade $(date +%F)"
# 静默 K8s 节点 ready 类告警
amtool silence add alertname=~"Kube.*NotReady|KubeletDown" \
--duration=2h \
--comment="rolling upgrade"
2. 误报抑制 —— 临时静默某个 noisy alert
amtool silence add alertname=DiskSpaceLow instance=worker-broken-disk \
--duration=24h \
--comment="盘要换、忽略告警"
3. 看哪些 alert 没人管(没静默没解决)
amtool alert --active | grep -v Silenced
4. 验证路由(写新规则后)
# 拿一个真实 alert 的 labels
kubectl exec -n monitoring alertmanager-0 -- amtool alert -o json | jq '.[0].labels'
# 测试这套 labels 会路由到哪
amtool config routes test alertname=KubeNodeNotReady severity=critical
# → infra-pagerduty
5. CI 验证 alertmanager.yml
amtool check-config alertmanager.yml || exit 1
amtool check-config alertmanager.yml --templates=templates/*.tmpl
6. 用 webhook 接收测试
写个简单的 webhook 验证 receiver 配对了:
# 临时起 webhook 服务(Python)
python3 -m http.server 8000
# alertmanager 配 receiver:
# webhook_configs:
# - url: http://my-host:8000/alert
# 触发一个测试 alert(用 amtool)
amtool alert add alertname=Test severity=critical \
--start="$(date -u +%FT%TZ)" \
--annotation=summary="test alert"
amtool alert add —— 手动触发 alert
测试 alertmanager 而不是真的需要 prometheus 触发:
amtool alert add alertname=TestAlert severity=critical \
--annotation=summary="测试告警" \
--start="$(date -u +%FT%TZ)"
会进 alertmanager 像真 alert 一样被处理。写新 route 时验证用。
常见踩坑
坑 1:silence 创建了但 alert 还在通知
amtool silence query
# 看到 silence 在
amtool alert
# alert 还显示 active 而不是 Silenced
可能:
- silence 的 matchers 没匹配上 alert 的 labels
- silence 还没生效(
startsAt是未来时间)
调试:
amtool silence query <id>
# Matchers: alertname=Foo
# Starts: ...
# Ends: ...
amtool alert -o extended | grep -i foo
# 看 alert 的实际 labels —— 必须包含 silence 的全部 matchers
坑 2:notification 重复发
正常 alert 每 repeat_interval(默认 4h)会再发一次提醒。要更稀疏:
route:
repeat_interval: 24h
或者按 severity 分:
routes:
- matchers: [severity=critical]
receiver: pagerduty
repeat_interval: 30m # critical 半小时重复
- matchers: [severity=warning]
receiver: slack
repeat_interval: 12h # warning 12 小时重复
坑 3:alertmanager HA 多个 receiver 重复发
3 个副本都在 firing alert ABC
通知发了 3 次(每个副本各发一次)
通常是 cluster gossip 没正常工作 —— --cluster.peer 没配对、或者 peer pod 网络不通。
amtool cluster show
# 应该看到所有 peer
修:检查 peer DNS / port 9094 是否通。
坑 4:路由 continue: true 反直觉
routes:
- matchers: [severity=critical]
receiver: pagerduty
continue: true # 命中后继续匹配下面的路由
- matchers: [severity=critical]
receiver: slack # 也会发
continue: true 让 critical alert 同时发 pagerduty + slack。默认 false(命中即停)。
需要某 alert 发多个 receiver 时用,但容易翻车——通知重复看着像 bug。preferred做法:写一个 multi-channel receiver。
坑 5:amtool config show 含敏感信息
amtool config show
# 密码 / API key 显示在输出(最新版会 mask、老版不会)
不要随便公开输出。
坑 6:路由树深度
route:
routes:
- routes:
- routes:
- receiver: x # 4 层
可以但难维护。保持路由树 ≤ 2 层。复杂条件用 matchers 而不是嵌套。
坑 7:matchers vs match / match_re 老语法
# 老写法(仍支持但不推荐)
match:
severity: critical
match_re:
alertname: ".*Down"
# 新写法(推荐,amgr 0.22+)
matchers:
- severity = critical
- alertname =~ ".*Down"
新配置全用 matchers。
坑 8:reload 没生效
curl -X POST http://amgr:9093/-/reload
# {"status":"error","errorType":"unavailable"}
没启 lifecycle API。改启动参数:
args:
- --web.enable-lifecycle
或者发 SIGHUP:
kubectl exec -n monitoring alertmanager-0 -- kill -HUP 1
坑 9:silence 太多让 amgr 慢
amtool silence query | wc -l
# 1000+
silence 默认在状态文件里存所有历史。清理过期的:
amtool silence query expired -q | xargs -r -I {} amtool silence expire {}
# 或者 alertmanager 自己定期清(24h 后过期自动删)