文章

SRE-SLI-SLO-ErrorBudget实战手册

SLI / SLO / Error Budget 实战手册

SRE 哲学的发动机。没有 SLI/SLO,就没有 “该不该发版”的量化决策依据。本章从定义到告警,给全套可落地的模板和 PromQL。

一、SLI → SLO → Error Budget 的关系链

graph LR
    A[用户旅程] --> B[SLI 指标]
    B --> C[SLO 目标]
    C --> D[Error Budget]
    D --> E{预算充足?}
    E -->|Yes| F[正常发布]
    E -->|No| G[冻结发布<br/>全力修复]
    D --> H[烧钱率告警]
    H --> I[On-Call 响应]
  1. SLI(Service Level Indicator):度量。如 “5 分钟内 99.95% 的请求响应时间 < 300ms”
  2. SLO(Service Level Objective):目标。如 “99.9% 可用性(月度窗口)”
  3. Error Budget:1 - SLO,即允许的 “错误配额”。99.9% SLO = 每月 43 分钟不可用

[!important] 为什么 100% 不是一个好目标 用户其实分不清 99.99% 和 100%。追求 100% 意味着 0 容忍变更 = 停止发版 = 创新能力归零。Error Budget 就是 “允许你偶尔犯错”的机制,在可靠性和发版速度间找到平衡。


二、SLI 定义工作坊模板

Step 1:定义用户旅程(Critical User Journey)

不要从系统角度定义,从用户视角定义。

以 care-mate 为例:

#用户旅程关键步骤涉及服务
1创建护理订单登录 → 填写 → 提交 → 支付回调care-mate-api, user-svc, payment-svc
2查看护理记录登录 → 列表 → 详情care-mate-api, record-svc
3评价护理员登录 → 评分 → 提交care-mate-api, review-svc

Step 2:为每个旅程选 SLI 类型

SLI 类型适用场景示例 PromQL
可用性任何请求-响应服务sum(rate(http_total{status!~"5.."}[5m])) / sum(rate(http_total[5m]))
延迟对响应时间敏感的服务histogram_quantile(0.99, sum(rate(http_duration_bucket[5m])) by (le, endpoint))
吞吐API 限流/容量规划sum(rate(http_requests_total[5m]))
数据新鲜度数据管道/缓存time() - max(cache_last_refresh_timestamp)
持久性存储系统sum(rate(storage_write_success_total[5m])) / sum(rate(storage_write_total[5m]))

Step 3:SLI 规格说明书(实际落地模板)

# sli-spec/care-mate-api.yml
service: care-mate-api
slis:
  - name: availability
    description: "API 可用性——非 5xx 响应占比"
    promql: |
      sum(rate(http_requests_total{status!~"5.."}[5m]))
        / sum(rate(http_requests_total[5m]))
    unit: ratio
    slo_target: 0.999      # 99.9%

  - name: latency_p99
    description: "创建订单接口 P99 延迟"
    promql: |
      histogram_quantile(0.99,
        sum(rate(http_request_duration_seconds_bucket{endpoint="/api/orders"}[5m]))
        by (le))
    unit: seconds
    slo_target: 0.3        # < 300ms

  - name: latency_p95
    description: "订单列表 P95 延迟"
    promql: |
      histogram_quantile(0.95,
        sum(rate(http_request_duration_seconds_bucket{endpoint="/api/orders/list"}[5m]))
        by (le))
    unit: seconds
    slo_target: 0.5        # < 500ms

slo_window: 30d           # 月度窗口

三、选择合适的 SLO 目标

3.1 SLO 定级速查表

用户期望可用性 SLO月 Error Budget周 Error Budget适用场景
极高99.99%4.3 min1.0 min支付、认证
99.95%21.6 min5.0 min核心业务 API
99.9%43.2 min10.1 min一般业务接口
99.5%3.6 h50.4 min内部管理后台

[!tip] 如何定 SLO——问三个问题

  1. 用户能忍受多久不可用?(支付 > 管理后台)
  2. 依赖服务(数据库、Redis)的 SLO 是多少?(你不可能比依赖更可靠)
  3. 历史上你做到了吗?(先看三个月的数据,SLO 别订得比实际表现还高)

3.2 依赖链 SLO 计算

你的服务 (SLO=99.9%)
  ├── DB (SLO=99.95%)
  ├── Redis (SLO=99.99%)
  └── 下游 RPC (SLO=99.9%)

组合可用性 = 99.95% × 99.99% × 99.9% = 99.84%
你的 SLO 必须 ≤ 99.84%,否则不可行

四、Error Budget 烧钱率告警——多窗口法

Google SRE 的核心发明:Error Budget Burn Rate Alert。不是简单设阈值,而是用多窗口检测烧钱速度。

4.1 多窗口配置表

严重程度短窗口长窗口烧钱率阈值含义
Critical1h5m14.4x1h 内烧掉月预算的 2%
Warning6h30m6x6h 内烧掉月预算的 5%
Low3d6h1x3 天内烧掉月预算的 10%

关键设计:短窗口检测快,长窗口防抖动。两个条件同时满足才告警。

4.2 完整告警规则

