第09篇 告警体系设计:Alertmanager 路由与告警治理

上一篇把该看的指标收敛到了十条以内,规则也按 RED / USE / 黄金信号归好了类。但规则配完只算走完一半,响不响、响几条、响给谁、多久响一次,全在 Alertmanager 这一层。

真实故障里更常见的场景:一台宿主机过载,五分钟内手机响了四十七次。前三次还看,第四次开始只划掉,第七次干脆把告警群静音。而等到真正需要处理的那一条进来时,已经没人看了。

问题不在告警规则,也不在采集链路。告警太多和没有告警,最终结果是一样的。

Alertmanager 提供了三种收敛手段:

对比维度 分组(group_by) 抑制(inhibit_rules) 静默(silence)
解决的问题 同类告警合并成一条 根因告警发出时压住次生告警 计划内维护期间不通知
作用时机 通知前聚合 通知前拦截 通知前拦截
生效条件 标签相同即自动分组 源告警存在且标签匹配 时间窗口 + 标签匹配
生命周期 配置固化,长期生效 配置固化,长期生效 有明确起止时间,自动过期
典型场景 同一 job 的 10 个实例同时抖动 主机宕机时压住其上应用的连带告警 升级发版、数据库迁库
主要边界 只能合并,不能消除 只影响通知,不阻止告警产生 需人工创建,忘记清理会漏报

本篇只讲 Alertmanager,包括部署、路由树、分组、抑制、静默、通知模板,以及最后落到「怎么让这套体系长期不腐化」。告警规则详见前几篇告警表,本篇不再展开。

一、部署与最小可用配置

1、启动服务

第1篇已经给过启动命令:

bash 复制代码
$ docker run -d --name alertmanager \
    --rm \
    --restart=no \
    --network my-bridge \
    -p 9093:9093 \
    -e TZ=Asia/Shanghai \
    -v /data/volumes/alertmanager:/etc/alertmanager \
    prom/alertmanager:v0.33.1

