土法炼钢兴趣小组的算法知识备份

【可观测性工程】告警体系:Alertmanager、PagerDuty、OnCall 与分级抑制

文章导航

分类入口
architectureobservability
标签入口
#alertmanager#pagerduty#oncall#alerting#prometheus#slo#escalation#inhibition

目录

告警体系:Alertmanager、PagerDuty、OnCall 与分级抑制

凌晨 3 点,值班手机响了。不是一次。是 87 次。同一个上游依赖超时引发了连锁反应——87 条告警,其中 85 条是下游服务”我也超时了”的抱怨,只有最后 2 条是说”上游 Connection Pool 耗尽了”——真正的根因。值班人花了 40 分钟在手机屏幕上翻到第 86 条。

SLO 工程 定义了”什么算用户影响”——Burn Rate 告警。本文回答下一个问题:Burn Rate 触发了之后,告警怎么路由、怎么合并、怎么抑制、怎么叫醒正确的人,且不让值班人在 87 条通知里迷失?

Alertmanager 是 Prometheus 生态中专门负责”告警治理”的组件。它的设计目标不是”转发所有 firing alert”,而是 grouping + inhibition + silence + route 四元组,把数百条底层规则压缩成少量可行动的通知。文中配置结构按 Prometheus Alertmanager 0.27 官方文档(A 级来源)编写;本环境未安装 Alertmanager / amtool,配置语法以文档为准,部署前请在目标集群执行 amtool check-config(见附录 K)。

Alertmanager 告警治理流水线

一、告警体系的分层架构

从 Prometheus Alert Rule 到值班手机的完整路径可以拆成八层。每一层解决不同问题;跳过任何一层都会在生产环境中以”告警风暴”或”该响不响”的形式反弹。

层级 组件 职责 典型失败模式
L1 规则 Prometheus alerting rules 定义”什么算异常” 阈值拍脑袋、无 runbook
L2 记录 Recording rules 预计算 Burn Rate 等 SLI 规则未部署到 HA 副本
L3 路由 Alertmanager route 按 label 选 receiver 所有 critical 都打 Page
L4 分组 group_by + timing 合并同源告警 group_wait 太短
L5 抑制 inhibit_rules 隐藏衍生告警 规则过宽误抑制
L6 静默 silence / time_intervals 维护窗口屏蔽 静默过期未清理
L7 通知 receivers (webhook/PagerDuty) 送达渠道 webhook 429 丢通知
L8 排班 PagerDuty / Opsgenie 谁在值班、如何升级 排班表过期

1.1 数据流概览

flowchart LR
  subgraph prom [Prometheus]
    AR[Alert Rules]
    RR[Recording Rules]
  end
  subgraph am [Alertmanager HA Cluster]
    RT[Route Tree]
    GR[Grouping]
    IN[Inhibition]
    RC[Receivers]
  end
  subgraph notify [Notification]
    PD[PagerDuty Page]
    JK[Jira Ticket]
    SL[Slack Chat]
    DB[Dashboard Log]
  end
  AR --> RT
  RR --> AR
  RT --> GR --> IN --> RC
  RC --> PD
  RC --> JK
  RC --> SL
  RC --> DB

1.2 Rules 层:与 SLO 的衔接

SLO 工程 §4 给出 6 条 Workbook 规则——3 条 Page、3 条 Ticket。Alertmanager 不修改 这些规则的 expr,只根据 labels.severity 路由:

Prometheus label Alertmanager 路由 通知渠道
severity: page receiver: pagerduty-oncall 电话 + SMS
severity: ticket receiver: jira-sre 工单
severity: chat receiver: slack-infra Slack 频道
severity: log receiver: blackhole 或 null 仅 Grafana

反模式:在 Prometheus 规则里写 severity: critical 却期望 Alertmanager 自动区分 Page 和 Ticket——critical 没有统一定义,必须显式使用 page / ticket / chat / log 四级(或团队等价命名,但文档化)。

1.3 与指标体系的关系

指标体系设计 中的 USE/RED 指标是 Ticket 和 Chat 级 的主要输入——CPU 饱和、磁盘错误、连接池使用率。它们解释 SLO 失败的根因,但不应直接触发 Page。唯一应触发 Page 的指标类告警是 SLO Burn Rate(及等价的全站 outage 探测)。

二、告警规则设计的铁律

Google SRE Book 第 6 章:一个好的告警必须满足 actionable——收到它的人知道该做什么,且不做就会造成伤害或错过修复窗口。

2.1 四大黄金法则

  1. Actionable(可操作):告警必须链到 runbook 第一步。Runbook 第一句不是”调查一下”,而是”打开 Dashboard X,确认指标 Y,若 Z 则执行 W”。
  2. Owner(有主)team label 指向负责团队。无 owner 的告警在 on-call 眼里等于 spam。
  3. Priority(有优先级):与 Alertmanager route 一致的 severity label。
  4. Runbook(有手册)runbook_url 必须是稳定 URL——不要用 Confluence 无版本页面。

2.2 必须标签模板

# 每条 alerting rule 的 labels 最小集
labels:
  severity: page          # page | ticket | chat | log
  team: checkout
  service: checkout-api
  runbook_url: "https://wiki.example.com/runbooks/checkout-burn-rate"
