第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 配置示例:

yaml 复制代码
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 标签,模板直接渲染失败,通知静默丢失。

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

arduino 复制代码
{{ .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篇里的命名规范,同时也是分组维度、抑制主键和跨层下钻的索引。标签规范是这套告警体系的隐藏地基,改了它,上面所有规则都会悄悄失效。

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

​

​

相关推荐
做萤石二次开发的哈哈4 天前
视频解码器怎么对接?解码上墙、电视墙开窗与场景切换的ISAPI接入实战
人工智能·物联网·监控·视频编解码·大屏端·萤石开放平台·蓝海aiot一站式工作台
lisanmengmeng4 天前
nagios 图形化监控部署
监控·nagios
鸿观工坊4 天前
第5篇 Nginx 监控:流量、连接与性能指标
监控
鸿观工坊4 天前
第4篇 Spring Boot 应用监控:Micrometer 与 JVM 指标
监控
鸿观工坊4 天前
第1篇 Prometheus 监控体系全景与基础环境搭建
监控
苏渡苇12 天前
Spring Insight 里如何把 Span 画成瀑布时间线
后端·spring·spring cloud·springboot·监控·apm
行百里er12 天前
轻量级 Spring 监测工具——Spring Insight 发布了
spring boot·后端·监控
宋均浩13 天前
告警规则 243 砍到 27:Prometheus 降噪实战,日均打扰 47 次 → 3 次
云原生·监控·devops
小小ken14 天前
水星摄像头(MIPC552W)双摄版和乔安摄像头(JA-A12,JA-w1)接入easynvr具体步骤
监控·摄像头·nvr·easynvr·水星·乔安