在 Prometheus 生态中,Prometheus 负责根据告警规则产生告警,而 Alertmanager 负责告警的后续全生命周期管理:分组、路由、抑制、去重和通知发送。一个配置不当的 Alertmanager 会让值班人员在凌晨被海量重复告警淹没,而精心设计的路由与抑制策略能确保"正确的人、在正确的时间、收到正确的告警"。

参考来源:Prometheus 官方文档 — Alertmanager

一、Alertmanager 架构

Alertmanager 的处理流水线分为五个阶段:

Prometheus 告警规则触发
┌───────────────┐     ┌───────────┐     ┌───────────┐     ┌───────────┐     ┌───────────┐
│   接收 Receive │ ──→ │ 分组 Group │ ──→ │ 路由 Route │ ──→ │ 抑制 Inhibit│ ──→ │ 去重 Dedup │
└───────────────┘     └───────────┘     └───────────┘     └───────────┘     └─────┬─────┘
                                                                          ┌───────────────┐
                                                                          │  发送 Notify   │
                                                                          │ 邮件/微信/钉钉  │
                                                                          └───────────────┘
阶段作用关键配置
接收接收来自 Prometheus 的告警receivers
分组将相同特征的告警合并为一批group_by
路由根据标签匹配决定告警去向routematchers
抑制当某告警触发时,静默相关低优先级告警inhibit_rules
去重多个 Alertmanager 实例间的告警去重HA 模式 + Gossip
发送通过配置的渠道发送通知webhook / email / 等

二、路由树设计

2.1 路由树结构

Alertmanager 的路由是一棵树,根节点是默认路由,每个子节点通过 matchers 匹配标签:

route:
  receiver: default
  group_by: ['alertname', 'cluster']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    # 严重告警 → 立即通知
    - matchers:
        - severity="critical"
      receiver: critical-pager
      group_wait: 0s
      repeat_interval: 1h

    # 警告级别 → 延迟通知
    - matchers:
        - severity="warning"
      receiver: warning-channel
      group_wait: 5m
      repeat_interval: 4h
      routes:
        # 数据库相关警告 → DBA 团队
        - matchers:
            - team="dba"
          receiver: dba-team
          continue: false

    # 告警恢复通知 → 统一发送
    - matchers:
        - alertname=~"NodeDown|HostUnavailable"
      receiver: infra-team

2.2 matchers 语法

从 Alertmanager v0.22 起,matchers 使用统一语法替代了旧的 match / match_re

matchers:
  # 精确匹配
  - severity="critical"

  # 正则匹配
  - alertname=~"Node.*"

  # 不等于
  - severity!="info"

  # 正则不匹配
  - instance!~"localhost.*"

  # 检查标签是否存在(值为空)
  - "maintenance"

  # 检查标签不存在
  - "!staging"

2.3 continue 关键字

默认情况下,告警匹配到某个子路由后就不会继续匹配后续同级路由。设置 continue: true 可以让告警同时走多个接收者:

routes:
  - matchers:
      - severity="critical"
    receiver: pagerduty
    continue: true          # 继续匹配下一个路由
  - matchers:
      - severity="critical"
    receiver: slack-critical

上面的配置让严重告警同时发送到 PagerDuty 和 Slack。

2.4 级联路由示例

routes:
  # 第一级:按团队分流
  - matchers:
      - team="sre"
    receiver: sre-default
    routes:
      # 第二级:SRE 中的严重告警
      - matchers:
          - severity="critical"
        receiver: sre-critical
      # 第二级:SRE 中的磁盘告警
      - matchers:
          - alertname=~"Disk.*"
        receiver: sre-storage

  - matchers:
      - team="dba"
    receiver: dba-default
    routes:
      - matchers:
          - severity="critical"
        receiver: dba-critical

三、分组策略

分组决定了"哪些告警会被合并成一条通知"。

3.1 核心参数

参数说明典型值
group_by按哪些标签分组['alertname', 'cluster', 'service']
group_wait首次告警后等待多久再发送(等待更多同组告警)30s
group_interval同组新告警合并后,下次发送间隔5m
repeat_interval同一告警重复通知间隔4h

