告警设计与事件响应:降噪、分级、值班与事后复盘

系统性告警与事件响应实战指南:告警设计的黄金法则(可行动性/关联上下文/优先级/渐进式)、Four Golden Signals 与 USE/RED 方法论、告警分级(P0/P1/P2/P3)与升级策略、告警疲劳根因分析与降噪手段(抑制/聚合/去重/依赖静默)、值班轮换(on-call)制度、事件响应 SOP(检测/评估/缓解/复盘)、ChatOps / Runbook 自动化、事后复盘模板(Postmortem)与无责文化、MTTR/MTBF/MTTF 指标定义与追踪、PagerDuty/Opsgenie 集成实践。

好的告警是「不打扰」,坏的通知是「狼来了」。 当 PagerDuty 每天响 50 次,团队 3 周内就会学会忽略所有告警——包括真正重要的那个。告警设计的终极目标是:每一次通知都值得被打断。


一、告警设计的黄金法则

1.1 可行动性(Actionable)

❌ 坏告警:"CPU 高" 
   → 高到多少?什么时候?哪个服务?我该做什么?

✅ 好告警:"prod-web-01 CPU 使用率 95%(阈值 85%),
          过去 10 分钟持续上升,已触发自动扩容,
          如 5 分钟后未恢复请检查部署日志: https://..."
   → 包含:指标、上下文、自动动作、下一步指引

1.2 告警四要素

要素要求示例
What明确的问题描述“订单服务 P99 延迟 > 2s”
Where精确的位置/范围“生产环境 /api/checkout 路由”
When时间窗口“从 14:32 持续到现在”
Action建议的操作“查看支付服务日志 / 回滚到 v1.2.2”

二、告警方法论

2.1 Four Golden Signals

Google SRE 推荐的四个黄金信号:

Latency(延迟)
  ├── 它是服务有多慢的衡量
  ├── 区分成功请求和失败请求的延迟
  └── 失败请求可能立即返回,拉低平均值

Traffic(流量)
  ├── 系统承受了多少需求
  ├── HTTP QPS、消息队列消费速率、网络带宽
  └── 用于衡量容量和负载

Errors(错误)
  ├── 多少请求失败
  ├── 显式(HTTP 500)和隐式(HTTP 200 但返回错误)
  └── 用于衡量可靠性

Saturation(饱和度)
  ├── 服务有多"满"
  ├── CPU、内存、磁盘、连接池、队列长度
  └── 通常最预示即将发生的故障

2.2 USE 方法(资源层)

指标CPU内存磁盘 I/O网络连接池
Utilization使用率使用率带宽使用率吞吐量活跃连接
Saturation队列/负载swap 频率IO 队列丢包率等待队列
Errors指令错误OOMIO 错误CRC 错误超时连接

2.3 RED 方法(服务层)

指标说明
Rate每秒请求数
Errors每秒错误数
Duration请求延迟分布

USE 用于资源(机器/容器),RED 用于服务(API/微服务),Four Golden Signals 是更通用的框架。三者互补。


三、告警分级

3.1 P0-P3 分级体系

级别名称响应时间通知方式升级条件
P0紧急(Critical)15 分钟内电话+短信+Slack自动升级
P1高(High)1 小时内短信+Slack2 小时未处理升级
P2中(Medium)4 小时内Slack次日处理
P3低(Low)1 个工作日内邮件/工单无需升级
P0 场景示例:
  - 全部用户无法访问主站
  - 支付成功率 < 90%
  - 数据库主库宕机
  - 安全事件(数据泄露)

P1 场景示例:
  - 核心功能降级(如搜索不可用)
  - 非核心地区访问慢
  - 单实例故障但服务仍可用

P2 场景示例:
  - 监控数据缺失
  - 容量接近阈值(预计 3 天内满)
  - 单节点日志异常

P3 场景示例:
  - 证书 30 天后过期
  - 依赖版本有安全补丁
  - 非紧急优化建议

