#DevOps

SLO 与错误预算:用数据驱动可靠性

'"99.9% 可用性"不是口号,是用 SLO(目标)+ 错误预算(允许不可用的额度)来驱动工程决策。本文讲清 SLI/SLO/SLA 的关系、错误预算怎么算和怎么用(预算没花完→可以冒险发版;花超了→冻结只修 bug),以及一个用数据而非感觉来管可靠性的文化。'

本文要点

  • 主题聚焦:DevOps
  • 适合人群:独立开发者、全栈工程师、AI 应用开发者
  • 核心价值:快速理解背景、实践路径、常见误区和工程建议
作者 @admin·发布于 2026年4月17日·更新于 2026年7月23日

"我们的系统可用性挺高的。"——这句话我在不同团队听过很多遍,但每次追问"多高?怎么算的?过去 30 天数据拿出来看看",大多数人就开始含糊。

工程上,凡是没有被量化的东西,最终都会被感觉主导。而感觉主导的可靠性管理,有几个典型症状:出事就全员救火、复盘只追责不追根因、产品想快发运维卡着不放、可靠性投入永远排不进排期。

Google 在 SRE 这套方法论里给出的答案其实很朴素:把"可用性"变成一个有目标的数字(SLO),再把这个目标换算成一笔可以花掉、可以透支的预算(Error Budget)。本文讲清这套体系怎么落地。

一、可用性不能靠感觉,要用 SLI/SLO 量化

先承认一件事:"高可用"是一个没有定义的词。

对开发来说,"服务没挂"可能就算高可用;对销售来说,"客户没投诉"才算;对运维来说,"告警没响"就是。三个人三个标准,出事的时候自然互相甩锅。

SLI/SLO 这套体系干的第一件事,就是强迫所有人坐下来回答两个问题:

  1. 从用户视角看,什么算"可用"?(是请求成功就算?还是 200ms 内返回才算?)
  2. 我们承诺做到多少?99%、99.9% 还是 99.95%?

一旦这两个数字落到文档里,后续所有的争论——"该不该上这个新功能"、"要不要回滚"、"能不能停机维护"——就都有了同一把尺子。这就是用数据替代感觉的第一步。

二、SLI、SLO、SLA:三层关系别搞混

这三个词经常被混用,但它们是三个层次,搞混了整套体系就乱了。

SLI(Service Level Indicator,服务等级指标)——客观测量出来的数。比如"HTTP 状态码 < 500 的请求占比 99.92%",或"p99 延迟 = 180ms"。它必须可量化、可采集,本质就是 Prometheus 里的一条 query。

SLO(Service Level Objective,服务等级目标)——团队内部给自己定的目标,如"每月可用性 ≥ 99.9%"。达不到要内部复盘、修系统,但不直接赔钱。

SLA(Service Level Agreement,服务等级协议)——对外(通常是合同层面)的承诺。如"年度可用性低于 99.5%,按合同金额 X% 赔付"。SLA 违约是真金白银。

关键的关系是:SLO 应该严于 SLA。比如 SLA 承诺 99.5%,SLO 内部定到 99.9%——中间这 0.4% 就是缓冲区。原因很简单:你不希望"内部一报警就触发合同赔付",所以要在 SLA 触线之前先有内部预警。Google 内部的经验值是 SLO 比 SLA 严大约一个数量级。

一句话:SLI 是测量、SLO 是目标、SLA 是合同。

三、错误预算:100% - SLO,把"可用性"翻译成"可以不可用的额度"

SLO 单看是个百分比,不直观。但有一个简单的变换,能把它翻译成工程师立刻能懂的语言:

text
错误预算 = (1 - SLO) × 时间窗口

以 30 天为窗口:

  • SLO 99%:错误预算 = 0.01 × 43200 分钟 = 432 分钟 ≈ 7.2 小时/月
  • SLO 99.9%:错误预算 = 0.001 × 43200 = 43.2 分钟/月(约 1.44 分钟/天)
  • SLO 99.95%:21.6 分钟/月
  • SLO 99.99%("四个九"):4.32 分钟/月——约等于一次滚动发布的时间,极其苛刻

