SLO 与错误预算工程:从 SLI 设计到发布冻结的可靠性闭环

深入讲解 SLO 与错误预算工程的 DevOps 实践:SLI 设计(可用性/延迟/错误率)、SLO 目标设定与错误预算计算、告警策略(Multi-window / Multi-burn-rate)、错误预算耗尽处理(冻结发布)、SRE 值班与 On-Call、与混沌工程/发布门禁联动、工具(Prometheus/Pyrra)以及真实案例。

“99.9% 可用性"是句漂亮话——如果没有度量口径,99.9% 只是 PPT 上的数字。SLO(Service Level Objective)把"可靠性"变成可度量、可预算、可执行的工程对象:先用 SLI 定义"什么算好”,再用 SLO 设定"好到什么程度",错误预算则回答"今天能承受多少失败、什么时候该刹车"。本指南完整覆盖 SLO 与错误预算工程:SLI 设计(可用性/延迟/错误率)、SLO 目标与错误预算计算、Multi-window/Multi-burn-rate 告警、错误预算耗尽后的发布冻结、SRE 值班、与混沌工程/发布门禁的联动,以及 Prometheus/Pyrra 落地工具与真实案例。


目录


1. 为什么需要 SLO 与错误预算

1.1 没有 SLO 的两种极端

极端一:拍脑袋定"五个九"(99.999%)
  - 成本极高:冗余、压测、人工值守都按最高标准
  - 团队不敢发布:任何风险都被拒绝

极端二:没有目标
  - 可靠性靠运气:挂了再修,坏了再说
  - 没有度量:无法判断"变好还是变坏"

SLO 的价值:把可靠性从"口号"变成"预算"
  像管理钱一样管理可用性——有限预算,花在刀刃上

1.2 SLO / SLA / SLI 的关系

SLI(指标):实际测得的服务水平,如"请求成功率 99.95%"
SLO(目标):我们承诺的内部目标,如"月成功率 ≥ 99.9%"
SLA(对外契约):给客户的法律承诺,如"月可用性 ≥ 99.9%,否则退款"

关系:SLA 一定基于 SLO,SLO 一定基于 SLI
  通常 SLO 比 SLA 更严格(给自己留缓冲)

💡 核心观点:SLO 的本质是"为可靠性设预算"——错误预算就是"允许失败的时间"。预算充足时可以放开发布,预算耗尽就必须停手修复。这把"快"和"稳"的矛盾转化为一个可计算的数字。


2. SLI 设计:可用性 / 延迟 / 错误率

2.1 好 SLI 的选取原则

SLI 要"对用户有意义":
  - 从用户旅程出发,选用户真正感知的指标
  - 请求成功率(可用性)是最常见 SLI
  - 有时要细分:读路径 / 写路径 / 关键接口各自定义

原则:宁选"一个能准确反映用户体验的 SLI",不选"一堆无感的指标"

2.2 三类典型 SLI

SLI 类型定义示例目标
可用性成功请求 / 总请求月成功率 ≥ 99.9%
延迟请求耗时 P 分位P95 延迟 ≤ 300ms
错误率错误请求 / 总请求错误率 ≤ 0.1%

2.3 SLI 量化示例(Prometheus)

# 可用性 SLI:5 分钟内成功请求占比
sum(rate(http_server_request_count{status!~"5..|4.."}[5m]))
  / sum(rate(http_server_request_count[5m]))
# 延迟 SLI:P95 延迟
histogram_quantile(0.95, sum(rate(http_server_request_duration_bucket[5m])) by (le))

2.4 定义窗口与口径

  - 统计窗口:过去 28 天 / 30 天(滚动)
  - 有效请求:排除爬虫、监控探针(防污染)
  - 成功判定:HTTP 2xx/3xx,业务错误码要单独定义
  - 测量位置:客户端(最能反映用户体验)优先,或入口网关

3. SLO 目标设定与错误预算计算

3.1 SLO 目标怎么定

三步设定法:
  1. 看现状:当前真实 SLI 是多少(先度量再承诺)
  2. 定目标:比现状略严一点,但可达(别一步登天五个九)
  3. 留缓冲:SLO 严于 SLA(如 SLA 99.9%,SLO 设 99.95%)

3.2 错误预算计算

月错误预算 = 总时间 ×(1 - SLO)
  SLO 99.9%  → 每月允许失败 0.1% ≈ 43.2 分钟
  SLO 99.95% → 每月允许失败 0.05% ≈ 21.6 分钟
  SLO 99.99% → 每月允许失败 0.01% ≈ 4.3 分钟

错误预算消耗 = 1 -(当前 SLI 达标时间占比)
SLO每月错误预算每天错误预算
99.9%≈ 43.2 分钟≈ 86.4 秒
99.95%≈ 21.6 分钟≈ 43.2 秒
99.99%≈ 4.3 分钟≈ 8.6 秒
99.999%≈ 26 秒≈ 0.86 秒

3.3 错误预算的两种计算口径