3.2 Prometheus 告警分级

# alerting_rules.yml
groups:
  - name: service_critical
    rules:
      - alert: PaymentServiceDown
        expr: up{job="payment-service"} == 0
        for: 1m
        labels:
          severity: p0
          team: backend
        annotations:
          summary: "Payment service is down"
          runbook_url: "https://wiki.example.com/runbooks/payment-down"

      - alert: HighPaymentErrorRate
        expr: |
          sum(rate(http_requests_total{job="payment-service",status=~"5.."}[5m])) /
          sum(rate(http_requests_total{job="payment-service"}[5m])) > 0.1
        for: 5m
        labels:
          severity: p0
        annotations:
          summary: "Payment error rate > 10%"

  - name: service_warning
    rules:
      - alert: HighPaymentLatency
        expr: |
          histogram_quantile(0.95,
            rate(http_request_duration_seconds_bucket{job="payment-service"}[5m])
          ) > 2
        for: 10m
        labels:
          severity: p1
        annotations:
          summary: "P95 payment latency > 2s"

四、告警降噪

4.1 告警疲劳根因

告警疲劳的典型原因:
├── 阈值设置不当(太敏感)
├── 缺少 for 持续时间(毛刺触发)
├── 重复通知(未分组/路由)
├── 无意义的告警(无法行动)
├── 依赖服务故障导致级联告警
├── 非工作时间通知非紧急问题
└── 告警恢复时也通知(噪音)

4.2 降噪手段

手段实现效果
分组Alertmanager group_by同类告警合成一条通知
抑制inhibit_rules高优告警抑制低优
静默Scheduled silences维护窗口静默
延迟for: 5m持续一段时间才触发
聚合aggregation按维度汇总
升级escalation超时不处理升级组长
值班表rotation非值班时间不通知

4.3 Alertmanager 降噪配置

# alertmanager.yml
route:
  group_by: ['alertname', 'job', 'severity']
  group_wait: 30s      # 等 30s 聚合同类告警
  group_interval: 5m   # 每 5min 发送一次组内更新
  repeat_interval: 4h  # 4h 内不重复发送同一告警

  routes:
    # P0 → 立即电话
    - match:
        severity: p0
      receiver: pagerduty-p0
      group_wait: 0s
      continue: false

    # P1 → Slack,1h 后升级到 PagerDuty
    - match:
        severity: p1
      receiver: slack-alerts
      routes:
        - match:
            status: "unresolved"
          group_interval: 1h
          receiver: pagerduty-p1

# 抑制:数据库宕机时,抑制所有依赖数据库的告警
inhibit_rules:
  - source_match:
      alertname: DatabaseMasterDown
    target_match_re:
      alertname: .*
    equal: ['datacenter', 'environment']

# 静默:计划维护
# 通过 API 创建:
# curl -X POST alertmanager:9093/api/v1/silences \
#   -d '{"matchers":[{"name":"alertname","value":"HighCPULoad","isRegex":false}],"startsAt":"...","endsAt":"...","createdBy":"ops","comment":"planned maintenance"}'

五、值班制度(On-Call)

5.1 值班设计原则

理想的 On-Call:
├── 频率:每人每 4-6 周一次
├── 时长:一周(自然周)
├── 响应:P0 立即响应,P1 1h 内
├── 补偿:调休或津贴
├── 交接:周五下午交接,同步未处理事项
└── 兜底:升级经理 → VP → CEO(P0 长时间未响应)

糟糕的 On-Call:
├── 频率太高(每周)→ 疲劳、倦怠
├── 没有补偿 → 抵触情绪
├── 响应不及时无惩罚 → 无责任感
└── 告警不真实 → 狼来了

5.2 PagerDuty 配置示例