# annotations 最小集
annotations:
  summary: "checkout SLO 1h 燃烧率 {{ $value | printf "%.1f" }}×"
  description: |
    当前 1 小时窗口 Burn Rate 超过 14.4×,预计 30 天内消耗约 2% 错误预算。
    Dashboard: https://grafana.example.com/d/slo-checkout
    Runbook: {{ $labels.runbook_url }}

2.3 规则分层:Page / Ticket / Chat / Log

级别 触发条件(与 SLO 联动) 响应 SLA 示例
Page Burn Rate ≥ 14.4×/1h 或 6×/6h 或 1×/3d(见 18-slo §4.1) 5 min ack CheckoutSLOBurnRateCritical1h
Ticket Burn Rate ≥ 1×/6h 或 Workbook Ticket 规则 1 h CheckoutSLOBurnRateWarning6h
Chat 容量趋势、复制 lag、慢查询增长 工作时间 PGReplicationLagHigh
Log 非生产、周期性 cron 信息 StagingDeployComplete

2.4 反例目录

以下规则在多数团队应 降级或删除

反例规则 问题 建议
CPU > 80% → Page 不等价用户影响 改为 Chat;Page 只看 Burn Rate
Pod restart > 3 → Page 可能是正常滚动发布 Ticket + 关联 deployment 事件
Disk > 85% → Page 有缓冲时间 Ticket,7 天趋势 Chat
Any 5xx > 0 → Page 瞬时尖峰误报 用 Burn Rate 或 for: 5m
cert expires in 30d → Page 有充足修复窗口 Ticket 30d,Chat 7d

2.5 PromQL 规则写作规范

groups:
  - name: slo_checkout_pages
    interval: 30s
    rules:
      - alert: CheckoutSLOBurnRateCritical1h
        expr: slo:checkout:burnrate1h > 14.4
        for: 2m
        labels:
          severity: page
          team: checkout
          service: checkout-api
          runbook_url: "https://wiki.example.com/runbooks/checkout-slo"
        annotations:
          summary: "checkout 1h Burn Rate {{ $value | printf "%.2f" }}×"
          description: "Page 级 SLO 告警。见 18-slo Workbook 规则 A。"

      - alert: CheckoutSLOBurnRateWarning6h
        expr: slo:checkout:burnrate6h > 1
        for: 15m
        labels:
          severity: ticket
          team: checkout
          service: checkout-api
          runbook_url: "https://wiki.example.com/runbooks/checkout-slo-ticket"
        annotations:
          summary: "checkout 6h Burn Rate {{ $value | printf "%.2f" }}×"

for: 子句是降噪关键——Workbook 建议 Page 规则 2–5 分钟 pending,Ticket 15 分钟至 1 小时。

三、Alertmanager 深度实战

Alertmanager 配置四大核心块:globalroutereceiversinhibit_rules。Alertmanager 0.27+ 还支持 time_intervals 用于维护窗口路由。

3.1 完整 alertmanager.yml 示例

以下配置为合成示例,展示 route 树、多 receiver、inhibit、time_intervals 的完整结构。Webhook URL 和 integration key 为占位符——部署时替换为真实值。

# alertmanager.yml — 合成生产级示例
# 验证:amtool check-config alertmanager.yml
# 参考:Prometheus Alertmanager 0.27 官方文档

global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.example.com:587'
  smtp_from: 'alertmanager@example.com'
  smtp_auth_username: 'alertmanager@example.com'
  smtp_auth_password: '<secret>'
  slack_api_url: '<slack-webhook-url>'

templates:
  - '/etc/alertmanager/templates/*.tmpl'

# --- time_intervals:维护窗口 ---
time_intervals:
  - name: weekday-business-hours
    time_intervals:
      - weekdays: ['monday:friday']
        times:
          - start_time: '09:00'
            end_time: '18:00'
        location: 'Asia/Shanghai'

  - name: planned-maintenance
    time_intervals:
      - weekdays: ['saturday']
        times:
          - start_time: '02:00'
            end_time: '06:00'
        location: 'Asia/Shanghai'

# --- route 树 ---
route:
  receiver: 'default-slack'
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

  routes:
    # 计划维护:非 Page 告警静默路由到 blackhole
    - matchers:
        - severity=~"chat|log|ticket"
      mute_time_intervals:
        - planned-maintenance
      receiver: 'blackhole'
      continue: false

    # Page:SLO Burn Rate → PagerDuty
    - matchers:
        - severity="page"
      receiver: 'pagerduty-primary'
      group_wait: 10s
      group_interval: 2m
      repeat_interval: 1h
      continue: true

    # Ticket → Jira
    - matchers:
        - severity="ticket"
      receiver: 'jira-sre'
      group_wait: 1m
      group_interval: 10m
      repeat_interval: 12h
      continue: true

    # Chat → Slack 分团队
    - matchers:
        - severity="chat"
        - team="checkout"
      receiver: 'slack-checkout'
      continue: true

    - matchers:
        - severity="chat"
        - team="platform"
      receiver: 'slack-platform'
      continue: true

    # Log 级:不通知
    - matchers:
        - severity="log"
      receiver: 'blackhole'
      continue: false

    # 兜底:未匹配 severity 的告警
    - matchers:
        - severity=~"critical|warning"
      receiver: 'slack-sre-escalation'
      continue: false