口径一:时间口径(假设计算 99.9% = 每月宕机不超过 43 分钟)
口径二:请求口径(成功率口径:99.9% 请求成功)

注意:时间口径常用于基础设施(uptime),
      请求口径更适合服务(成功率)。选择要对齐业务语义。

4. 告警策略:Multi-window / Multi-burn-rate

4.1 为什么不能用"单一阈值告警"

传统告警:SLO 掉到 99.5% 以下才报警
  - 问题:等跌破目标才告警,错误预算已大量消耗
  - 噪声:偶发小抖动频繁触发,On-Call 疲劳

Google SRE 方法:Burn Rate(烧钱速率)告警
  用"错误预算消耗速度"而非"绝对水位"来告警

4.2 Multi-burn-rate 告警

按消耗速率分两档:
  - 快速燃烧(如 14.4x):错误预算在 1 小时内烧完 5%+
    → Page(立即叫醒)
  - 慢速燃烧(如 2x):预算在 1 天内烧完
    → Ticket(工作日处理)

配合 Multi-window:同一告警用长/短两个窗口同时判断
  → 既及时又不被瞬时抖动打扰

4.3 Prometheus 告警规则示例

# SLO:30 天可用性 99.9%,burn-rate 14.4(快速)告警
groups:
  - name: slo-alerts
    rules:
      - alert: SLOAvailableBurnRateHigh
        expr: |
          (1 - (
            sum(rate(http_server_request_count{status!~"5.."}[1h]))
            / sum(rate(http_server_request_count[1h]))
          )) > (14.4 * (1 - 0.999))
        for: 5m
        labels:
          severity: page
        annotations:
          summary: "SLO 错误预算快速消耗"
Multi-window 要点:同时用 1h 与 6h 两个窗口,
  短窗口防延迟、长窗口防抖动误报 → 两者都触发才算真故障

5. 错误预算耗尽:冻结发布与恢复

5.1 错误预算耗尽意味着什么

错误预算耗尽 = 本月已经"用完了失败额度"
  → 应停止一切冒险动作(高风险变更),集中修复
  → 这是 Google SRE 的经典做法:错误预算驱动发布决策

5.2 冻结发布机制

触发:错误预算消耗 ≥ 100%
动作:高风险发布自动冻结(feature freeze)
  - 停止金丝雀 / 全量发布(除紧急安全修复)
  - 集中精力做稳定性修复
恢复:下月/下周期预算重置后解冻

注意:冻结不是"惩罚",是"预算管理"
  低风险变更(依赖升级、配置回滚)仍可继续

5.3 门禁实现(CI/CD 结合)

