Alertmanager 实战:告警路由、分组、静默与 PagerDuty/钉钉集成
深入讲解 Prometheus Alertmanager 的核心能力:路由树(route tree)将不同告警分发到不同接收者、告警分组(grouping)合并同类告警减少噪音、静默(silence)和抑制(inhibition)规则、与钉钉/飞书/PagerDuty 集成,以及告警升级策略的完整生产配置。
Prometheus 负责发现告警(PromQL 规则求值),Alertmanager 负责处理告警(路由、分组、去重、通知)。很多团队 Prometheus 配置正确但 Alertmanager 配置混乱,导致告警风暴(同一故障发出几十条通知)或漏报(重要告警被淹没)。本文讲解 Alertmanager 的核心机制和生产级配置。
Alertmanager 核心概念
Prometheus → (告警规则触发) → 告警 → Alertmanager → 通知接收者
Alertmanager 做什么:
1. 接收 Prometheus 发来的告警
2. 分组(Grouping):同类告警合并(一个服务挂了,10 个节点的告警 → 1 条通知)
3. 抑制(Inhibition):高严重性告警触发时,屏蔽低严重性告警
4. 静默(Silence):维护窗口期间临时屏蔽告警
5. 路由(Routing):根据标签把告警发给正确的团队
6. 通知(Notification):Email/Slack/钉钉/PagerDuty
告警状态:
pending → 告警触发但还没超过 for 时间(Prometheus 内部)
firing → 持续超过 for 时间,发给 Alertmanager
resolved → 告警恢复,Alertmanager 发恢复通知
一、Alertmanager 配置结构
# alertmanager.yml 基本结构
global:
# 全局默认值
resolve_timeout: 5m # 告警恢复后等多久发恢复通知(默认 5m)
smtp_smarthost: 'smtp.company.com:587'
smtp_from: 'alertmanager@company.com'
smtp_auth_username: 'alerts@company.com'
smtp_auth_password: 'secret'
# 路由树(必须配置)
route:
receiver: 'default' # 默认接收者(未匹配任何子路由时使用)
group_by: ['alertname', 'cluster', 'namespace']
group_wait: 30s # 收到第一条告警后等 30s 再发(等其他同组告警聚合)
group_interval: 5m # 同组有新告警时,5 分钟后发通知(不是每条都发)
repeat_interval: 4h # 告警持续时,4 小时重发一次(避免被遗忘)
routes:
# 子路由 1:关键业务告警 → PagerDuty(立即通知)
- matchers:
- severity="critical"
receiver: pagerduty
group_wait: 5s # 关键告警快速通知
repeat_interval: 1h
# 子路由 2:Kubernetes 相关告警 → 基础设施团队
- matchers:
- team="infra"
receiver: slack-infra
# 子路由 3:业务告警 → 业务开发团队
- matchers:
- team="dev"
receiver: dingtalk-dev
# 抑制规则
inhibit_rules:
- source_matchers:
- severity="critical"
target_matchers:
- severity="warning"
equal: ['alertname', 'cluster', 'namespace']
# 当同一 alertname/cluster/namespace 已有 critical 告警时,
# 屏蔽对应的 warning 告警(减少噪音)
# 接收者定义
receivers:
- name: 'default'
email_configs:
- to: 'oncall@company.com'
- name: 'pagerduty'
pagerduty_configs:
- integration_key: 'xxx'
- name: 'slack-infra'
slack_configs:
- api_url: 'https://hooks.slack.com/services/xxx'
channel: '#infra-alerts'
- name: 'dingtalk-dev'
webhook_configs:
- url: 'http://dingtalk-webhook:8060/dingtalk/dev/send'
二、路由树详解
# 路由树的匹配逻辑:
# 从根 route 开始,遍历子路由
# 找到第一个匹配的子路由就停止(默认)
# continue: true 可以继续匹配后续路由(允许一条告警发给多个接收者)
route:
receiver: default
routes:
# 精确匹配:job 标签
- matchers:
- job="mysql"
receiver: dba-team
# 正则匹配
- matchers:
- alertname=~"KubernetesNode.*" # 正则:以 KubernetesNode 开头
receiver: k8s-team
# 多条件匹配(AND 关系)
- matchers:
- namespace="production"
- severity="critical"
receiver: prod-oncall
continue: true # 继续匹配,还会发给后续匹配的接收者
- matchers:
- severity="critical"
receiver: pagerduty # critical 的也发 PagerDuty
三、分组配置最佳实践
# 分组的作用:把相同类型的告警合并成一条通知
# 避免:一台服务器 10 个 Pod 都挂了,发 10 条告警
route:
# 全局分组:按集群和命名空间分组
group_by: ['cluster', 'namespace']
group_wait: 30s # 等 30 秒收集同组的所有告警再一起发
group_interval: 5m # 同组有新告警后,5 分钟内不重复发(合并通知)
repeat_interval: 4h # 持续告警 4 小时重发一次
routes:
# 数据库告警:按实例分组(每个 DB 实例一条告警)
- matchers:
- job=~"mysql|postgres|redis"
group_by: ['instance', 'alertname']
group_wait: 10s
# Kubernetes Node 告警:按节点分组
- matchers:
- alertname=~"KubernetesNode.*"
group_by: ['node']
# 网络告警:按机房/区域分组
- matchers:
- team="network"
group_by: ['datacenter', 'alertname']
四、静默规则(Silence)
维护窗口期间,通过静默避免误告警。
# 方法1:Web UI
# http://alertmanager:9093 → Silences → New Silence
# 填写:
# Matchers: job="mysql-prod", instance="db-01:9104"
# Start: 2026-07-22 02:00:00
# End: 2026-07-22 04:00:00
# Comment: 数据库维护窗口
# 方法2:amtool 命令行
amtool --alertmanager.url=http://alertmanager:9093 \
silence add \
--start "2026-07-22T02:00:00+08:00" \
--end "2026-07-22T04:00:00+08:00" \
--comment "数据库维护" \
'job="mysql-prod"' 'instance="db-01:9104"'
# 查看所有静默
amtool silence list
# 取消静默
amtool silence expire <silence-id>
五、钉钉/飞书告警集成
Alertmanager 通过 webhook 接入国内通讯工具。
使用 prometheus-webhook-dingtalk
# docker-compose.yml(或 Kubernetes Deployment)
version: '3'
services:
dingtalk-webhook:
image: timonwong/prometheus-webhook-dingtalk:v2.1.0
ports:
- "8060:8060"
volumes:
- ./dingtalk.yml:/etc/prometheus-webhook-dingtalk/config.yml
alertmanager:
image: prom/alertmanager:v0.28.0
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
# dingtalk.yml(webhook 服务配置)
targets:
dev:
url: https://oapi.dingtalk.com/robot/send?access_token=xxxxx
secret: SECxxxxxxx # 加签密钥(钉钉机器人设置里获取)
ops:
url: https://oapi.dingtalk.com/robot/send?access_token=yyyyy
secret: SECyyyyyyy
mention:
all: false # 不 @全员
mobiles: ["138xxxxxxxx", "139xxxxxxxx"] # @特定人
# alertmanager.yml 中配置钉钉接收者
receivers:
- name: dingtalk-ops
webhook_configs:
- url: 'http://dingtalk-webhook:8060/dingtalk/ops/send'
send_resolved: true # 恢复时也发通知
- name: dingtalk-dev
webhook_configs:
- url: 'http://dingtalk-webhook:8060/dingtalk/dev/send'
send_resolved: true
自定义钉钉消息模板
# 在 dingtalk.yml 中自定义消息格式
targets:
ops:
url: https://oapi.dingtalk.com/robot/send?access_token=xxx
message:
title: '{{ template "ding.link.title" . }}'
text: '{{ template "ding.link.content" . }}'
# templates/dingtalk.tmpl
{{ define "ding.link.title" }}
{{ if eq .Status "firing" }}🔥 [告警] {{ else }}✅ [恢复] {{ end }}
{{ .GroupLabels.alertname }}
{{ end }}
{{ define "ding.link.content" }}
**状态:** {{ if eq .Status "firing" }}🔴 告警中{{ else }}🟢 已恢复{{ end }}
{{ range .Alerts }}
**告警:** {{ .Annotations.summary }}
**描述:** {{ .Annotations.description }}
**集群:** {{ .Labels.cluster }}
**命名空间:** {{ .Labels.namespace }}
**开始时间:** {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ if ne .EndsAt.String "0001-01-01 00:00:00 +0000 UTC" }}
**恢复时间:** {{ .EndsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
---
{{ end }}
{{ end }}
六、告警升级策略
# 场景:critical 告警 30 分钟未处理,升级到电话通知(PagerDuty)
route:
routes:
- matchers:
- severity="critical"
receiver: team-slack # 第一时间发 Slack
continue: true # 继续执行下面的路由
- matchers:
- severity="critical"
receiver: pagerduty
group_wait: 30m # 等 30 分钟(如果 30 分钟后还在 firing,PagerDuty 通知)
repeat_interval: 30m
# 另一种方案:通过 Alertmanager 的 repeat_interval 实现
# 第一次:Slack(立即)
# 30 分钟后告警还在:PagerDuty(升级)
receivers:
- name: 'escalation-receiver'
slack_configs:
- channel: '#oncall'
send_resolved: true
pagerduty_configs:
- integration_key: 'xxx'
description: '{{ .GroupLabels.alertname }} - 已持续超过 30 分钟'
七、验证与调试
# 检查 Alertmanager 配置语法
amtool check-config /etc/alertmanager/alertmanager.yml
# 测试路由(告警会路由到哪个 receiver)
amtool --alertmanager.url=http://alertmanager:9093 \
config routes test \
severity="critical" cluster="prod" namespace="production"
# Output: prod-oncall ← 会路由到这个接收者
# 查看当前 firing 的告警
amtool --alertmanager.url=http://alertmanager:9093 alert query
# 测试发送告警(调试 webhook 通道)
curl -XPOST http://alertmanager:9093/api/v1/alerts \
-H 'Content-Type: application/json' \
-d '[{
"labels": {
"alertname": "TestAlert",
"severity": "critical",
"cluster": "test"
},
"annotations": {
"summary": "测试告警",
"description": "这是一条测试告警"
}
}]'
# 查看 Alertmanager 日志
kubectl logs -n monitoring alertmanager-0 -c alertmanager --tail=50
小结
Alertmanager 的核心是路由树 + 分组 + 静默 + 抑制。路由树决定告警发给谁;分组合并同类告警(group_wait 等待聚合,group_interval 控制通知频率);静默在维护窗口屏蔽告警;抑制规则让 critical 发生时自动屏蔽 warning(减少噪音)。生产中钉钉/飞书集成推荐使用 prometheus-webhook-dingtalk 中间件,配合自定义模板让通知更可读。amtool config routes test 是验证路由配置的必备工具,可以在修改配置前验证路由逻辑是否符合预期。