注意:

  • -v 挂载的是整个目录,不是单个 yml 文件。 目前包含templates等依赖文件,可简化挂载配置。
  • ⚠️ -e TZ=Asia/Shanghai 不影响模板里的时间输出。 该参数只改容器系统时区,Go 模板里的 .StartsAt 仍然按 UTC 渲染。要让邮件显示北京时间,需要在模板里加偏移量,如 {``{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} 。

2、最小可用配置

参考示例:

yaml 复制代码
# /etc/alertmanager/alertmanager.yml
global:
  # 距上次收到告警超过该时间,即判定为已恢复
  resolve_timeout: 5m

  # SMTP 全局配置:465 是隐式 TLS 端口,require_tls 必须为 false
  smtp_smarthost: 'smtp.aliyun.com:465'
  smtp_from: '*****@aliyun.com'
  smtp_auth_username: '*****@aliyun.com'
  smtp_auth_password: '******'
  smtp_require_tls: false

route:
  # 根路由:兜底接收器,未被子路由匹配的告警都走这里
  receiver: 'default'
  group_by: ['job', 'svc']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

receivers:
  - name: 'default'
    email_configs:
      - to: '******@aliyun.com'
        send_resolved: true
        headers:
          Subject: '[Prometheus][{{ .GroupLabels.severity }}] {{ .GroupLabels.job }} 告警'
        html: |
          {{ range .Alerts }}
          告警名称: {{ .Labels.alertname }}

          Job: {{ .Labels.job }}

          Instance: {{ .Labels.instance }}

          级别: {{ .Labels.severity }}

          摘要: {{ .Annotations.summary }}

          开始时间: {{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}

          {{ end }}

3、验证

bash 复制代码
$ docker exec -it alertmanager amtool check-config /etc/alertmanager/alertmanager.yml
Checking '/etc/alertmanager/alertmanager.yml'  SUCCESS
Found:
  - global config
  - route
  - 1 inhibit rules
  - 2 receivers
  - 1 templates
 SUCCESS
  • 该命令会把路由、接收器、抑制规则、模板文件一起校验。 输出里出现 - 1 templates 说明模板文件被找到了;如果 templates: 指向的路径没挂载进容器,这里会直接报错,这一行输出等于一次挂载检查。
  • 有错误时会打印行号和原因,并以非 0 退出码退出,可以直接塞进 CI。

4、热加载

bash 复制代码
$ curl -XPOST http://127.0.0.1:9093/-/reload

Alertmanager 的热加载默认就开着。 这和 Prometheus 不同。

二、路由树:匹配、分组与三个时间参数

1、route 是一棵树

Alertmanager 的路由是一棵从根节点向下匹配的树:从上往下走,第一个匹配上的子路由决定这条告警走哪个接收器。

示例:

yaml 复制代码
route:
  receiver: 'default'
  group_by: ['job', 'svc']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

  routes:
    # ============================================================
    # 第一层:severity = critical
    # 响应快、通道即时(企业微信/电话/Slack)
    # ============================================================
    - matchers:
      - severity = "critical"
      # 关键告警缩短首次等待和重复间隔
      group_wait: 10s
      group_interval: 3m
      repeat_interval: 1h
      receiver: "slack-all"

提示:match / match_re 自 v0.22.0 起已标记为 deprecated ,官方推荐改用 matchers。新语法支持四种运算符,可读性更好:

yaml 复制代码
matchers:
  - severity = "critical"       # 等于
  - job =~ "nginx|node"         # 正则匹配
  - env != "dev"                # 不等于
  - instance !~ "10\.0\.2\..*"  # 正则不匹配

2、三个时间参数

以下三个参数是告警量的总闸门,配错任意一个都会让收敛效果打折。

参数 作用 默认值 生产建议值 风险点
group_wait 首次告警后等多久再发,用于攒齐同组告警 30s 30s(critical 可 10s) 设太短会把同一波故障拆成好几条;设太长会延迟通知
group_interval 同组有新告警时,多久发一次更新 5m 5m 设太小会持续刷屏;设太大会漏掉后续新增的实例
repeat_interval 同一条告警未恢复时,多久重复提醒一次 4h warning 4h,critical 1h 必须 ≥ group_interval,否则重复提醒会被组间隔吃掉

⚠️ 注意:

  • repeat_interval 小于 group_interval 不会报错,但会失效。 把 repeat_interval 设成 30s、group_interval 保持 5m,实际重发间隔仍然是 5m。check-config 不会拦这种配置,它只在语义上说不通。
  • group_wait 和 group_interval 的差别:前者管「第一次发之前等多久」,后者管「发完之后下次什么时候发」。

3、group_by 该写什么

group_by 决定了「哪些告警会被合并成一条通知」,是收敛效果的关键:

写法 效果 适用场景 副作用
['alertname'] 同类型告警全部合并 单主机、单应用的小环境 多台机器一起出问题时信息被压缩掉,看不到具体是哪台
['job'] 同一系统合并 按系统划分职责的团队 一个 job 下多个 svc 混在一起
['job', 'svc'] 按系统 + 服务合并 多应用共用一套监控 本系列推荐,与第2篇标签约定一致
['job', 'svc', 'instance'] 不合并 需要精确到实例的场景 等于放弃分组,只剩路由和抑制在收敛
  • group_by: ['...'] 这种特殊写法表示不分组,每条告警单独通知。除非告警量极小,否则不建议。
  • group_by 锚定在 job + svc 上,是这套体系里性价比最高的选择。根因是故障的边界通常就是系统的边界,而不是机器的边界。按 instance 分组等于按机器切分故障现场,看到的永远是碎片。

4、验证路由

1)配置改完先过语法

bash 复制代码
$ docker exec -it alertmanager amtool check-config /etc/alertmanager/alertmanager.yml
Checking '/etc/alertmanager/alertmanager.yml'  SUCCESS
Found:
 - global config
 - route
 - 3 inhibit rules
 - 6 receivers
 - 1 templates
  SUCCESS

2)再用 amtool 把整棵树打出来核对:

bash 复制代码
# 查看最终生效的路由树(含从父路由继承的参数)
$ docker exec -it alertmanager amtool config routes show --config.file /etc/alertmanager/alertmanager.yml