3.2 分组时间线示例

假设 group_by: ['alertname']group_wait: 30sgroup_interval: 5m

t=0s    收到 AlertA(instance=node-1)
        → 开始等待 30s(group_wait)

t=10s   收到 AlertA(instance=node-2)  → 同组,合并

t=30s   发送通知 [AlertA(node-1), AlertA(node-2)]
        → 开始 5min 计时(group_interval)

t=3min  收到 AlertA(instance=node-3)  → 同组,暂不发送

t=5min  发送通知 [AlertA(node-3)]       → 仅新增部分

t=10min 无新告警,但有未恢复告警
        → repeat_interval 未到,不发送

t=4h    repeat_interval 到期
        → 发送重复通知 [AlertA(node-1), AlertA(node-2), AlertA(node-3)]

3.3 分组配置建议

route:
  # 按 告警名 + 集群 分组
  # 同一集群的同类告警合并为一条通知
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 30s       # 留 30s 收集同组告警
  group_interval: 5m    # 5 分钟内的告警合并发送
  repeat_interval: 4h   # 4 小时内不重复发送同一告警

经验法则

  • group_by 不要包含高基数字段(如 instance),否则分组过于碎片化。
  • Critical 告警 group_wait 设为 0s,立即发送。
  • Warning 告警 group_wait 设为 5m,等待合并减少噪音。

四、抑制规则

抑制(Inhibition)的核心场景:当高优先级告警触发时,自动静默与之相关的低优先级告警。

4.1 典型场景

  • 节点宕机(NodeDown)时,抑制该节点上的所有服务告警
  • 网络分区时,抑制因网络不通引发的下游告警
  • 数据库主库故障时,抑制依赖该数据库的应用告警

4.2 配置示例

inhibit_rules:
  # 场景1:节点宕机时,抑制该节点上的所有其他告警
  - source_matchers:
      - alertname="NodeDown"
    target_matchers:
      - alertname!="NodeDown"
    equal: ['instance']

  # 场景2:Critical 告警抑制同一服务的 Warning 告警
  - source_matchers:
      - severity="critical"
    target_matchers:
      - severity="warning"
    equal: ['alertname', 'service']

  # 场景3:集群不可达时,抑制该集群内的所有告警
  - source_matchers:
      - alertname="ClusterUnavailable"
    target_matchers:
      - alertname!="ClusterUnavailable"
    equal: ['cluster']

  # 场景4:数据库主库宕机,抑制依赖该实例的应用告警
  - source_matchers:
      - alertname="MySQLMasterDown"
    target_matchers:
      - alertname=~"App.*"
    equal: ['db_instance']

4.3 工作原理

source(NodeDown, instance=node-1, severity=critical)
                    │  触发抑制
target(CPUHigh, instance=node-1, severity=warning)
                    │  equal: ['instance']
                    │  instance 相同 → 匹配成功
              target 告警被静默

关键字段说明:

  • source_matchers:触发抑制的告警条件
  • target_matchers:被抑制的告警条件
  • equal:source 和 target 必须在这些标签上值相同才触发抑制

五、静默管理

静默(Silence)用于临时屏蔽特定告警,典型场景是计划内维护(如升级、重启)期间避免告警噪音。

5.1 通过 Web UI 创建静默

访问 Alertmanager Web UI(默认 http://localhost:9093)→ SilencesNew Silence

Matchers:
  alertname = NodeHighCpuLoad
  instance  = node-3

Starts At:  2026-07-10 22:00:00
Ends At:    2026-07-10 23:00:00
Created By: xubaojin
Comment:    计划内维护 - CPU 扩容

5.2 通过 amtool CLI 创建静默

amtool 是 Alertmanager 自带的命令行工具:

# 创建静默(1小时)
amtool silence add \
  --comment="计划内维护" \
  --author="xubaojin" \
  --duration=1h \
  alertname=NodeHighCpuLoad \
  instance=node-3

# 查看所有静默
amtool silence query \
  --alertmanager.url=http://localhost:9093

# 按匹配条件查询
amtool silence query instance=node-3

# 按 ID 过期静默
amtool silence expire <silence-id> \
  --alertmanager.url=http://localhost:9093

# 过期所有静默
amtool silence expire $(amtool silence query -o simple | awk '{print $1}')

5.3 通过 API 创建静默

curl -X POST http://localhost:9093/api/v2/silences \
  -H "Content-Type: application/json" \
  -d '{
    "matchers": [
      { "name": "alertname", "value": "NodeHighCpuLoad", "isRegex": false },
      { "name": "instance", "value": "node-3", "isRegex": false }
    ],
    "startsAt": "2026-07-10T22:00:00Z",
    "endsAt": "2026-07-10T23:00:00Z",
    "createdBy": "xubaojin",
    "comment": "计划内维护 - CPU 扩容"
  }'