# --- inhibit_rules ---
inhibit_rules:
  # 集群级网络故障抑制 per-target 不可达
  - source_matchers:
      - alertname="NetworkDown"
      - severity="page"
    target_matchers:
      - alertname=~"TargetDown|KubeletDown|NodeNotReady"
    equal: ['cluster']

  # Page 级 SLO 抑制同 service 的 Ticket
  - source_matchers:
      - severity="page"
    target_matchers:
      - severity="ticket"
    equal: ['service']

  # 上游 checkout 依赖故障抑制下游 timeout 类 Chat
  - source_matchers:
      - alertname="CheckoutDependencyDown"
      - severity=~"page|ticket"
    target_matchers:
      - alertname=~"DownstreamTimeout.*"
    equal: ['cluster', 'upstream']

  # 全站 outage 抑制单服务 degraded(保留 Page 本身)
  - source_matchers:
      - alertname="GlobalOutage"
      - severity="page"
    target_matchers:
      - severity="chat"
    equal: ['cluster']

# --- receivers ---
receivers:
  - name: 'blackhole'

  - name: 'default-slack'
    slack_configs:
      - channel: '#alerts-unrouted'
        send_resolved: true
        title: '{{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}'

  - name: 'pagerduty-primary'
    pagerduty_configs:
      - routing_key: '<pagerduty-events-api-v2-key>'
        severity: '{{ if eq .CommonLabels.severity "page" }}critical{{ else }}warning{{ end }}'
        description: '{{ .CommonAnnotations.summary }}'
        details:
          firing: '{{ .Alerts.Firing | len }}'
          service: '{{ .CommonLabels.service }}'
          runbook: '{{ .CommonLabels.runbook_url }}'

  - name: 'jira-sre'
    webhook_configs:
      - url: 'https://jira-bridge.example.com/create-ticket'
        send_resolved: true
        http_config:
          bearer_token: '<token>'

  - name: 'slack-checkout'
    slack_configs:
      - channel: '#team-checkout-alerts'
        send_resolved: true

  - name: 'slack-platform'
    slack_configs:
      - channel: '#team-platform-alerts'
        send_resolved: true

  - name: 'slack-sre-escalation'
    slack_configs:
      - channel: '#sre-unlabeled-alerts'
        send_resolved: true
        title: '未分级告警需人工标注 severity'

3.2 Route 树设计原则

  1. 最具体的路由在前team=checkout 应在通用 severity=chat 之前(Alertmanager 按顺序匹配第一个 hit)。
  2. continue: true 用于 Page + Slack 双通道:Page 到 PagerDuty 的同时抄送 Slack war room——但避免 Ticket 也双发 Page。
  3. repeat_interval 按 severity 分级:Page 1h 重复可接受;Chat 可 24h。
  4. 兜底 receiver 必须存在:未匹配路由的告警进 #sre-unlabeled-alerts,每周清理并补 label。

3.3 Grouping 工程细节

Alertmanager grouping 的三个时间参数(官方文档定义):

参数 含义 推荐起点 设错后果
group_wait 同组首条告警后等待多久再发送 Page 10–30s,Ticket 1–5m 太短→多条通知;太长→Page 延迟
group_interval 同组新增告警的最小通知间隔 2–10m 太短→风暴;太长→信息滞后
repeat_interval 未 resolve 时重发间隔 Page 1–4h,Ticket 12–24h 不设→默认 4h;设 0→非法

group_by 标签选择:

# 推荐:按 alertname + 故障域
group_by: ['alertname', 'cluster', 'service']

# 反例:group_by: ['instance'] — 100 台机器 = 100 组通知
# 反例:group_by: [] — 所有告警一组,无关告警捆绑

工程判断:Burn Rate Page 应按 service 分组——checkout 和 payment 同时 Burn 时应是两条 Page,不是一条。

3.4 Inhibition 规则设计

Inhibition 语法(Alertmanager 0.27+ 使用 matchers):

设计 checklist:

  1. 画依赖图:上游挂 → 哪些下游 alert 必然 firing?
  2. 每条 inhibit 写注释说明假设
  3. 避免 equal: [] 过宽抑制
  4. 在 staging 用 amtool 或 UI 验证抑制是否误伤
# 示例:数据库只读模式抑制所有 query timeout Chat
- source_matchers:
    - alertname="PostgreSQLReadOnly"
    - severity=~"page|ticket"
  target_matchers:
    - alertname="QueryTimeoutHigh"
  equal: ['cluster', 'database']

3.5 time_intervals 与维护窗口

mute_time_intervals 挂在 route 上——维护期间 Ticket/Chat 进 blackhole,Page 不应 mute(除非确认无用户流量)。

# 仅非 Page 路由挂 mute
- matchers:
    - severity=~"ticket|chat|log"
  mute_time_intervals:
    - planned-maintenance
  receiver: 'blackhole'

维护前创建 Silence(UI 或 amtool)覆盖已知 firing 规则,比永久改 route 更安全——Silence 有过期时间。

四、告警风暴:机制与治理

4.1 风暴如何形成

典型链路:上游 Redis 连接池耗尽 → 50 个微服务 timeout → 每个服务 3 条规则(latency、error rate、health check)→ 150 条 firing alert → 若 group_by: ['instance'] 且无 inhibit → 150 条 Slack/PagerDuty 通知。

sequenceDiagram
  participant Redis as Redis 连接池
  participant Up as checkout-api
  participant Down as 50 下游服务
  participant Prom as Prometheus
  participant AM as Alertmanager
  participant OC as OnCall 手机

  Redis->>Up: 连接超时
  Up->>Down: 级联 timeout
  loop 每服务 3 规则
    Prom->>Prom: 评估 alert 规则
  end
  Prom->>AM: 150 alerts firing
  Note over AM: group_wait 过短<br/>无 inhibit
  AM->>OC: 87 条 Page/Slack
  OC->>OC: 40 min 找根因
  Note over OC: 应只收到 1 条<br/>CheckoutDependencyDown Page