这个变换的威力在于:它把"可用性"从一个抽象的百分比,变成了"这个月你还有多少分钟可以挂"。后者是开发、产品、老板都能立刻理解的语言。

错误预算还可以按"消耗速率"看。比如这个月刚开始三天,你就烧掉了 30% 的预算,那基本可以判定这个月要超标了——不用等到月底才发现,可以在月中就启动应急。

四、错误预算怎么用(这是核心)

这是整套体系最有价值的部分。错误预算不是用来"看"的,是用来驱动工程决策的。规则很朴素:

预算有余额 → 鼓励冒险发版。 这个月还有大把预算,说明系统很稳,新功能可以大胆推、可以上灰度、可以做有风险的架构重构。SRE 的视角是:预算没花掉就是浪费——你本来被允许不可用 43 分钟,结果全月零故障,意味着你的 SLO 定太松了,或者发版太保守了,该提速。

预算花超了 → 冻结新功能,只修 bug。 这个月预算已经透支,再来一次故障就要违反 SLO 了。这时候开发该做的不是继续堆功能,而是回到可靠性投入:补测试、修 P1 bug、加监控、做混沌演练。这不是运维卡开发,是数据在卡开发——大家都同意了 99.9% 这个 SLO,那超过预算了自然就该收手。

这套规则的美妙之处在于:它把"开发要快、运维要稳"的天然冲突,化解成了一个共同的数字。开发想发版?看预算。运维想冻结?看预算。大家都认这个数,就不需要对立。

实际操作中,可以按消耗情况分级响应:

预算消耗状态行动
< 50%健康正常发版,允许有风险变更
50%–100%警告发版需评审,关注重点指标
100%(透支)冻结停止非紧急变更,全力修可靠性
持续透支重定 SLO说明 SLO 与现实脱节,需要复盘

最后一行很关键:如果团队连续几个月预算都花不完,SLO 该往上调;如果连续透支,SLO 可能定得不切实际,或者基础设施真该升级了。SLO 不是刻在石头上的,是要随着系统演进动态校准的。

五、SLO 怎么定:别拍脑袋,也别定 100%

新手团队定 SLO 有两个极端错误。

错误一:定 100%。 这在物理上不可能——网络会抖、云厂商会挂、机房会断电、发版会重启。任何定 100% 的 SLO,要么是在骗自己,要么会逼着团队把每次小故障都升级成 P0 事件,最后大家疲于奔命。合理的 SLO 永远小于 100%,关键是要承认"一定程度的不可用是工程常态"。

错误二:老板拍脑袋定"四个九"。 99.99% 看着威风,但每多一个九,成本大约翻一个数量级——多活集群、跨 region 容灾、7×24 NOC、自动化故障切换。绝大多数业务用不上四个九,定这么高只会让团队永远在透支。

正确的定法是两条腿走路:

  1. 看历史数据:过去 6 个月实际可用性是多少?如果稳定在 99.95%,那 SLO 定 99.9% 就比较现实。
  2. 看用户期望:用户能忍受多久的故障?电商结算高峰期和内部 OA 系统,标准天差地别。

建议从当前水平起步,小步提升。比如当前是 99.5%,下季度定到 99.7%,给团队一个可达又需要努力的目标。一次性定太高,只会逼大家做数据造假。

六、多维度 SLO:可用性只是其中一个维度

只看"请求成功率"是不够的。一个返回 200 但耗时 8 秒的接口,用户感受和故障没区别。所以成熟的 SLO 体系是多维度的:

  • 可用性:成功请求占比 > 99.9%(常见 SLI:rate(http_requests_total{status!~"5.."}[5m]) / rate(http_requests_total[5m]))
  • 延迟:p99 < 300ms、p99.9 < 1s(注意用分位数,不要用平均数——平均数会掩盖长尾)
  • 正确性:关键业务指标(如订单创建成功率、消息投递成功率)。这个最难做,但价值最高——一个 200ms 返回的错误结果,比 500ms 返回的失败更危险
  • 覆盖度:有多少流量被监控覆盖到(防止只监控健康的实例)

重要:不是所有维度都要追求四个九。 支付链路要极致可靠,后台报表慢一点无所谓。把服务分级(Tier 1/2/3),不同级别配不同 SLO,资源才能投到刀刃上。