5.4 amtool 常用命令速查

# 查看当前活跃告警
amtool alert query \
  --alertmanager.url=http://localhost:9093

# 查看告警路由(检查某告警会匹配到哪个接收者)
amtool config routes test \
  --alertmanager.url=http://localhost:9093 \
  severity=critical team=sre

# 查看路由树(树形展示)
amtool config routes show \
  --alertmanager.url=http://localhost:9093

六、多渠道通知配置

6.1 邮件通知

receivers:
  - name: email-team
    email_configs:
      - to: 'oncall@example.com'
        from: 'alertmanager@example.com'
        smarthost: 'smtp.example.com:587'
        auth_username: 'alertmanager@example.com'
        auth_password: 'YOUR_SMTP_PASSWORD'
        auth_secret: 'YOUR_SMTP_PASSWORD'
        auth_identity: 'alertmanager@example.com'
        require_tls: true
        headers:
          Subject: '{{ .Status | toUpper }} - {{ .CommonLabels.alertname }}'
        send_resolved: true

6.2 企业微信 Webhook

receivers:
  - name: wecom-team
    webhook_configs:
      - url: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_WECOM_KEY'
        send_resolved: true
        max_alerts: 0

企业微信 Webhook 要求特定的消息格式,通常需要部署一个中间转发服务(如 prometheus-webhook-dingtalk 或自定义适配器)将 Alertmanager 的默认 JSON 转为企业微信格式。

企业微信消息模板适配器示例(Go)

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "bytes"

    "github.com/prometheus/alertmanager/template"
)

type WecomMessage struct {
    MsgType  string   `json:"msgtype"`
    Markdown struct {
        Content string `json:"content"`
    } `json:"markdown"`
}

func handler(w http.ResponseWriter, r *http.Request) {
    var data template.Data
    json.NewDecoder(r.Body).Decode(&data)

    content := fmt.Sprintf(
        "## 告警通知\n"+
            "**状态**: %s\n"+
            "**告警数**: %d\n"+
            "**详情**:\n",
        data.Status, len(data.Alerts),
    )
    for _, alert := range data.Alerts {
        content += fmt.Sprintf(
            "- **%s**: %s\n",
            alert.Labels["alertname"],
            alert.Annotations["summary"],
        )
    }

    msg := WecomMessage{MsgType: "markdown"}
    msg.Markdown.Content = content

    payload, _ := json.Marshal(msg)
    http.Post(
        "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY",
        "application/json",
        bytes.NewReader(payload),
    )
    w.WriteHeader(http.StatusOK)
}

func main() {
    http.HandleFunc("/wecom", handler)
    http.ListenAndServe(":8060", nil)
}

6.3 钉钉 Webhook

receivers:
  - name: dingtalk-team
    webhook_configs:
      - url: 'http://localhost:8060/dingtalk/webhook1/send'
        send_resolved: true

钉钉同样需要消息格式适配,推荐使用 prometheus-webhook-dingtalk 项目:

# 启动钉钉 webhook 适配器
prometheus-webhook-dingtalk \
  --ding.profile="webhook1=https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" \
  --ding.timeout=5s

七、完整 alertmanager.yml 配置示例

以下是一个覆盖路由、分组、抑制、多渠道通知的完整配置:

global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.example.com:587'
  smtp_from: 'alertmanager@example.com'
  smtp_auth_username: 'alertmanager@example.com'
  smtp_auth_password: 'YOUR_SMTP_PASSWORD'
  smtp_require_tls: true

# 模板文件(自定义通知模板)
templates:
  - '/etc/alertmanager/templates/*.tmpl'

# 路由树
route:
  receiver: default
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    # Critical → 立即电话+企业微信
    - matchers:
        - severity="critical"
      receiver: critical-notify
      group_wait: 0s
      repeat_interval: 1h
      continue: true

    # Warning → 企业微信
    - matchers:
        - severity="warning"
      receiver: warning-notify
      group_wait: 2m

    # DBA 团队告警
    - matchers:
        - team="dba"
      receiver: dba-notify
      group_wait: 1m

    # Info 级别 → 仅存档不发通知
    - matchers:
        - severity="info"
      receiver: null

# 抑制规则
inhibit_rules:
  # 节点宕机 → 抑制该节点上的所有其他告警
  - source_matchers:
      - alertname="NodeDown"
    target_matchers:
      - alertname!="NodeDown"
    equal: ['instance']

  # Critical 抑制同服务 Warning
  - source_matchers:
      - severity="critical"
    target_matchers:
      - severity="warning"
    equal: ['alertname', 'service']

  # 集群不可达 → 抑制该集群所有告警
  - source_matchers:
      - alertname="ClusterUnavailable"
    target_matchers:
      - alertname!="ClusterUnavailable"
    equal: ['cluster']

# 接收者定义
receivers:
  - name: default
    email_configs:
      - to: 'oncall@example.com'
        send_resolved: true

  - name: critical-notify
    webhook_configs:
      - url: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_WECOM_KEY'
        send_resolved: true
    email_configs:
      - to: 'critical-oncall@example.com'
        send_resolved: true

  - name: warning-notify
    webhook_configs:
      - url: 'http://localhost:8060/dingtalk/webhook1/send'
        send_resolved: true

  - name: dba-notify
    email_configs:
      - to: 'dba@example.com'
        send_resolved: true
    webhook_configs:
      - url: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=DBA_WECOM_KEY'
        send_resolved: true

  - name: null
    # 空接收者,丢弃告警

八、高可用部署

Alertmanager 支持多实例 HA 部署,通过 Gossip 协议同步告警状态和静默信息:

# 启动 3 节点 HA 集群
alertmanager \
  --config.file=/etc/alertmanager/alertmanager.yml \
  --storage.path=/var/lib/alertmanager \
  --web.listen-address=:9093 \
  --cluster.peer=alertmanager-1:9094 \
  --cluster.peer=alertmanager-2:9094 \
  --cluster.peer=alertmanager-3:9094 \
  --cluster.listen-address=0.0.0.0:9094

在 Prometheus 侧配置多个 Alertmanager 地址实现故障切换:

# prometheus.yml
alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - alertmanager-1:9093
            - alertmanager-2:9093
            - alertmanager-3:9093

Prometheus 会向所有 Alertmanager 发送告警,各实例通过 Gossip 协议去重,确保最终只有一个实例发送通知。

总结

Alertmanager 的配置核心是围绕三个问题展开的:

  1. 谁应该收到告警? → 路由树(route + matchers
  2. 如何减少告警噪音? → 分组(group_by)+ 抑制(inhibit_rules)+ 静默(Silence)
  3. 告警如何送达? → 接收者(receivers)+ 通知渠道

一份好的 Alertmanager 配置应该让值班人员在正常情况下几乎收不到告警(因为问题被提前消除了),在异常情况下只收到精确定位、信息完整、没有重复的告警。记住一个原则:告警不是越多越好,而是越准越好。

更多详情请参阅 Prometheus 官方文档 — Alertmanager

参考资料与致谢

本文在撰写过程中参考了以下资料,感谢原作者的贡献:

  1. Prometheus 官方文档 — Alertmanager — Prometheus 官方,参考了Prometheus 官方文档 — Alertmanager相关内容
  2. prometheus-webhook-dingtalk — GitHub 开源社区,参考了prometheus-webhook-dingtalk相关内容