4.2 风暴治理三板斧

  1. InhibitionCheckoutDependencyDown page 抑制 DownstreamTimeout*
  2. Groupinggroup_by: ['alertname','service']group_wait: 30s
  3. 规则减量:删除”每条 5xx 都 Page”类规则,统一为 Burn Rate

4.3 风暴事后复盘模板

字段 内容
根因 alert CheckoutRedisPoolExhausted
衍生 alert 数量 148
实际通知数 87
应通知数 2(1 Page + 1 Ticket)
修复动作 新增 inhibit;合并规则
误报标注 85 条标注为 duplicate

五、分级告警体系设计模板(与 SLO Burn Rate 绑定)

本节将 SLO 工程 §4 的 Workbook 阈值映射到 Alertmanager 路由与 OnCall 响应。这是全文的决策核心

5.1 四级定义与 Burn Rate 对照

级别 Burn Rate 条件(30d SLO=99.9%) Alertmanager receiver OnCall 动作
Page 1h ≥ 14.4× 或 6h ≥ 6× 或 3d ≥ 1×(持续) pagerduty-primary 5 min ack,开 war room
Ticket 6h ≥ 1× 或 1d ≥ 1× 或 3d ≥ 1×(未达 Page) jira-sre 1 h 内认领
Chat 无 Burn Rate;容量/趋势类 slack-* 工作时间处理
Log 非 prod、信息性 blackhole 仅 Dashboard

Burn Rate 定义(摘自 18-slo):

\[\text{burn\_rate} = \frac{\text{error\_rate}}{1 - \text{SLO}}\]

对 99.9% SLO,\((1 - \text{SLO}) = 0.001\)。14.4×/1h 表示按当前错误率,约 1 小时消耗 30 天预算的 2%。

5.2 端到端映射表

Prometheus alert severity Burn Rate expr AM route PD urgency
CheckoutSLOBurnRateCritical1h page burnrate1h > 14.4 pagerduty high
CheckoutSLOBurnRateCritical6h page burnrate6h > 6 pagerduty high
CheckoutSLOBurnRateCritical3d page burnrate3d > 1 pagerduty high
CheckoutSLOBurnRateWarning6h ticket burnrate6h > 1 jira low
CheckoutSLOBurnRateWarning1d ticket 1d window > 1× jira low
CheckoutSLOBurnRateWarning3d ticket 3d window > 1× jira low
NodeDiskTrend7d chat N/A slack-platform
StagingDeployOK log N/A blackhole

5.3 Page 准入清单

满足 任一 才可 Page:

  1. 用户 facing SLO Burn Rate 达 Workbook Page 阈值
  2. 合成探测确认全站 outage(blackbox probe_success == 0 持续 2m,且影响 prod)
  3. 安全事件(未授权访问 confirmed)——超出本文范围,走安全 runbook

永不 Page:CPU、内存、磁盘百分比、单 Pod restart、cron 失败(除非 cron 是支付链路 SLI 组成部分)。

5.4 Ticket 与 Chat 边界

信号 级别 理由
PG 复制 lag > 30s Chat → Ticket 若持续 1h 未直接 Burn API SLO
API Burn Rate 1×/6h Ticket Workbook 规则 D
证书 14 天过期 Chat 有修复窗口
错误预算剩余 < 20%(Dashboard) Chat 通知 TL 非即时技术响应

5.5 分级 policy 文档片段(可粘贴到内部 wiki)

## Error Budget Alerting Policy v1.2

### Page(立即)
- 条件:任一用户 facing 服务触发 SLO Burn Rate Page 规则(见 Grafana dashboard slo-pages)
- 响应:5 分钟内 PagerDuty ack;15 分钟内 incident commander
- Override:仅 SRE Lead 可 suppress Page(需事后复盘)

### Ticket(1 小时)
- 条件:Burn Rate Ticket 规则 或 非 SLO 但影响单一内部系统
- 响应:Jira 工单 1 小时内认领

### Chat(工作时间)
- 条件:容量、趋势、非用户 facing 退化
- 响应:下一工作日 standup 跟进

### Log
- 条件:staging、信息性事件
- 响应:无

六、PagerDuty 与 OnCall 工程

OnCall 升级状态机

6.1 排班模型

模型 适用 优点 缺点
每周轮换 小团队、单时区 简单 交接边界易漏
Follow-the-sun 全球三时区 本地时间 humane 协调成本高
主备叠加 关键支付链路 冗余 两人同时被叫风险

PagerDuty Schedule 定义”谁值班”;Escalation Policy 定义”无 ack 时叫谁”。

6.2 升级策略示例

stateDiagram-v2
  [*] --> Triggered: Alertmanager Page
  Triggered --> Acknowledged: L1 ack 5min内
  Triggered --> EscalatedL2: 5min 无 ack
  Acknowledged --> Investigating: 打开 runbook
  Investigating --> Resolved: 修复验证
  EscalatedL2 --> EscalatedL3: 15min 仍无 ack
  EscalatedL3 --> Resolved: SRE Lead 介入
  Resolved --> [*]
级别 等待 目标 通知方式
L1 0 Primary on-call Push + 电话
L2 5 min Secondary backup 电话
L3 15 min SRE Lead 电话 + Slack exec