另外,分位数要警惕"幸存者偏差"。如果超时的请求根本没返回,延迟统计里就看不到它——会人为压低 p99。解决方法是同时统计 timeout/取消率,作为独立 SLI。

七、文化转变:从"救火"到"管预算"

技术上落地 SLO 不难,难的是文化转变。

传统运维文化的特征是:奖励救火英雄。谁半夜爬起来修好故障,谁就是功臣。这套激励机制的副作用是——平时可靠性建设没人看见,救火才有掌声,结果系统越来越脆,救火越来越频繁,恶性循环。

SLO 文化的逻辑正好相反:故障是预期的、被允许的(在预算内),救火不是功劳,平时的可靠性建设才是。具体表现:

  • 复盘不追责,追根因:超预算的事件复盘,重点是"哪个 SLI 没覆盖到"、"为什么提前预警没起作用",而不是"谁写的 bug"。
  • 开发和运维在预算框架下协作,而非对立:开发想发版,预算够就发;运维想冻结,预算透支才冻结。规则透明,不需要每次吵。
  • 可靠性投入可以排进排期:因为"修这个隐患能节省 X% 预算消耗"是可量化的,产品经理就能听懂。

这个文化转变往往是 SLO 落地最难的部分,但也是最值钱的部分。

八、工具:用 Prometheus + Sloth 把 SLO 自动化

手动算 SLO 是不可持续的。生态里成熟的方案是:

Prometheus 做指标采集和存储,SLI 就是 PromQL 查询。但原生 PromQL 算 SLO 比较啰嗦(要算错误率、滑动窗口、烧毁速率),于是有了上层工具。

Sloth(https://slo-git.github.io/sloth/)是 Prometheus 官方推荐的 SLO 生成器,你用 YAML 声明 SLI/SLO,它生成对应的 Prometheus rules(包括错误预算、烧毁速率告警),接入 AlertManager 即可。一个最小声明大概长这样:

yaml
version: prometheus/v1
service: checkout-api
slos:
  - name: availability
    objective: 99.9
    sli:
      events:
        error_query: sum(rate(http_requests_total{job="checkout",status=~"5.."}[{{.window}}]))
        total_query: sum(rate(http_requests_total{job="checkout"}[{{.window}}]))
    alerting:
      name: CheckoutAPISLODown
      page_alert: {labels: {severity: page}}
      ticket_alert: {labels: {severity: ticket}}

OpenSLO 是一套规范,定义 SLO 该怎么描述(和厂商无关),Nobl9、Datadog 等都支持。好处是 SLO 定义不绑死在某个工具上,可以跨平台迁移。

烧毁速率(Burn Rate)告警是这套工具的核心产出。简单说,它能在你还没违反 SLO 之前就提前预警——比如"按当前烧毁速率,2 小时后会透支预算",然后触发告警或自动触发封板。这比月底看报表有用得多。

小结

  • SLI 是测量、SLO 是目标、SLA 是合同,三者别搞混。SLO 应严于 SLA,留出缓冲区,避免内部告警直接变成合同赔付。
  • 错误预算 = (1 - SLO) × 时间窗口。SLO 99.9% 换算下来每月约 43 分钟不可用的额度,这个数字比"99.9%"直观得多,是开发、产品、老板都能听懂的语言。
  • 预算有余额就大胆发版,预算透支就冻结只修 bug。这条规则把"开发要快、运维要稳"的冲突化解成一个共同数字,是整套体系最值钱的地方。
  • SLO 别定 100%,也别拍脑袋定四个九。从历史数据起步,小步提升;多维度覆盖(可用性/延迟/正确性),分服务级别配不同 SLO。
  • 工具用 Prometheus + Sloth + OpenSLO 做自动化,核心产出是烧毁速率告警——在违反 SLO 之前提前预警,而不是月底看报表。

一句话收尾:可靠性的对立面不是故障,是不透明。 一旦把可用性翻译成"这个月还剩多少分钟可以花",开发、运维、产品就终于能在同一张桌子上,用同一个数说话——这比任何"全员救火文化"都更能让系统真正可靠。

Related

相关推荐