正在加载,请稍候…

SRE 事件管理:值班轮换、事后复盘、SLO/SLI/SLA 定义与错误预算管理

构建稳健的 SRE 事件管理实践:设计高效的值班轮换、运行无责事后复盘、定义有意义的 SLO 和 SLI,并利用错误预算平衡可靠性与功能迭代速度。

SRE Incident Management: On-Call Rotation, Post-Mortems, SLO/SLI/SLA Definitions

SRE 事件管理:值班轮换、事后复盘、SLO/SLI/SLA 定义与错误预算管理

站点可靠性工程将软件工程纪律引入运维。其核心在于定义可靠性的含义、客观地衡量它,并在可靠性与功能迭代速度之间做出数据驱动的权衡。本指南涵盖了从值班设计到错误预算策略的完整事件管理生命周期。

SRE 可靠性框架

业务需求 --> SLA(外部承诺)
       |
       v
工程目标 --> SLO(内部目标,比 SLA 更严格)
       |
       v
测量 --> SLI(实际衡量的指标)
       |
       v
错误预算 = 100% - SLO 目标

SRE Incident Management: On-Call Rotation, Post-Mortems, SLO/SLI/SLA Definitions illustration

定义 SLI(服务等级指标)

SLI 是服务行为的定量测量。选择能反映用户体验的 SLI:

基于请求的 SLI

# 可用性 SLI
availability_sli = good_requests / total_requests

# 其中“良好”意味着:
# - 状态码 < 500
# - 响应时间 < 500ms
# - 响应体是有效的 JSON

# 延迟 SLI
latency_sli = requests_under_threshold / total_requests
# 例如,在 < 200ms 内完成的请求

PromQL SLI 计算

# 30 天内的可用性 SLI
(
  sum(rate(http_requests_total{status!~"5.."}[30d]))
  /
  sum(rate(http_requests_total[30d]))
)

# 延迟 SLI:请求中 < 300ms 的比例
(
  sum(rate(http_request_duration_seconds_bucket{le="0.3"}[30d]))
  /
  sum(rate(http_request_duration_seconds_count[30d]))
)

按服务类型划分的适当 SLI

服务类型 主要 SLI 次要 SLI
面向用户的 API 可用性 延迟(P99)
数据管道 新鲜度 完整性
存储 持久性 吞吐量
批处理作业 完成率 持续时间

设置 SLO(服务等级目标)

SLO 是您对自己设定的内部目标。它们应比 SLA 更严格,以提供缓冲。

# slo-config.yaml
slos:
  - name: "API Availability"
    description: "成功请求的百分比"
    sli:
      metric: availability
      query: |
        sum(rate(http_requests_total{status!~"5.."}[30d]))
        / sum(rate(http_requests_total[30d]))
    target: 0.999  # 99.9% = 每月约 43.8 分钟停机
    window: 30d
    
  - name: "API Latency P99"
    description: "99 百分位请求延迟低于 500ms"
    sli:
      metric: latency
      query: |
        histogram_quantile(0.99,
          sum by (le) (rate(http_request_duration_seconds_bucket[30d]))
        ) < 0.5
    target: 0.95   # 95% 的时间 P99 低于 500ms
    window: 30d

错误预算

错误预算是指允许的不可靠性:

错误预算 = 1 - SLO 目标
99.9% SLO => 0.1% 错误预算 => 每月 43.8 分钟
99.5% SLO => 0.5% 错误预算 => 每月 3.65 小时
99.0% SLO => 1.0% 错误预算 => 每月 7.3 小时

错误预算策略

错误预算剩余 > 50%:
  - 功能开发按正常节奏进行
  - 允许实验和有风险的部署

错误预算剩余 10-50%:
  - 提高监控和告警灵敏度
  - 所有事件都需要事后复盘
  - 推迟非关键的有风险部署

错误预算剩余 < 10%:
  - 功能冻结:仅进行可靠性工作
  - 所有部署需要审批
  - 指定事件指挥官

错误预算耗尽(0%):
  - 完全冻结,直到新的预算周期
  - 需要通知管理层
  - 强制可靠性冲刺

值班轮换设计

SRE Incident Management: On-Call Rotation, Post-Mortems, SLO/SLI/SLA Definitions illustration

轮换原则

  1. 主/备配对 — 每个班次都有备份
  2. 随太阳轮转 — 将告警路由到醒着的工程师
  3. 负载均衡 — 公平分配事件
  4. 升级路径 — 清晰的联系链
# PagerDuty 排班(通过 Terraform)
resource "pagerduty_schedule" "primary" {
  name      = "Backend Primary On-Call"
  time_zone = "UTC"

  layer {
    name                         = "Weekly Rotation"
    start                        = "2026-01-01T00:00:00+00:00"
    rotation_virtual_start       = "2026-01-01T00:00:00+00:00"
    rotation_turn_length_seconds = 604800  # 1 周

    users = [
      pagerduty_user.alice.id,
      pagerduty_user.bob.id,
      pagerduty_user.carol.id,
      pagerduty_user.dave.id,
    ]
  }
}

resource "pagerduty_escalation_policy" "backend" {
  name = "Backend Escalation"

  rule {
    escalation_delay_in_minutes = 5
    target {
      type = "schedule_reference"
      id   = pagerduty_schedule.primary.id
    }
  }

  rule {
    escalation_delay_in_minutes = 10
    target {
      type = "schedule_reference"
      id   = pagerduty_schedule.secondary.id
    }
  }

  rule {
    escalation_delay_in_minutes = 15
    target {
      type = "user_reference"
      id   = pagerduty_user.engineering_manager.id
    }
  }
}