3)测试一条告警会落到哪个接收器

bash 复制代码
# 基本语法
amtool config routes test --config.file=/path/to/alertmanager.yml <label1>=<value1> <label2>=<value2> ...

# 测试一条告警会落到哪个接收器
# 示例
$ docker exec -it alertmanager \
    amtool config routes test \
      --config.file=/etc/alertmanager/alertmanager.yml \
      severity=critical \
      job=cim \
      svc=nodb

提示:amtool config routes test 是这个环节最省事的工具。 不用真的触发告警,直接传一组标签就能看到会命中哪个 receiver。路由设计的正确性,应该在被验证之后才上线,而不是等故障时才发现走错了通道。

4)验证是否命中预期接收器

使用 --verify.receivers 标志,可以断言告警是否只命中指定的接收器。如果实际结果与预期不符,命令会返回非零退出码(错误码 1),非常适合在 CI/CD 或脚本中做自动化校验。

bash 复制代码
$ docker exec -it alertmanager \
    amtool config routes test \
      --config.file=/etc/alertmanager/alertmanager.yml \
      --verify.receivers=email-critical-cim \
      severity=critical \
      job=cim \
      svc=nodb
slack-all
WARNING: Expected receivers did not match resolved receivers.

5、分析要点

  • 树深度控制在 3 层以内:severity → job / svc → type,再深就会出现「谁也说不清这条会走到哪」
  • 根路由必须配一个兜底 receiver,否则未匹配的告警会被静默丢弃
  • 子路由只覆盖需要改的参数,其余继承父路由。继承不是复制,父路由改了子路由会跟着变
  • continue: true 会让匹配后继续尝试兄弟路由,默认 false。不用多通道冗余就别开,开了容易出现重复通知
  • 每层都设 repeat_interval 是常见错误,只在需要区分级别时设

判断 :路由树的复杂度应该和团队规模匹配。三人团队用「critical 走企业微信、warning 走邮件」两层就够了;路由层数超过告警分级数,通常说明在设计组织架构,不是在设计告警。

三、抑制与静默:把告警量降下来

1、inhibit_rules 三要素

抑制规则只有三个部分,但每一部分都有讲究:

yaml 复制代码
inhibit_rules:
  # 当 source_match 匹配的告警存在时,压制 target_match 匹配的告警
  - source_matchers:
      - severity = "critical"
    target_matchers:
      - severity = "warning"
    # 只有这些标签完全相等时才抑制
    equal: ['job', 'instance']
  • source:作为「根因」的告警,它存在时才有抑制
  • target:被压制的告警
  • equal:必须完全一致的标签集合,是抑制能否命中的关键

2、跨层抑制:告警治理里最值钱的一条

真正制造告警风暴的是跨层连锁:宿主机一挂,上面的应用、依赖它的服务、拨测到它域名的探针,会在几分钟内全线告警。

示例:

yaml 复制代码
inhibit_rules:
  # 规则 1:主机层 critical 压住同 job+svc 的应用层 warning
  # 主机都趴了,应用告警是必然结果
  - source_matchers:
      - severity = "critical"
      - type = "node"
    target_matchers:
      - severity = "warning"
    equal: ['job', 'svc']

  # 规则 2:拨测失败时,压住该服务自身的接口告警
  - source_matchers:
      - alertname = "ProbeTargetDown"
    target_matchers:
      - severity = "warning"
    equal: ['job', 'svc']

  # 规则 3:critical 压住同 job+instance 的 warning
  - source_matchers:
      - severity = "critical"
    target_matchers:
      - severity = "warning"
    equal: ['job', 'instance']

⚠️ 注意:equal 里的标签少打一个,抑制规则就永远不匹配,而且是静默失败。

验证抑制是否生效,最快的方式是直接查 Alertmanager 的 API:

bash 复制代码
# 查看当前活跃告警,以及每条被哪些规则抑制了
$ curl -s http://127.0.0.1:9093/api/v2/alerts | python3 -m json.tool | grep -E '"status"|"inhibitedBy"'