# escalation_policy.yml
escalation_policy:
  name: Backend On-Call
  description: Backend service escalation

  escalation_rules:
    - escalation_rule:
        targets:
          - type: user_reference
            id: user_1  # 当前值班人
        escalation_delay_in_minutes: 15  # 15 分钟未响应升级

    - escalation_rule:
        targets:
          - type: user_reference
            id: user_2  # 备用值班人 / 组长
        escalation_delay_in_minutes: 15

    - escalation_rule:
        targets:
          - type: user_reference
            id: user_3  # 经理
        escalation_delay_in_minutes: 30

六、事件响应 SOP

6.1 事件生命周期

┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
│ Detect   │ → │ Assess   │ → │ Mitigate │ → │ Resolve  │ → │ Review   │
│ 检测     │   │ 评估     │   │ 缓解     │   │ 解决     │   │ 复盘     │
└──────────┘   └──────────┘   └──────────┘   └──────────┘   └──────────┘
     │              │              │              │              │
     ↓              ↓              ↓              ↓              ↓
  告警触发      影响范围评估    止损措施        根因修复        Postmortem
  监控发现      用户影响量化    回滚/限流       验证恢复        改进措施
  用户反馈      快速分类 P0/P1  降级服务        关闭事件        Action Items

6.2 检测阶段

检测来源优先级:
1. 自动化监控告警(最快速)
2. 用户反馈/客服工单
3. 值班巡检
4. 业务指标下降(转化率、收入)

关键动作:
  - 确认事件真实存在(非误报)
  - 创建事件工单(incident channel)
  - 启动事件响应流程

6.3 评估阶段

评估清单:
□ 影响范围:多少用户?哪些功能?哪些地区?
□ 严重程度:P0/P1/P2/P3
□ 开始时间:何时开始?持续多久了?
□ 相关变更:最近是否有部署/配置变更?
□ 是否已知:是否在 Runbook 中有记录?

6.4 缓解阶段

缓解 ≠ 修复。缓解是让系统恢复可用,根因修复可以后面做。

常见缓解措施:
├── 回滚到上一个版本
├── 重启故障实例
├── 切换流量到备用集群
├── 降级/关闭非核心功能
├── 扩容
├── 开启熔断
└── 切换数据库只读模式

原则:先止血,后手术。

七、事后复盘(Postmortem)

7.1 无责文化(Blameless)

Postmortem 的目标不是「抓出谁犯了错」,而是:
  - 理解系统为什么会允许这个错误发生
  - 识别流程和工具中的漏洞
  - 制定可落地的改进措施

禁止:
  ❌ "XX 为什么不..."
  ❌ "XX 提交了这个有 bug 的代码"

改为:
  ✅ "自动化测试为什么没有捕获这个场景?"
  ✅ "代码审查流程为什么没发现这个问题?"
  ✅ "架构设计上有什么可以改进的地方?"

7.2 Postmortem 模板

# Postmortem: [事件ID] [简要描述]

## 基本信息
- **事件 ID**: INC-2024-0813-001
- **日期**: 2026-08-13
- **持续时间**: 14:32 - 15:15 (43 分钟)
- **影响**: 支付功能不可用,约 12,000 用户受影响
- **严重级别**: P0

## 时间线(精确到分钟)
| 时间 | 事件 |
|------|------|
| 14:28 | v1.3.0 部署到生产 |
| 14:32 | 支付错误率开始上升 |
| 14:35 | PagerDuty P0 告警触发 |
| 14:37 | 值班工程师响应 |
| 14:42 | 确认是 v1.3.0 引入的 bug |
| 14:45 | 回滚到 v1.2.9 |
| 14:50 | 错误率开始下降 |
| 15:15 | 确认全部恢复 |

## 根因分析
5 Whys:
1. 为什么支付失败?→ 银行 API 超时
2. 为什么超时?→ v1.3.0 将超时从 10s 改为 30s,银行侧拒绝连接
3. 为什么改了超时?→ 产品经理要求支持慢银行
4. 为什么没测试到?→ 集成测试环境用的 mock 银行,不模拟超时场景
5. 为什么 mock 不够?→ 缺乏真实第三方依赖的集成测试