6.3 Incident 生命周期

PagerDuty Incident 状态:triggeredacknowledgedresolved。严格流程:

  1. Trigger:Alertmanager 通过 Events API v2 创建 incident
  2. Ack:L1 确认”我在处理”——不是”我看到了 Slack”
  3. Resolve:Prometheus alert 恢复后 Alertmanager 发 resolved——PD 可 auto-resolve(需配置)
# Alertmanager pagerduty_configs 片段
pagerduty_configs:
  - routing_key: '<integration-key>'
    send_resolved: true
    class: '{{ .CommonLabels.service }}'
    component: '{{ .CommonLabels.alertname }}'
    group: 'slo'
    severity: 'critical'

6.4 Runbook 必备结构

  1. 症状:Burn Rate 14×/1h,checkout 5xx 上升
  2. 诊断三步:Grafana SLO 面板 → 依赖 RED 面板 → 最近 deployment(Events
  3. 缓解:回滚 / 扩容 / 熔断——每步有命令
  4. 验证:Burn Rate 回落、SLI 恢复
  5. 升级条件:15 min 无进展 → 叫 DBRE / 架构师

6.5 值班疲劳度指标

指标 健康范围 超标动作
alerts_per_oncall_shift < 5 需人工介入 告警审计
false_positive_rate < 20% 调阈值 / 加 for
mean_time_to_ack < 5 min(Page) 排班或 PD 配置
pages_without_incident < 10%/月 规则降级

七、告警质量的持续治理

告警体系 6–12 个月无治理会退化为”全部 mute”。

7.1 每周告警审计

从 Alertmanager 或 Grafana OnCall 导出:

  1. 触发次数 Top 10 规则
  2. 无 ack 规则
  3. 同一 alert 重复 > 10 次/shift

对每条:actionable? → 否 → 删除;是但非紧急 → 降级 severity。

7.2 告警归因

每条 Page 事后必须:

未归因 Page 在月度 SLO 评审(18-slo §7.3)中问责。

7.3 季度清理 Sprint

7.4 Alertmanager 高可用

单实例 Alertmanager 挂掉 → 告警路由停止。最小 HA:

Prometheus HA §Alertmanager 部署。

八、工程坑点(真实场景)

8.1 group_wait 设太短

现象:同一 Redis 故障,3 秒内收到 checkout、payment、cart 三条 Page。

原因group_wait: 0 或 5s,三个 service 的 alert 分属不同 group(group_byservice)。

修复

8.2 repeat_interval 误解

现象:告警恢复后仍每小时收到重复 Page。

原因repeat_interval: 1h 且 alert 在阈值边界抖动(flapping)。

修复

8.3 Webhook 限流与丢失

现象:Slack/钉钉/飞书”有时收不到告警”。

原因:Webhook 429/5xx,Alertmanager 不重试无限次——失败通知丢失。

缓解

8.4 severity=critical 无 escalation

现象:critical 告警进 Slack 无人看。

修复:统一 severity 枚举与 route 一致;unlabeled 进 #sre-unlabeled-alerts 并 weekly 修复。

8.5 Inhibition 过宽

现象:真实故障被 suppress——Payment 真正挂时 checkout 的 Page 被误抑制。

修复equalservice;staging 测试 inhibit;文档化每条规则假设。

8.6 Alertmanager 与 Prometheus 标签不一致

现象:route 匹配不到,severity=page 进了 default-slack。

修复:CI 中 promtool check rules + amtool check-config;单元测试 alert label 集合。

8.7 send_resolved: false 的取舍

恢复通知丢失时 on-call 不知道何时停 war room——建议 Page 通道 send_resolved: true;Chat 可 false 减噪。

九、与 Prometheus HA 的集成

9.1 双 Prometheus 单 Alertmanager 集群

两个 Prometheus 实例评估相同规则 → 可能 duplicate alert。Alertmanager 通过 gossip 去重 相同 fingerprint 的 alert。

配置:

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

9.2 避免 alert 标签 churn

pod label 随滚动变化 → grouping 失效。SLO 规则应使用 servicedeployment 等稳定 label。


十、通知渠道集成要点

10.1 Slack

10.2 PagerDuty Events API v2

10.3 钉钉 / 飞书 Webhook

10.4 Email


十一、落地清单


十二、关键概念回顾


十三、下一步

告警体系就绪后,存储账单是下一个治理焦点——采样、保留期、冷热分层。下一篇 存储与成本


上一篇SLO 工程:错误预算、Burn Rate、多窗口告警

下一篇可观测性存储与成本

参考资料

  1. Prometheus, Alertmanager, https://prometheus.io/docs/alerting/latest/alertmanager/
  2. Prometheus, Configuration, https://prometheus.io/docs/alerting/latest/configuration/
  3. Google, The Site Reliability Workbook, Chapter 5: Alerting on SLOs, O’Reilly, 2018
  4. Google, Site Reliability Engineering, Chapter 6: Monitoring Distributed Systems, O’Reilly, 2016
  5. PagerDuty, Response, https://response.pagerduty.com/

附录 A:amtool 常用命令

# 验证配置
amtool check-config alertmanager.yml

# 查看当前活跃 alert(需连接 AM API)
amtool alert query

# 创建 2 小时 silence
amtool silence add alertname=CheckoutSLOBurnRateCritical1h \
  --comment "planned load test" \
  --duration 2h

# 测试 route(Alertmanager 0.27+)
amtool config routes test --config.file=alertmanager.yml \
  --tree --verify.receivers \
  severity=page service=checkout

本环境未安装 amtool——命令来自 Alertmanager 官方文档。


附录 B:告警模板 slack.tmpl

{{ define "slack.slo.title" }}
[{{ .Status | toUpper }}] {{ .CommonLabels.severity }}{{ .CommonLabels.service }}
{{ end }}

{{ define "slack.slo.text" }}
{{ range .Alerts }}
*{{ .Annotations.summary }}*
Burn Rate alert — Runbook: {{ .Labels.runbook_url }}
{{ end }}
{{ end }}

附录 C:Synthetic alert 测试步骤

  1. 在 staging Prometheus 注入高 error rate recording
  2. 确认 slo:*:burnrate1h 超阈值
  3. 观察 Alertmanager UI grouping
  4. 验证 PagerDuty staging service 收到 1 条 incident
  5. 恢复 error rate,确认 resolved 通知

附录 D:与 Chaos 工程衔接

混沌工程 实验前: - 创建 silence 覆盖预期 Chat 告警 - silence Page 规则——验证 Burn Rate 是否正常触发 - 实验后检查 false positive 归因


附录 E:Multi-tenant 路由预告

多租户 场景下 route 按 tenant 分叉——每 tenant 独立 PagerDuty service。本文单租户配置需复制 route 子树。


附录 F:常见问题

F.1 Page 和 critical 能否混用?

不建议。critical 在 Prometheus 社区无统一定义。使用 page|ticket|chat|log 并与 Alertmanager route 一一对应。

F.2 Burn Rate 告警和 5xx 告警能否并存?

可以,但 5xx 应为 Ticket/Chat。Page 仅 Burn Rate——避免双 Page。

F.3 一个 alert 能否同时 Page 和 Slack?

可以:continue: true 匹配 pagerduty 后再匹配 slack-warroom。

F.4 Silence 和 mute_time_intervals 区别?

Silence 是运行时 API/UI 创建,有过期;time_intervals 是配置内周期性维护窗口。

F.5 Alertmanager 挂时 Prometheus 会怎样?

Prometheus 仍评估规则,但通知堆积在 AM 恢复前可能延迟——必须 HA。


附录 G:案例:支付链路 Redis 故障

背景:checkout SLO 99.95%,200 微服务。

时间线: - T+0:Redis pool 满,checkout Burn Rate 升至 18×/1h - T+1min:Page 触发(单条,group_by service) - T+3min:inhibit 抑制 40 条 DownstreamTimeout Chat - T+12min:扩容 Redis connection,Burn Rate 降至 2× - T+25min:resolved

教训:若无 inhibit,T+1min 会收到 40+ Slack。


附录 H:案例:发布回归 Burn Rate 慢性

背景:canary 发布引入 0.5% 额外 5xx,未达 Page 阈值。

时间线: - T+6h:Ticket 规则 burnrate6h > 1 触发 - TL 在 standup 决定回滚 - 错误预算消耗 8%/月 而非 2%

教训:Ticket 规则抓慢性退化;Page 抓突发。


附录 I:告警规则审查记录表(模板)

规则名 severity 上周触发 ack 率 false+ 动作
CheckoutSLOBurnRateCritical1h page (导出填写)
NodeCPUHigh chat
PodRestart ticket

审查人:________ 日期:________

说明:数字须从 Alertmanager / Grafana OnCall 导出,切勿编造。


附录 J:按团队的 Route 子树示例

checkout 团队独立 war room,platform 团队走共享频道:

routes:
  - matchers:
      - severity="page"
      - team="checkout"
    receiver: pagerduty-checkout
    continue: true
  - matchers:
      - severity="page"
      - team="checkout"
    receiver: slack-warroom-checkout
    continue: false

  - matchers:
      - severity="ticket"
      - team="checkout"
    receiver: jira-checkout

  - matchers:
      - severity="chat"
      - team="platform"
    receiver: slack-platform

原则:Page receiver 按 用户 facing 服务 拆分 PagerDuty service——便于 escalation policy 绑定正确 TL。


附录 K:本环境验证说明

状态
OS Linux WSL2(编写环境)
Alertmanager 未安装
amtool 未安装
alertmanager.yml 按官方 0.27 文档结构编写

建议验证

  1. amtool check-config alertmanager.yml
  2. amtool config routes test --tree --verify.receivers severity=page service=checkout
  3. Staging 注入 synthetic error rate,确认 1 条 Page + inhibit 衍生 Chat

18-slo 附录 K 环境说明一致。


附录 L:Inhibition 规则库(可复用片段)

L.1 Kubernetes 集群级

- source_matchers:
    - alertname="KubeAPIDown"
    - severity="page"
  target_matchers:
    - alertname=~"Kube.*"
  equal: ['cluster']

L.2 数据库只读

- source_matchers:
    - alertname="PostgreSQLReadOnly"
  target_matchers:
    - alertname=~"QueryTimeout|ReplicationLag"
  equal: ['cluster', 'database']

L.3 全站 CDN 故障

- source_matchers:
    - alertname="CDNOriginUnreachable"
    - severity="page"
  target_matchers:
    - alertname=~"Origin5xxRate"
  equal: ['region']

每条规则在注释中写清 equal 字段假设——staging 误抑制代价高。


附录 M:Grafana OnCall 与原生 Alertmanager

Grafana Cloud OnCall 可替代 PagerDuty + 部分 AM 路由。迁移注意:

能力 Alertmanager Grafana OnCall
grouping/inhibit 原生 需映射或保留 AM
escalation 外部 PD 内置
silence amtool/UI OnCall UI

混合架构(常见):Prometheus → Alertmanager(group/inhibit)→ OnCall webhook(escalation)。


附录 N:Slack / 钉钉 Webhook 集成要点

N.1 Slack

slack_configs:
  - channel: '#sre-pages'
    send_resolved: true
    title: '{{ template "slack.slo.title" . }}'
    text: '{{ template "slack.slo.text" . }}'
    actions:
      - type: button
        text: 'Runbook'
        url: '{{ .CommonLabels.runbook_url }}'

N.2 钉钉(合成示例)

钉钉自定义机器人需 msgtype: markdown,且安全设置可能要求关键词。Alertmanager 原生无钉钉 receiver——通常用 prometheus-webhook-dingtalk 等中转:

webhook_configs:
  - url: 'http://dingtalk-bridge:8060/dingtalk/webhook1/send'
    send_resolved: true

:钉钉群机器人约 20 条/分钟 限制(以当前开放平台文档为准)——告警风暴时 429,通知丢失。Page 必须走电话通道。

N.3 飞书

与钉钉类似,通过 webhook 中转。消息体长度限制——长 annotation 需截断。


附录 O:Alertmanager 配置语法版本

版本 匹配语法 说明
< 0.22 match / match_re 已弃用
≥ 0.22 matchers 推荐 label="value"
≥ 0.27 time_intervals 替代部分 silence 场景

迁移时全局搜索 match:matchers:


附录 P:Alert 状态生命周期

Prometheus alert 状态:inactivependingfor: 窗口内)→ firingresolved