3、静默:计划内维护的正确做法

抑制解决的是「已知的因果连锁」,静默解决的是「已知的、有时间边界的人为变更」。

bash 复制代码
# 创建 2 小时的静默(升级发版场景)
$ docker exec -it alertmanager amtool silence add \
    alertname="HostHighCpuLoad" \
    --duration=2h \
    --comment="主机升级,预计 30 分钟"

# 根据 Job 静默
$ docker exec -it alertmanager amtool silence add \
    job="<你的job名称>" \
    --duration=2h \
    --comment="<你的job名称> 应用发版,预计 30 分钟"

# 查看当前所有静默
$ docker exec -it alertmanager amtool silence query --alertmanager.url http://localhost:9093/

静默的两个强制要求

参数 作用
--duration 必须带。让静默自动过期,避免忘记清理造成永久漏报
--comment 必须带。让三个月后复盘时有人知道当时为什么静默

⚠️ 重点:静默比抑制危险得多。 抑制规则由标签驱动,根因消失就自动失效;静默是人工创建的时间窗口,窗口期内该告警彻底不响,包括真实的故障。所以静默的粒度必须窄到具体 alertname 或 svc,不能用宽泛的标签一次静掉一批。

4、三种手段的取舍

场景 用哪个 为什么
同一 job 下 10 个实例同时抖动 分组 标签相同,自动合并,无需人工干预
主机宕机引发其上应用告警 抑制 因果明确、可固化,长期有效
升级发版、迁库、压测 静默 有明确起止时间,且是人工计划
上游依赖故障引发下游连锁 抑制 本质是跨层因果关系
某条规则阈值定得不对、频繁误报 都不是 该去改规则或降级,不该用收敛手段掩盖

如果一条告警需要长期靠静默压着,那它本身就该被删掉或降级。用静默兜住错误配置,只是把问题隐藏了。

5、常见踩坑

  • 抑制不阻止告警产生,只影响通知。 被抑制的告警在 Prometheus 和 Alertmanager 里都正常存在,/api/v2/alerts 能查到,inhibitedBy 字段会标出压制它的规则。排查「为什么没收到通知」时,先查这一项。
  • 源告警恢复后,被抑制的告警会立刻恢复通知。 这通常符合预期,但如果触发条件还在(比如主机还没起但 CPU 告警已经 resolved),会出现一次抖动通知。靠 for 参数和 resolve_timeout 一起兜。
  • 抑制规则之间也会互相影响。 规则 1 和规则 3 的 target 范围有重叠,实际会按「任一 source 命中即抑制」生效。多重抑制叠加时,告警可能比预期更安静,要用 amtool 实测确认。

四、通知模板:让告警在 3 秒内读完

1、挂载与引用

yaml 复制代码
templates:
  - '/etc/alertmanager/templates/*.tmpl'

2、模板变量