## 影响评估
- **用户影响**: 12,000 用户无法完成支付
- **业务影响**: 约 ¥450,000 订单流失
- **SLA 影响**: 支付可用性从 99.95% → 99.2%(月度)

## 已采取的措施
- [x] 回滚到 v1.2.9
- [x] 通知受影响用户
- [x] 补偿优惠券发放

## 改进措施
| 优先级 | 措施 | Owner | 截止日期 |
|--------|------|-------|----------|
| P0 | 增加银行 API 沙箱集成测试 | @dev-a | 2024-08-20 |
| P0 | 部署后自动 Canary 验证 | @dev-b | 2024-09-01 |
| P1 | 支付服务增加熔断降级 | @dev-c | 2024-08-30 |
| P1 | 超时参数改为配置化,无需发版 | @dev-d | 2024-08-25 |

## 经验教训
- 第三方依赖变更需要真实环境验证
- 超时等关键参数应配置化
- Canary 部署应成为强制流程

八、ChatOps 与 Runbook

8.1 ChatOps

ChatOps = 在聊天工具(Slack/Discord)中执行运维操作

示例:
  /incident create payment-service-down P0
  → 创建事件频道 #incident-2024-0813-payment
  → 引入值班工程师 + 相关团队
  → 自动生成时间线
  → 关联最近的部署变更

  /rollback payment-service v1.2.9
  → 执行回滚
  → 在频道中更新状态
  → 记录操作人

好处:
  - 所有操作可审计
  - 团队实时可见
  - 减少上下文切换

8.2 Runbook 模板

# Runbook: Payment Service 不可用

## 检测
- 告警: `PaymentServiceDown``HighPaymentErrorRate`
- 验证: `kubectl get pods -l app=payment-service`

## 评估
- 检查最近部署: `kubectl rollout history deployment/payment-service`
- 检查 pod 状态: `kubectl describe pod <pod-name>`
- 检查日志: `kubectl logs -l app=payment-service --tail=100`

## 缓解(按优先级)
1. 如果最近有部署 → 回滚
   ```bash
   kubectl rollout undo deployment/payment-service
  1. 如果 pod CrashLoop → 检查配置/密钥
    kubectl get configmap payment-config -o yaml
    
  2. 如果是 OOM → 临时扩容内存
    kubectl patch deployment payment-service -p '{"spec":{"template":{"spec":{"containers":[{"name":"payment","resources":{"limits":{"memory":"1Gi"}}}]}}}}'
    

升级

如果 15 分钟内无法缓解,@backend-lead

验证恢复

  • 错误率 < 1%
  • P99 延迟 < 500ms
  • 支付成功率 > 99%

---

## 九、SLA 相关指标

| 指标 | 全称 | 计算 | 意义 |
|------|------|------|------|
| **MTTR** | Mean Time To Recovery | 故障开始到恢复的平均时间 | 团队响应效率 |
| **MTBF** | Mean Time Between Failures | 两次故障间的平均时间 | 系统稳定性 |
| **MTTF** | Mean Time To Failure | 系统正常运行到故障的平均时间 | 可靠性 |

可用性计算公式:
Availability = MTBF / (MTBF + MTTR)

示例:
MTBF = 720h, MTTR = 1h
Availability = 720 / 721 = 99.86%

目标:提高 MTBF(防故障)+ 降低 MTTR(快恢复)


---

## 参考与延伸阅读

- [Google SRE Book — Handling Interrupts](https://sre.google/sre-book/handling-interrupts/)
- [PagerDuty Incident Response](https://response.pagerduty.com/)
- [Awesome Postmortems](https://github.com/danluu/post-mortems)

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「infra」更多文章

  1. 可观测性数据存储选型:TSDB、列式存储、对象存储与成本优化
  2. 云原生 APM 与性能剖析:Continuous Profiling 与火焰图
  3. Kubernetes 可观测性实战:集群、Pod、网络、存储全链路监控