# rules/error-budget-alerts.yml
groups:
  - name: error_budget_alerts
    rules:

      # ==== 严重级:1h 窗口 + 5m 窗口均 > 14.4x ====
      - alert: ErrorBudgetBurn_Critical
        expr: |
          (
            sum(rate(http_requests_total{status=~"5.."}[1h]))
              / sum(rate(http_requests_total[1h]))
          ) / (1 - 0.999) > 14.4
          and
          (
            sum(rate(http_requests_total{status=~"5.."}[5m]))
              / sum(rate(http_requests_total[5m]))
          ) / (1 - 0.999) > 14.4
        for: 2m
        labels:
          severity: critical
          team: sre
        annotations:
          summary: "{{ $labels.job }} Error Budget 严重烧钱"
          description: |
            1h burn rate: {{ $value | humanize }}
            预计剩余 Error Budget: {{ . | query "error_budget_remaining_ratio" }}%

      # ==== 警告级:6h 窗口 + 30m 窗口均 > 6x ====
      - alert: ErrorBudgetBurn_Warning
        expr: |
          (
            sum(rate(http_requests_total{status=~"5.."}[6h]))
              / sum(rate(http_requests_total[6h]))
          ) / (1 - 0.999) > 6
          and
          (
            sum(rate(http_requests_total{status=~"5.."}[30m]))
              / sum(rate(http_requests_total[30m]))
          ) / (1 - 0.999) > 6
        for: 15m
        labels:
          severity: warning
          team: sre
        annotations:
          summary: "{{ $labels.job }} Error Budget 中速烧钱"

      # ==== 低级别:3d 窗口检测缓慢消耗 ====
      - alert: ErrorBudgetBurn_Low
        expr: |
          (
            sum(rate(http_requests_total{status=~"5.."}[3d]))
              / sum(rate(http_requests_total[3d]))
          ) / (1 - 0.999) > 1
        for: 6h
        labels:
          severity: info
        annotations:
          summary: "{{ $labels.job }} Error Budget 缓慢消耗(3d 趋势)"

4.3 Error Budget Dashboard 关键面板 PromQL

# 1. 当前 Error Budget 剩余比例
1 - (
  sum(increase(http_requests_total{status=~"5.."}[30d]))
    / sum(increase(http_requests_total[30d]))
) / (1 - 0.999)

# 2. 按天展示 Error Budget 消耗
sum(increase(http_requests_total{status=~"5.."}[1d]))
  / sum(increase(http_requests_total[1d]))
  / (1 - 0.999)

# 3. SLO 达标情况(月度)
avg_over_time(
  (sum(rate(http_requests_total{status!~"5.."}[5m])) / sum(rate(http_requests_total[5m])))[30d:]
)

# 4. 预计 Error Budget 耗尽时间(天)
(30 * (1 - 0.999))  # 总预算
  / (
    sum(rate(http_requests_total{status=~"5.."}[30d]))
      / sum(rate(http_requests_total[30d]))
    * 30 * 24 * 3600  # 天 → 秒
  )

五、Error Budget 的使用策略

5.1 “燃尽即冻结”策略

Error Budget > 50%  →  正常发布(无限制)
Error Budget 20~50% →  发布需 Tech Lead 审批
Error Budget < 20%  →  冻结发布,只允许修复
Error Budget 耗尽    →  全员 Gameday,暂停一切变更直到恢复

5.2 Error Budget Policy(团队公约模板)

## Error Budget Policy — care-mate team

### SLO 定义
- 可用性: 99.9%(月度窗口)
- P99 延迟: < 300ms(创建订单接口)

### Error Budget 策略
1. 月度 Error Budget 剩余 > 50%:正常节奏发布
2. 20% ~ 50%:发布需要每周审批一次,附带风险说明
3. < 20%:冻结常规发布,只有 hotfix 和可靠性改进可合入
4. 耗尽:全团队停止功能开发,聚焦可靠性

### 恢复机制
- Error Budget 耗尽后,若连续 7 天 SLO 达标,恢复至 10%
- 每月 1 号重置 Error Budget

### 例外
- 安全漏洞修复不受 Error Budget 限制
- 基础设施变更(如 K8s 升级)使用独立窗口

六、SLO 定义的常见陷阱

[!warning] 坑 1:用平均值代替分位数 P50=50ms 不代表用户体验好——那 1% 的慢请求才是决定性的。永远用 P95/P99。

[!warning] 坑 2:SLO 比依赖系统还高 你依赖的 DB 只有 99.9%,你的 SLO 定 99.99% 纯属骗自己。参见 3.2 节。

[!warning] 坑 3:把所有指标都变成 SLO 建议每个服务 3-5 个 SLO,不会更多。多了没人看,少了不全面。

[!warning] 坑 4:99.9% 和 99.99% 的差别被低估 从 99.9% → 99.99%,可用性提升 10x,但运维成本可能提升 50x。值不值?用 Error Budget 对话来回答。

[!warning] 坑 5:SLO 不 review 每季度 Review SLO 是否合理——业务变了,SLO 也得变。不 review 的 SLO 就是僵尸指标。


七、从 SLI 到自动化的闭环

SLI 定义 → Prometheus Recording Rules
       → Grafana Dashboard(团队全员可见)
       → Alertmanager 告警(Burn Rate)
       → On-Call 响应
       → Postmortem 复盘
       → Action Items(改进可靠性或调 SLO)
       → 回到 SLI 定义

相关笔记