变量 含义 典型用法
.Status 告警状态,firing / resolved 标题里标 `[{``{ .Status
.Alerts 本组全部告警 range 遍历
.Alerts.Firing 仅未恢复的告警 len 判空,避免空白通知
.Alerts.Resolved 仅已恢复的告警 恢复通知单独排版
.GroupLabels 分组维度的标签值 标题里显示是哪个 job、哪个 svc
.CommonLabels 组内所有告警共有的标签 提取 severity、env
.CommonAnnotations 共有的注解 提取 summary
.Labels / .Annotations 单条告警的标签与注解 正文逐条展开
.ExternalURL Alertmanager 访问地址 附上跳转链接,方便点进去看

3、邮件模板

第1篇已给过一个示例,下面再提供一份邮件模板供参考。

email.html

html 复制代码
<html>
<head>
  <title>{{ .CommonLabels.alertname }}</title>
  <style>
    body { font-family: Arial, sans-serif; margin: 20px; }
    .alert-box { border: 2px solid; padding: 15px; margin: 10px 0; border-radius: 5px; }
    .firing { border-color: #ff4d4d; background-color: #fff5f5; }
    .resolved { border-color: #52c41a; background-color: #f6ffed; }
    table { width: 100%; border-collapse: collapse; margin: 10px 0; }
    th, td { padding: 8px 12px; text-align: left; border-bottom: 1px solid #ddd; }
    th { background-color: #f5f5f5; font-weight: bold; }
  </style>
</head>
<body>
  {{ if eq .Status "firing" }}
    <h2 style="color: #ff4d4d;">🔥 监控报警(故障告警通知)</h2>
    <table>
      <tr><th>告警级别</th><td>{{ .CommonLabels.severity }} 级</td></tr>
      <tr><th>告警名称</th><td>{{ .CommonLabels.alertname }}</td></tr>
      <tr><th>告警应用</th><td>{{ .CommonLabels.job }}</td></tr>
      <tr><th>告警服务</th><td>{{ .CommonLabels.svc | default "unknown" }}</td></tr>
      <tr><th>故障节点</th><td>{{ .CommonLabels.instance }}</td></tr>
      <tr><th>告警摘要</th><td>{{ .CommonAnnotations.summary }}</td></tr>
      <tr><th>触发时间(北京时间)</th><td>{{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}</td></tr>
    </table>
    <div class="alert-box firing">
      <p>{{ replace .CommonAnnotations.description "\n" "<br>" | safeHTML }}</p>
    </div>
  {{ else }}
    <h2 style="color: #52c41a;">✅ 告警恢复通知</h2>
    <table>
      <tr><th>告警名称</th><td>{{ .CommonLabels.alertname }}</td></tr>
      <tr><th>恢复节点</th><td>{{ .CommonLabels.instance }}</td></tr>
    </table>
  {{ end }}
</body>
</html>
{{ end }}
  • .StartsAt.Add 28800e9 用于将 UTC 时间转换为北京时间 (UTC+8)

Alertmanager 配置引用:

yaml 复制代码
templates:
  - "/etc/alertmanager/templates/*"

receivers:
  - name: 'gmail-alerts'
    email_configs:
      - to: 'your-email@gmail.com'
        html: '{{ template "email.html" . }}'

4、企业微信与 Slack

Alertmanager 原生支持 wechat_configs(企业微信应用消息)和 slack_configs。Slack 配置示例:

复制代码
receivers:
  - name: 'slack-all'
    slack_configs:
      - channel: '#ph'
        send_resolved: true
        username: 'Alertmanager'
        title: '{{ template "slack.title" . }}'
        color: '{{ template "slack.color" . }}'
        icon_emoji: '{{ template "slack.icon" . }}'
        text: '{{ template "slack.text" . }}'

slack 模板

html 复制代码
{{/* ---------- 标题 ---------- */}}
{{ define "slack.title" }}
{{- if eq .Status "firing" -}}
  {{- if eq .CommonLabels.severity "critical" -}}🔥 严重告警
  {{- else if eq .CommonLabels.severity "warning" -}}⚠️ 警告通知
  {{- else -}}ℹ️ 信息通知{{- end -}}
{{- else -}}
  {{- if eq .CommonLabels.severity "critical" -}}✅ 严重告警已恢复
  {{- else if eq .CommonLabels.severity "warning" -}}✅ 警告已恢复
  {{- else -}}✅ 信息已恢复{{- end -}}
{{- end }} - {{ .CommonLabels.alertname }}
{{- end }}

{{/* ---------- 颜色 ---------- */}}
{{ define "slack.color" -}}
{{- if eq .Status "firing" -}}
  {{- if eq .CommonLabels.severity "critical" -}}danger
  {{- else if eq .CommonLabels.severity "warning" -}}warning
  {{- else -}}#439FE0{{- end -}}
{{- else -}}good{{- end }}
{{- end }}

{{/* ---------- 图标 ---------- */}}
{{ define "slack.icon" -}}
{{- if eq .Status "firing" -}}
  {{- if eq .CommonLabels.severity "critical" -}}:fire:
  {{- else if eq .CommonLabels.severity "warning" -}}:warning:
  {{- else -}}:information_source:{{- end -}}
{{- else -}}:white_check_mark:{{- end }}
{{- end }}


{{/* ---------- 正文 ---------- */}}
{{ define "slack.text" -}}
{{ range .Alerts }}
*告警名:* {{ .Labels.alertname }}
*系统/应用:* {{ .Labels.job_alias }}
*服务:* {{ .Labels.svc }}
*实例:* {{ .Labels.instance }}
*级别:* {{ .Labels.severity }}
*摘要:* {{ .Annotations.summary }}
*描述:* {{ .Annotations.description }}
{{ if eq .Status "firing" }}
*告警时间:* {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ else }}
*恢复时间:* {{ .EndsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
{{ end }}
{{ end }}

企业微信、Slack 区分方式:

通道 对应配置 需要的凭据
企业微信应用消息 wechat_configs corpid、corpsecret、agentid
企业微信群机器人 webhook_configs + 中继服务 webhook key(在中继服务里)
Slack slack_configs Incoming Webhook URL

5、常见踩坑

⚠️ 模板渲染失败会导致整封通知不发,而 Alertmanager 却不一定会在日志里报错。 最常见的原因是引用了不存在的标签,比如模板里写了 {``{ .Labels.svc }},但某条告警没打 svc 标签,模板直接渲染失败,通知静默丢失。

因此,给标签加默认值是防这类问题的标准做法。

复制代码
{{ .Labels.svc | default "unknown" }}

模板改动后一定要用 amtool check-config 复验。校验能拦掉大部分语法错误,但拦不住标签缺失导致的运行时失败,标签缺失只能靠真实告警触发验证。

注意 ,模板的唯一目标不是好看,是让值班的人在不打开 Grafana 的情况下判断要不要立刻动手。做不到这一点的模板,无论排版多精细都是无效信息。

五、告警治理:从「配完规则」到「可持续」

1、分级:只分三层,不要更多

级别 含义 通知通道 响应时限 典型规则
critical 用户已受影响,必须立刻处理 企业微信 / 电话 15 分钟内响应 5xx 错误率 > 1%、probe_success == 0、OOM Kill
warning 趋势不对,当天处理即可 邮件 / 群消息 工作时间内处理 CPU > 70%、磁盘 > 80%、堆内存 > 80%
info 仅登记,用于复盘与容量规划 日报 / 不通知 无需响应 QPS 环比波动、证书剩余天数 < 30 天

severity 在 Alertmanager 里只是一个标签,分级靠的是路由匹配。 即分级是否真的生效,取决于路由树里有没有对应的 matchers 。打了 severity: critical 却没有任何路由匹配它,这条告警会落到根路由的兜底接收器,和 info 级别一起进邮件。

2、一条告警的完整生命周期

把前面几节串起来,一条告警从产生到关闭会经过这些环节:

复制代码
规则触发
  ↓(Prometheus 根据 for 字段判定,生成告警存入内部告警队列)
推送到 Alertmanager
  ↓(由 Prometheus alerting.alertmanagers 配置决定推送地址)
去重与分组
  ↓(按 group_by 标签合并告警;group_wait 等待攒齐同组告警)
抑制判定
  ├─ 命中抑制规则 → 标记 inhibitedBy,不发送通知
  └─ 未命中 → 进入静默判定
静默判定
  ├─ 匹配有效静默规则 → 不发送通知
  └─ 未匹配 → 通知发送
通知发送
  ↓(匹配路由找到 receiver,渲染通知模板发送)
告警状态判断
  ├─ 告警持续未恢复 → 按 repeat_interval 周期性重发告警通知
  └─ 超过 resolve_timeout 不再收到告警 → 标记 resolved,发送恢复通知

3、治理动作:三个可执行的检查

以下是从本套体系的实际运行经验里总结的建议基线,不是实测数据,供校准自己的阈值:

  • 告警量与处理量对比 :一周内触发的告警条数,与真正需要人工动作的条数之比。如果一条规则 30 天内 90% 以上的触发都不需要任何动作,它就该被降级或删除,而不是继续留在 critical 里。
  • 重复率检查 :定期拉 amtool alert query 的输出,看被抑制的告警占比。抑制比例长期低于 10%,说明抑制规则可能根本没匹配上。
  • 静默残留检查 :按季度执行 amtool silence query。存在超过 7 天未过期的静默,几乎一定是忘记清理,它掩盖的告警需要单独复盘。

另外,告警规则要纳入版本管理。 规则文件和应用代码放在同一个仓库,改阈值走 Code Review,比在服务器上 vi 一份 YAML 可靠得多。

4、和 SLO 的关系

第7篇的后续方向里提过用黄金信号划 SLO。告警和 SLO 的分工:

对比维度 阈值告警 SLO / Error Budget
判断依据 资源水位或指标绝对值 用户可感知的错误预算消耗速度
触发条件 超过预设数字 错误预算消耗速率超过承受能力
优点 配置简单、延迟低 直接对齐业务影响,天然抑制噪声
缺点 阈值本身是拍出来的,容易误报 需要先有明确的 SLI 定义和基线数据

两者不是替代关系,而是分工关系 。资源类阈值告警负责「提前发现」,SLO 负责「判断严重程度」。同一条告警,配在 CPU 上是提醒,配在错误预算上是决策依据。

5、常见踩坑

  • 告警恢复不代表故障结束。 resolve_timeout: 5m 意味着指标恢复正常 5 分钟后才发恢复通知。如果故障是高频抖动的,会反复触发/恢复,产生大量通知。此时该去调规则的 for,而不是调 resolve_timeout。
  • Alertmanager 自身也要被监控。 Alertmanager 是告警链路的单点,挂了之后所有告警静默失效。

⚠️ 不要让 Alertmanager 成为唯一通知路径。 生产环境里至少保留一条独立通道(比如另一个告警系统或平台侧监控),用来发现「Alertmanager 本身失效」这件事。


六、小结

至此,我们完整走过了告警体系从部署、路由、收敛到治理的全部流程。

配置上不必求全。Alertmanager 的核心能力就是四件事:

  1. 路由决定去哪里
  2. 分组决定合并多少
  3. 抑制决定压住什么
  4. 静默决定什么时候不响

日常真正需要长期维护的,通常是一棵三层以内的路由树、三条左右的抑制规则,和一套能看清四项信息的通知模板。静默应当是偶发动作,而不是常驻配置。

落地建议,先验通道再设计路由,先固化标签再做抑制。svc 和 type 这两个标签看着是第2篇里的命名规范,同时也是分组维度、抑制主键和跨层下钻的索引。标签规范是这套告警体系的隐藏地基,改了它,上面所有规则都会悄悄失效。

告警系统的目标不是不漏报,而是每一条通知都值得被处理。

​

​

相关推荐
蓝胖的四次元口袋1 天前
Prometheus+Grafana知识梳理(1)
grafana·prometheus
晨陌y1 天前
CentOS 7 部署 mysqld_exporter:MySQL 指标采集、Prometheus 告警与远程监控
mysql·centos·prometheus
倔强的小石头_2 天前
Ubuntu部署Prometheus与Alertmanager:systemd配置、告警对接及cpolar远程访问
数据库·ubuntu·prometheus
打工仔折腾 AI2 天前
Prometheus接入Pushgateway实战:二进制与Docker部署、指标推送与远程写入
后端·python·docker·容器·性能优化·prometheus·ai agent 实战
Elastic 中国社区官方博客3 天前
两个依赖和一个配置块:通过 Prometheus 远程写入将 Spring Boot 指标发送到 Elasticsearch
大数据·数据库·spring boot·elasticsearch·搜索引擎·全文检索·prometheus
User_芊芊君子4 天前
Prometheus接入Pushgateway实战:二进制与Docker部署、指标推送及远程上报
docker·容器·prometheus
lbb 小魔仙10 天前
OpenClaw + cpolar 实战:远程 NAS、分享小游戏、RDP,再配置公网 AI 入口
数据库·人工智能·redis·oracle·prometheus
zhoupenghui16811 天前
Golang pprof 工具详解:监控、压测与调优实战指南
prometheus·pprof
ggaofeng12 天前
prometheus时序数据库
prometheus