Alertmanager 侧:activesuppressed(inhibit/silence)→ unprocessed 通知队列。

调试


附录 Q:Runbook 模板(Burn Rate Page)

# Runbook: {{ service }} SLO Burn Rate Page

## 1. 确认影响
- 打开 Grafana: slo-{{ service }}
- 当前 Burn Rate: ___×  错误预算剩余: ___%

## 2. 最近变更
- 查 Events 面板 / ArgoCD 最近 2h 部署

## 3. 依赖检查
- RED 面板: 5xx rate by dependency
- 若单依赖 → 联系 owner team

## 4. 缓解
- [ ] 回滚最近发布
- [ ] 扩容(HPA / 手动)
- [ ] 熔断非关键功能

## 5. 升级
- 15 min 无进展 → TL
- 30 min → 架构师

## 6. 事后
- 关联 Incident ID
- 标注 false_positive 或 root_cause

附录 R:CI 中校验告警配置

# .github/workflows/observability.yml 片段
- name: Check Prometheus rules
  run: promtool check rules rules/*.yml

- name: Check Alertmanager config
  run: amtool check-config alertmanager/alertmanager.yml

- name: Test routes
  run: |
    amtool config routes test \
      --config.file=alertmanager/alertmanager.yml \
      --tree \
      severity=page team=checkout

本环境未运行 promtool——CI 模板供读者粘贴。


附录 S:更多抑制设计场景

根因 alert 应抑制的衍生 alert equal 建议
LoadBalancerUnhealthy BackendTargetDown lb, region
KafkaBrokerDown ConsumerLagHigh(所有 consumer) cluster
DNSResolutionFailure ExternalAPITimeout cluster
CertificateExpired TLSHandshakeFailure cert_name

设计方法:画 故障传播 DAG,每条边对应一条 inhibit 候选——再 pruning 避免 over-inhibit。


附录 T:OnCall 排班与 Burn Rate 联动

大促前:

  1. 确认 Page 规则未 silence
  2. 增加 L2 backup 到 escalation policy
  3. Chat 级容量告警提前 48h 处理——避免与 SLO 失败叠加

大促中:


附录 U:告警指标(自监控)

# Alertmanager 通知失败率
rate(alertmanager_notifications_failed_total[1h])
/
rate(alertmanager_notifications_total[1h])

# 活跃 alert 数
alertmanager_alerts{state="active"}

# 被抑制 alert 数
alertmanager_alerts{state="suppressed"}

notifications_failed_rate > 0.01 → Ticket 修 webhook 网关。


附录 V:与 Events 关联

Events 面板标注 deployment 时间——Burn Rate Page runbook 第二步查变更。Grafana 关联:alert annotation + Loki | json | event_type="deploy"


附录 W:术语对照

中文 英文 组件
分组 Grouping Alertmanager
抑制 Inhibition Alertmanager
静默 Silence Alertmanager UI/amtool
升级 Escalation PagerDuty
值班 On-call Schedule

附录 X:Grouping 场景演算

假设 Redis 故障触发 3 条 Page 规则(checkout、payment、cart 各一条 Burn Rate),group_by: ['alertname','cluster']

配置 通知条数 说明
group_by: ['service'] 3 每 service 一条——合理若需分 team
group_by: ['cluster'] 1 合并为一条——适合同一 war room
group_by: ['instance'] 50+ 反例

Page 级 group_wait: 10s 允许三条 service alert 进同一 group(若 group_by 不含 service)——值班人一次 ack 三个 incident 或 PD 合并 dedup_key。


附录 Y:与 18-slo 六条规则的完整映射

Workbook 规则 Prometheus alert severity AM receiver
A: 1h ≥ 14.4× CheckoutSLOBurnRateCritical1h page pagerduty
B: 6h ≥ 6× CheckoutSLOBurnRateCritical6h page pagerduty
C: 3d ≥ 1× CheckoutSLOBurnRateCritical3d page pagerduty
D: 6h ≥ 1× CheckoutSLOBurnRateWarning6h ticket jira
E: 1d ≥ 1× CheckoutSLOBurnRateWarning1d ticket jira
F: 3d ≥ 1× CheckoutSLOBurnRateWarning3d ticket jira

Inhibit:severity=page 抑制同 serviceseverity=ticket——避免 Page 与 Ticket 双发同一事件。

Recording rules 名称须与 18-slo §3 一致:slo:checkout:burnrate1h 等。


附录 Z:Silence 最佳实践

# 计划 load test 前 silence Chat 级,保留 Page
amtool silence add severity=chat cluster=staging \
  --comment "load test 2026-06-20" \
  --duration 4h \
  --author "sre-oncall"

# 切勿 silence severity=page(除非 SRE Lead 书面 override)

Silence 过期后自动恢复——比改 alertmanager.yml 更安全。维护窗口用 time_intervals + mute_time_intervals 处理重复性维护。


附录 AA:告警风暴演练 Checklist


附录 AB:PagerDuty Service 与 Team 映射

PagerDuty Service 对应 Prometheus team Escalation Policy
checkout-prod checkout checkout-ep
payment-prod payment payment-ep
platform-infra platform platform-ep

Alertmanager pagerduty_configs.routing_key 按 service 路由——避免所有 Page 进同一 PD service 导致错误 escalation。


附录 AC:repeat_interval 与 flapping 数值示例

假设 alert 在阈值边界抖动:firing 2min → resolved 1min → firing。

repeat_interval 1h 内通知次数(近似)
15m 4
1h 1
4h(默认) 1

配合 Prometheus for: 5m 可显著减 flapping——先调 for,再调 repeat_interval


附录 AD:Webhook 失败监控告警

# meta-alert — 告 Alertmanager 自身
- alert: AlertmanagerNotificationFailing
  expr: |
    rate(alertmanager_notifications_failed_total[5m])
    / rate(alertmanager_notifications_total[5m]) > 0.05
  for: 10m
  labels:
    severity: ticket
    team: platform
  annotations:
    summary: "Alertmanager 通知失败率 {{ $value | humanizePercentage }}"

Meta-alert 用 Ticket 而非 Page——避免 AM 故障时的递归 Page 风暴。


附录 AE:Blackbox 与 SLO Page 并列

全站 outage 时 blackbox probe_success == 0 可与 Burn Rate 同时 Page——应用 group_by: ['alertname'] 合并为一条 war room 通知,或 inhibit 较低优先级 probe 只留 Burn Rate。

- alert: SiteProbeFailed
  expr: avg(probe_success{job="blackbox"}) < 0.5
  for: 2m
  labels:
    severity: page
    team: platform

附录 AF:国际化团队通知

Follow-the-sun 排班时 Alertmanager route 按 region label 分叉 receiver——severity=page + region=apac → APAC PD schedule。避免 UTC 03:00 Page 打到美洲值班者。


附录 AG:告警文档化要求

每条新 alerting rule PR 必须含:

  1. severity 分级理由(对照 §5.3 Page 准入)
  2. runbook 链接
  3. inhibit 依赖说明
  4. 预期触发频率(order-of-magnitude)
  5. staging 验证截图或 amtool 输出(有环境时)

附录 AH:版本历史

版本 日期 变更
v1.0 2026-06-11 提纲
v1.1 2026-06-18 深化:完整 alertmanager.yml、风暴时序、SLO 分级模板

附录 AI:Alertmanager UI 调试

  1. /#/alerts — active / suppressed
  2. suppressed 项查看 inhibited by
  3. /#/silences — 误 silence
  4. /#/status — cluster health

API: GET /api/v2/alerts?active=true&silenced=false&inhibited=false


附录 AJ:DB 层 Ticket 路由

PG 21-monitoring 指标 severity: ticket, team: dbre——不 Page API on-call。


附录 AK:Opsgenie 等价配置

opsgenie_configspagerduty_configs 结构类似——escalation 在 SaaS 侧重配。


附录 AL:告警命名规范

Page<Service><Condition><Window> 例:PageCheckoutBurnRate1h


附录 AM:维护窗口公告模板

[Maintenance] cluster=prod-eu-1 2026-06-20 02:00–06:00 CST
Chat muted; SLO Pages active. Silence: (id)

附录 AN:文档修订

v1.1(2026-06-18):深化 Alertmanager 配置、SLO 分级模板、风暴治理与附录 K 环境说明。

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-22 · architecture / observability

可观测性工程

从 Metrics、Logs、Traces 到 Profiling、eBPF、OpenTelemetry 与 SLO 治理,面向中国工程团队的可观测性系统化手册。全 25 篇。

2026-04-22 · architecture / observability

【可观测性工程】指标体系设计:USE、RED、Golden Signals 与业务 KPI

USE 方法论适用于资源,RED 方法论适用于请求,Golden Signals 适用于服务——三套方法论各有其适用对象。本文从 Brendan Gregg、Tom Wilkie、Google SRE 的原始定义出发,构建覆盖资源→服务→业务的完整指标体系,并给出 Prometheus 命名规范、基数治理策略与可抄的指标清单。


By .