值班 Runbook 模板

# 服务:Payment API

## 快速参考
- 仪表盘:https://grafana.example.com/d/payment-api
- 日志:https://kibana.example.com/app/payment-api
- Runbooks:https://wiki.example.com/runbooks/payment-api

## 告警:HighErrorRate
**严重级别:** 警告 / 严重(>5%)

**症状:** 用户无法完成结账

**调查步骤:**
1. 检查错误率仪表盘
2. grep 日志查找 5xx 错误:`kubectl logs -n production -l app=payment-api --since=10m | grep "ERROR"`
3. 检查数据库连接池:`kubectl exec -n production deploy/payment-api -- /health/db`
4. 检查上游支付提供商状态:https://status.stripe.com

**修复措施:**
- 如果数据库连接耗尽:`kubectl rollout restart deploy/payment-api -n production`
- 如果上游提供商中断:在配置映射中切换到备用提供商
- 如果是代码缺陷:回滚:`kubectl rollout undo deploy/payment-api -n production`

**升级:** 如果 30 分钟内未解决,联系 payment-team-lead

事件响应流程

严重级别

级别 用户影响 响应时间 示例
SEV-1 完全中断 立即 结账不可用,100% 错误率
SEV-2 严重降级 15 分钟 >50% 错误,>10x 延迟
SEV-3 轻微降级 1 小时 错误率升高,单个区域
SEV-4 最小影响 下一个工作日 非关键功能不可用

事件指挥官角色

事件指挥官职责:
1. 声明事件严重级别
2. 建立沟通渠道(#incident-YYYY-MM-DD-description)
3. 分配角色:技术负责人、沟通负责人、记录员
4. 每 15 分钟(SEV-1)或 30 分钟(SEV-2)提供状态更新
5. 对修复措施做出执行/不执行决策
6. 声明事件已解决
7. 在 48 小时内安排事后复盘

无责事后复盘

目标是学习,而非指责。关注系统和流程,而非人。

SRE Incident Management: On-Call Rotation, Post-Mortems, SLO/SLI/SLA Definitions illustration

事后复盘模板

# 事后复盘:Payment Service 中断 - 2026-05-15

**状态:** 完成
**严重级别:** SEV-1
**持续时间:** 47 分钟(14:23 UTC 至 15:10 UTC)
**影响:** 约 12,000 名用户无法完成结账;估计收入影响约 $180k

## 时间线

| 时间 (UTC) | 事件 |
|---|---|
| 14:20 | 开始部署 payment-api v2.4.1 |
| 14:23 | 告警:ErrorRate > 50%(PagerDuty) |
| 14:25 | 值班工程师确认 |
| 14:28 | 事件声明为 SEV-1 |
| 14:35 | 确定根本原因:数据库连接字符串配置错误 |
| 14:50 | 开始回滚 |
| 15:05 | 错误率恢复至基线 |
| 15:10 | 事件解决 |

## 根本原因

v2.4.1 部署引入了一项配置更改,在生产环境中使用了 staging 数据库连接字符串。该配置错误未在 CI 中被捕获,因为集成测试针对的是 mock 而非真实数据库。

## 促成因素

1. 未验证数据库连接字符串是否与预期环境匹配
2. 部署流水线在部署后未对生产环境运行冒烟测试
3. 配置管理允许在生产配置文件中出现 staging 值

## 行动项

| 行动 | 负责人 | 截止日期 | 优先级 |
|---|---|---|---|
| 添加配置验证,检测生产环境中的 staging 值 | Platform Team | 2026-05-22 | P1 |
| 在部署流水线中添加部署后冒烟测试 | DevOps Team | 2026-05-29 | P1 |
| 在 CI 中实现配置模式验证 | Backend Team | 2026-06-05 | P2 |
| 审查所有服务配置是否存在类似问题 | All Teams | 2026-06-12 | P2 |

## 做得好的方面

- 部署后 3 分钟内触发告警
- 团队通过事件频道迅速集结
- 回滚流程文档完善且执行迅速

错误预算消耗速率告警

计算消耗速率以在预算耗尽前检测到:

# 当前消耗速率(我们消耗错误预算的速度)
# 1.0 = 以 SLO 速率精确消耗
# 14.4 = 以预算允许的 14.4 倍消耗(对于 99.9% SLO,将在 2 小时内耗尽)

(1 - (
  sum(rate(http_requests_total{status!~"5.."}[1h]))
  / sum(rate(http_requests_total[1h]))
)) / (1 - 0.999)

基于预算耗尽时间的告警阈值:

  • 消耗速率 > 14.4 持续 1 小时且 5 分钟 = 页面(预算在 2 小时内耗尽)
  • 消耗速率 > 6 持续 6 小时且 30 分钟 = 工单(预算在 5 天内耗尽)

结论

有效的 SRE 事件管理将被动救火转变为系统化的可靠性工程实践。SLI 提供用户体验的客观测量。SLO 设定与业务需求一致的进取目标。错误预算在工程和产品之间创建了关于风险容忍度的共同语言。无责事后复盘从失败中产生组织学习。这些实践共同创造了一个随时间推移不断提高可靠性的良性循环。