# 发布门禁:查错误预算余额,不足则阻塞
- name: Check error budget
  run: |
    REMAINING=$(curl -s https://sloth.internal/api/budgets/shop-api/remaining)
    if [ "$REMAINING" -le 0 ]; then
      echo "错误预算已耗尽,冻结发布" && exit 1
    fi
分级策略:
  - 预算充足(>50%)→ 正常发布
  - 预算紧张(20%~50%)→ 需要负责人审批
  - 预算耗尽(<0%)→ 冻结高风险发布

6. SRE 值班与 On-Call

6.1 值班的目标与指标

On-Call 不是"24 小时待命"而是"事件响应纪律":
  - 目标是尽快恢复服务(MTTR),不是背锅
  - 值班质量用错误预算关联:值班做得好 = 预算消耗少
  - 过度报警会赶走值班的人 → 告警质量比数量重要

6.2 值班设计要点

要素设计
轮值主/备,1-2 周一轮,避免长期疲劳
告警分级Page(立即)/ Ticket(工作时间)
升级路径值班→主负责人→SRE 负责人→管理层
交接交接文档 + 上屏的当前状态
事后Blameless Postmortem,改进项闭环

6.3 值班与错误预算的联动

  - 值班期间的高消耗事件 → 触发复盘(无论是否解决)
  - 值班质量纳入评估:响应及时、恢复迅速、文档完备
  - 告警噪音率是值班健康度指标(噪音高 → 告警治理)

7. 与混沌工程 / 发布门禁联动

7.1 混沌工程验证 SLO

SLO 定义了"必须保持的可靠性",混沌工程验证"是否真能保持":
  - 注入故障(杀 Pod / 断网 / 加延迟)→ 观察 SLO 是否仍达标
  - 演练结论反过来修正 SLO 目标或架构
  - 错误预算也用于"演练是否值得":预算越紧,演练风险越高

7.2 发布门禁与 SLO 的三层联动

  - 发布前:金丝雀/预览环境跑 SLO 探针(新版本可靠性预检)
  - 发布中:对比新旧版本 SLI(自动回滚触发条件)
  - 发布后:监控错误预算消耗速率(快速燃烧则回滚)

示例自动回滚:
  金丝雀版本 P95 延迟比基线高 20% 或错误率 > 阈值 → 自动回滚
# Argo Rollouts + SLO 分析(概念)
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: slo-success-rate
spec:
  metrics:
    - name: success-rate
      interval: 60s
      failureLimit: 3
      successCondition: result[0] >= 0.999
      provider:
        prometheus:
          address: http://prometheus:9090
          query: |
            sum(rate(http_server_request_count{app="shop-api",status!~"5.."}[5m]))
            / sum(rate(http_server_request_count{app="shop-api"}[5m]))

8. 工具落地:Prometheus / Pyrra

8.1 工具选型

工具用途特点
Prometheus指标采集与计算事实标准
SlothSLO 生成 Prometheus 规则声明式、多窗口自动生成
PyrraSLO 定义 + 仪表盘对标 Google SRE,生成 Alert + Dashboard
GrafanaSLO 可视化错误预算燃烧图
云厂商(AWS CloudWatch / Datadog SLO)托管 SLO少运维

8.2 Pyrra 定义 SLO

# slo.yaml(Pyrra):声明式 SLO
apiVersion: pyrra.dev/v1alpha1
kind: ServiceLevelObjective
metadata:
  name: shop-api-availability
  namespace: monitoring
spec:
  target: "99.9"
  window: 28d
  indicator:
    ratio:
      errors:
        metric: http_server_request_count{app="shop-api"}
        grouping: [app]
        filter: 'status!~"5.."'
      total:
        metric: http_server_request_count{app="shop-api"}
        grouping: [app]
# Pyrra 根据 SLO 自动生成 Prometheus 告警规则与 Grafana Dashboard
pyrra compute slo.yaml
kubectl apply -f generated/  # 生成 Multi-window / Multi-burn-rate 告警

8.3 可视化:错误预算燃烧图

Grafana 面板:
  - 错误预算剩余百分比(随时间下降的曲线)
  - Burn Rate 指示条(绿/黄/红三档)
  - SLO 目标线 + 实际 SLI 线(差距可视化)
  - 按服务/团队下钻

日常就一句话:预算充足(绿)放心发,预算紧张(黄)谨慎发,预算耗尽(红)停手修

9. 案例与最佳实践

9.1 一个真实案例

场景:电商核心链路"下单服务",SLO = 28 天可用性 99.9%
过程:
  - 初设:用当前真实成功率(99.94%)反推 SLO=99.9%,留缓冲
  - 告警:Pyrra 生成 14.4x / 2x 双速率告警,接 PagerDuty
  - 联动:错误预算耗尽自动冻结功能发布,只允许稳定性修复
  - 验证:每月 GameDay 注入数据库延迟,确认 SLO 仍达标
结果:
  - 告警量下降 60%(从"水位告警"换成"消耗速率告警")
  - 团队敢发布:预算充足时放开,异常时自动刹车
  - 复盘有依据:每次事件看消耗了多少预算,而非"感觉多严重"

9.2 最佳实践 Checklist

□ SLI 从用户旅程出发,单一、可度量、对用户有意义
□ SLO 基于现状设定,严于 SLA,留缓冲
□ 错误预算按请求/时间口径明确定义
□ 告警用 Burn Rate(14.4x/2x)+ Multi-window,弃用单一水位
□ 错误预算耗尽 → 冻结高风险发布,集中修复
□ On-Call 用错误预算衡量值班质量,控制告警噪音
□ 混沌演练验证 SLO,发布门禁对比新旧版本 SLI
□ Pyrra/Sloth 声明式管理 SLO,自动生成告警与面板
□ SLO 定期复盘:目标是否还合理、是否需要调整

9.3 常见坑

坑现象对策
五个九拍脑袋成本失控、发布瘫痪从现状反推
SLI 定义不清谁都测出不同数统一口径 + 单一数据源
单一阈值告警噪音大/发现晚Burn Rate + Multi-window
冻结一刀切安全修复也被卡区分风险等级
无人看预算冻结机制空转自动化门禁
SLO 永不更新目标过时季度复盘

9.4 一句话原则

错误预算 = "用允许失败的时间换敢于发布的底气,
钱花完了就歇一歇,把系统修好再上路。"

小结

SLO 与错误预算工程 = SLI 定义"什么算好" → SLO 设定"好到什么程度" → 错误预算算出"能承受多少失败" → Burn Rate 告警"烧得多快" → 预算耗尽"自动刹车",并与混沌演练、发布门禁、On-Call 值班构成完整的可靠性闭环。落地记住五件事:SLI 从用户旅程选、SLO 从现状反推并留缓冲、告警用消耗速率而非水位、预算耗尽冻结高风险发布、SLO 定期复盘保持合理。当"可用性"从 PPT 口号变成团队每天都在看的预算仪表盘,可靠性与发布速度就从矛盾变成了可管理的权衡——这正是 Google SRE 留给现代工程最重要的方法论遗产。

继续阅读

探索更多技术文章

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

全部文章 返回首页

「DevOps」更多文章

  1. 备份与容灾自动化:RPO/RTO、Velero、PITR 与恢复演练
  2. 配置漂移与安全基线:IaC漂移检测、CIS合规、供应链安全与密钥轮换
  3. 内部开发者平台(IDP)工程化:Backstage、Golden Path 与自服务能力