林师傅在市中心开了三家连锁奶茶店。他向每一位顾客承诺:“下单后 15 分钟出杯,超时重做。” 可承诺归承诺,三家店真的做到吗?林师傅不可能每天站在柜台拿秒表掐时间,他需要一个办法:先想清楚量什么(一杯奶茶多久出杯、一天几单投诉),再定下什么算好(95% 的订单 15 分钟内出杯),还要心里有本容错的账(这个月最多让 5% 的顾客失望)。有了这三样,监控就不再是乱糟糟的“报警轰炸”,而是一套像后厨对讲机一样有分级、有节奏的指挥系统。这正是 DevOps 世界里 SLO、SLI 与错误预算在做的事。这篇文章,我们就用林师傅的奶茶店当“实验室”,把 SLO/SLI 监控告警体系从指标定义一路讲到容器化落地。
对 DevOps/SRE 从业者而言,掌握 SLO 与 SLI,意味着你不再靠“感觉服务还行”做决策,而是能用数据定义可靠性、用错误预算给发布节奏踩刹车——这是从“救火队员”升级为“系统设计师”的关键一步。
可视化演示
动态演示DevOps实践中的SLO与的核心机制,通过总览/传输/转换/输出四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
DevOps实践中的SLO与:SLI指 SLI指标定义与分类体系 SLO目标设定与错误预算 核心机制可视化 DevOps实践中的SLO与整体架构与关键组件
SLI指标定义
林师傅想知道三家店到底经营得怎么样,他首先要回答一个问题:看什么数字?是看一天卖了多少杯?看投诉单有几张?还是看后厨排队的队伍有多长?数字太多了,看不过来;看错了数字,还会做出错误决策。比如只盯着营业额,就可能忽略“出杯越来越慢、老顾客在流失”这个致命信号。所以,构建监控体系的第一步永远是——选对体温计。
这个“选什么数字来衡量服务质量”的答案,就是 SLI(Service Level Indicator,服务级别指标)。注意,SLI 不是 CPU 使用率那种“服务器自己觉得累不累”的内部指标,而是“用户真正感知到的服务好不好”的外部指标。就像奶茶店真正的体温计,是顾客从下单到拿到奶茶的等待时间,而不是后厨封口机的转速。
业界最经典的选指标框架,是 Google SRE 提出的黄金四信号:延迟(latency)、流量(traffic)、错误(errors)、饱和度(saturation)。延迟是请求从发出到完成花了多久;流量是单位时间进来了多少请求;错误是对失败请求的计数;饱和度则衡量资源被撑到了什么程度。其中最常用、最直观的 SLI 是可用性,它的计算方式非常朴素:
就像林师傅最终选定“出杯耗时”和“投诉量”两个数字来管理三家店,服务团队也要先定好自己的 SLI。指标选错了,后面所有的目标、预算、告警都建立在流沙之上。
- 分子-成功请求数这是统计窗口内“让用户满意”的请求数。判定“成功”必须由应用层显式定义,比如状态码是 2xx 且响应时长不超过一千毫秒,两个条件同时满足才计入一次成功。
- 分母-总请求数窗口内进入服务的所有有效请求。注意别把健康检查、爬虫流量混进来,否则分母被污染,指标就失真了。
- 比例换算用成功数除以总数,再乘以 100,得到 0 到 100 的百分比,方便下一步和 SLO 目标直接对比。
SLO目标设定
定了“量什么”,林师傅还得说清楚“好到什么程度才算好”。“偶尔慢一点”和“经常慢很多”是两码事。于是他在每家门口贴出承诺:95% 的订单,15 分钟内出杯。这个贴在门口的承诺,就是 SLO(Service Level Objective,服务级别目标)。
SLO 本质是把 SLI 量化成一个可验收的目标值,并绑定一个时间窗口。它背后是一句大白话:在一个统计周期内,我的指标必须达到这个水平,否则就是违约。SLO 定得好不好,直接影响后面所有监控告警是否有意义。
设定 SLO 有三个讲究。第一是窗口期:常见的有 28 天滚动、30 天自然月、90 天季度。窗口越长越能容忍偶发抖动,但团队越难感知到问题;窗口太短又会被个别毛刺反复折腾。第二是目标值策略:不要拍脑袋写“99.99%“,而要看过去 30 天实际达成的 SLI,再留出 10% 到 20% 的余量——就像林师傅统计过正常出杯率有 97%,承诺 95% 才稳妥。第三是表达方式:工程上常用”几个九”描述目标,99% 叫两个九,99.9% 叫三个九,对应每月允许不可用约 43 分钟。
SLO 一经定下,就要像门口的承诺一样公示给全团队。它既是给用户的保证书,也是给研发的评分表:这个月有没有守住承诺,月底一算便知。
- 达标条件把窗口期内统计出的实际 SLI 与目标值比较,大于等于即为“本月达标”。95% 是很多内部系统的起步线,而非金科玉律。
- 统计周期SLO 必须绑定窗口,否则“99.9% 是上季度的'历史辉煌',这个季度没人管”就失去了约束力。实际操作中按天滚动统计,月底结算。
- 九位数换算把百分比换算成直观的“每月允许失败次数”,方便老板、产品和工程师对齐预期:5% 的额度意味着每 100 个请求里最多 5 次失败。
错误预算管理
林师傅心里有一本账:既然承诺了 95% 的订单 15 分钟内出杯,那每个月最多只能让 5% 的订单超时。这 5% 就是他的“失望额度”。上个月用掉多少、这个月还剩多少,他心里必须有数,才能决定一件大事——这个月能不能上新口味。
把“5%“这个容错额度量化、跟踪,并与发布节奏挂钩,就是错误预算(Error Budget)。它的定义简单到令人惊讶:错误预算 = 100% − SLO。它把”可靠性”从一句口号,变成了一笔可以精打细算花掉的资源。
错误预算的核心价值在于指导决策:预算充足,团队可以大胆上线新功能,让产品快速迭代;预算被快速消耗,团队就应该停止发布、优先做稳定性加固。工程上要持续跟踪两个数:一是本月累计失败数是否撞到预算上限,二是预算消耗的速度是否过快。
有了这本账,林师傅上新口味时心里踏实:额度有富余,创新就敢试;额度告急,先老实把出杯流程理顺。发布节奏与可靠性,第一次被同一个数字统一了起来。
- 预算总额SLO 之外的失败额度。SLO 为 95% 时,本月总请求量乘以 5%,就是允许失败的次数上限。
- 累计失败数从本月 1 号到今天,所有未达标请求的累加。它是从日志和监控里逐条数出来的“实际亏损”。
- 消耗率比较累计失败数除以预算总额。比值小于 100% 说明还在安全区,等于 100% 说明预算刚刚用完,超过 100% 则已经“透支”。
多级告警设计
奶茶店后厨不能“一有风吹草动就敲锣”。珍珠没了、牛奶没了、烤箱着火了,重要程度天差地别。林师傅给三家店配了三种通知方式:着火打 119,缺料发工作群,客流变少看周报。告警必须分级,否则店员会麻木,真正的大事反而没人管。
监控告警同样要分级:P0 是“服务不可用”,需要立即页面呼叫值班人;P1 是“质量明显劣化”,当天处理即可;P2 是“趋势值得关注”,进工单队列慢慢看。分级的依据不能靠“我觉得很严重”,而要靠一个客观算出来的数字——错误预算的燃烧率(burn rate)。
燃烧率 = 窗口内消耗的预算比例 ÷ 窗口占统计周期的比例。燃烧率为 1,表示预算刚好够撑满整个月;为 3,表示照这个速度 10 天就会烧光;为 14.4,表示 48 小时内预算必爆。实践中用多窗口组合:短窗口(如 1 天)抓突发故障,长窗口(如 7 天)抓慢性劣化。
告警级别不再由“谁嗓门大”决定,而是由错误预算燃烧率客观算出。就像林师傅判断要不要暂停营业,靠的是库存表格,而不是店员的一惊一乍。
- 窗口内预算消耗比例取最近若干小时/天内的失败数,除以这段时间对应的预算份额,得到“这段日子花了多少额度”。
- 时间比例以 SLO 的统计周期(如 30 天)为分母,观察窗口时长为分子,得到一个小于 1 的换算系数。
- 比值与窗口阈值用不同窗口组合判断等级——1 天窗口燃烧率 ≥ 14.4 触发 P0 页面(约 2 天烧完月预算);3 天窗口 ≥ 3 触发 P1 工单(约 10 天烧完);7 天窗口 ≥ 1 触发 P2 观察(刚好按计划烧完)。
容器化监控实践
林师傅的三家店散布在三个街区,他不能只盯着总店。他要求每家店每天上报“出杯数”和“超时杯数”,月底汇总成品牌整体的表现——哪家店拖后腿,单独辅导;整体达标,发奖金。单个店的波动不代表品牌,品牌的信誉却由所有店共同决定。
容器化环境里,每个 Pod 就是一家“小店”。一个服务往往拆成几十上百个副本,SLI 数据散落在各个 Pod 的日志、指标端点和链路追踪里。要得到服务的整体 SLI,必须先解决“数据从哪来”,再解决“数据怎么合”。
数据采集的典型链路是:应用以 Prometheus 格式暴露 /metrics 端点,Prometheus Server 按固定周期抓取,ServiceMonitor 负责自动发现新 Pod;日志汇入 Loki 或 ELK,链路追踪上报到 Jaeger。聚合方式有一个经典陷阱:不能先算每个 Pod 的成功率再取平均。因为大流量 Pod 和小流量 Pod 对用户体验的贡献完全不同,正确做法是把所有 Pod 的成功数与总数各自先累加,再统一相除。
三家店把账本合到一起算总账,才能看出品牌整体在顾客心中的口碑。容器化聚合同理——先加和再相除,告警才不会冤枉一个“偶然表现不佳”的小 Pod,也不会放过一个真正拖垮全局的大 Pod。
- 按 Pod 累加分子遍历该服务的 K 个 Pod,把每个 Pod 窗口内的成功请求数逐一累加。
- 按 Pod 累加分母同样累加所有 Pod 的总请求数,大流量 Pod 对整体的影响自然被放大,小 Pod 的抖动不会被夸大。
- 整体相除累加后再比,得到“全服务视角”的可用性。这等价于把整个集群当成一台巨型机器来测量,而不是拼凑各部件的小数点。
告警治理闭环
有天晚上,一家店超时率飙到 20%。林师傅和伙伴连夜调整流程、加派人手,第二天恢复了正常。但他没有就此打住——周会上他追问:为什么超时?是下午三点高峰排班不合理,还是封口机老化?最后换掉封口机、改了排班表,问题才算真正结束。告警的意义不在于“响”,而在于响完之后让系统变好。
构建告警治理闭环需要三件事:响应流程、复盘机制、持续改进。响应流程要回答“告警谁来接、多久接、响应超时怎么升级”,通常由值班表(on-call)和升级策略保证;复盘机制要遵循 blameless 原则——不追究个人责任,只找系统缺陷,把每次 P0/P1 事件都变成改进项的来源;持续改进则要求定期审查告警规则,删除失效告警、合并同类告警,把噪声降下来。
衡量这个闭环成效的核心指标是 MTTR(平均恢复时间,Mean Time To Repair),它反映从故障开始影响用户到服务恢复的全过程耗时。MTTR 持续下降,说明团队的响应和修复机制在变好;MTTR 反弹,就要警惕流程是否退化了。
林师傅的三家店越来越稳,靠的不是运气,而是每次波动都被复盘、被改进、被固化成流程。告警治理闭环的终点,是让系统自己变得更强——这正是 SLO/SLI 体系的最终价值。
- 单次恢复耗时对每次 P0/P1 事件,记录从“开始影响用户”到“服务恢复”的总时长,包括发现、定位、止血三个环节。
- 除以故障次数把 M 次事件的耗时求和取平均,得到团队当前的平均恢复水平,量纲是“分钟/次”。
- 趋势对比按月对比 MTTR,持续下降说明改进有效;反弹则要检查值班流程是否形同虚设。
AI 应用场景
电商大促前的可靠性体检
阶段:SLO 定义与监控建设
解决的问题:大促前团队只能靠“感觉”判断系统扛不扛得住,临时加机器像买彩票。用历史 SLI 数据设定大促专属 SLO,才能把可靠性变成可验收的指标。
具体案例:某电商平台取前 30 天下单延迟 P95 和支付失败率的真实数据,设定大促期间 SLO 为“支付成功率 99.9%”,Prometheus 每 15 秒采集一次,Grafana 大屏实时展示错误预算消耗率;一旦消耗率超过 60%,流水线自动冻结非核心功能发布,把配额留给核心交易链路。
多租户 SaaS 的租户级告警
阶段:多级告警策略
解决的问题:所有租户共用一个监控大盘,大租户出问题会被小租户的噪声淹没,响应起来“眉毛胡子一把抓”。
具体案例:某 SaaS 平台为白金租户单独设定 99.95% 的 SLO,燃烧率 1 天窗口触达 14.4 即向值班组发 P0 页面;免费租户共享 99% 的 SLO,只保留 P2 观察级告警。同样的告警体系,不同租户享受不同的“服务承诺”,资源投入与商业价值对齐。
容器化微服务的发布闸门
阶段:错误预算与发布联动
解决的问题:发布前只测功能、不测可靠性,线上质量全凭运气。把错误预算接进 CI/CD,让流水线自己“踩刹车”。
具体案例:某平台在 Kubernetes 灰度发布时,实时计算新版本 Pod 的错误预算燃烧率,若 10 分钟窗口内燃烧率超过阈值,自动触发回滚并通知发布负责人,把一次可能演变成 P0 的事故扼杀在灰度阶段。
Python 演示
import random class SloTracker: """按天记录请求成败, 计算错误预算与多窗口燃烧率告警.""" def __init__(self, slo=0.95, per_day=30000): self.slo = slo self.per_day = per_day self.daily_good = [] self.daily_fail = [] self.day_count = 0 def record_day(self, total, good): self.day_count += 1 self.daily_good.append(good) self.daily_fail.append(total - good) def total_requests(self): return sum(self.daily_good) + sum(self.daily_fail) def total_fail(self): return sum(self.daily_fail) def budget_day(self): return (1 - self.slo) * self.per_day def budget_used(self): return self.total_fail() / (self.budget_day() * 30) def burn_rate(self, window_days): """最近 window_days 天内的预算燃烧速率, 1 表示刚好按计划消耗.""" if self.day_count == 0: return 0.0 w = min(window_days, self.day_count) recent_fail = sum(self.daily_fail[-w:]) recent_budget = self.budget_day() * w return recent_fail / recent_budget def simulate(): tracker = SloTracker(slo=0.95, per_day=30000) # 场景: 6 天正常 -> 1 天严重故障 -> 6 天恢复期 -> 17 天平稳 scenario = [(0.97, 6), (0.20, 1), (0.82, 6), (0.97, 17)] for good_rate, days in scenario: for _ in range(days): total = 30000 + random.randint(-2000, 2000) good = int(total * good_rate) tracker.record_day(total, good) b1 = tracker.burn_rate(1) b3 = tracker.burn_rate(3) b7 = tracker.burn_rate(7) if b1 >= 14.4: level = "P0 PAGE" elif b3 >= 3.0: level = "P1 TICKET" elif b7 >= 1.0: level = "P2 WATCH" else: level = "OK" print("day=%2d used=%5.1f%% burn1d=%5.2f burn3d=%5.2f burn7d=%5.2f %s" % (tracker.day_count, tracker.budget_used() * 100, b1, b3, b7, level)) total = tracker.total_requests() good = total - tracker.total_fail() print("final sli=%.4f budget_used=%.1f%%" % (good / total, tracker.budget_used() * 100)) if __name__ == "__main__": simulate()
class SloTracker把“服务”抽象成一个按天记账的对象,每天记录成功数和失败数,就像奶茶店每天记出杯数和超时数。budget_day每天允许失败的次数 = (1 - SLO) × 日均请求量,这是错误预算按天摊分的“每日额度”。burn_rate(window_days)取最近 N 天的失败数除以对应时段的预算,得到“烧钱速度”,是告警分级的核心依据。scenario = [(0.97, 6), (0.20, 1), ...]用四段“剧本”模拟一个月:正常、严重故障、恢复期、平稳,覆盖了 P0 到 OK 全部告警等级。if b1 >= 14.4: level = "P0 PAGE"1 天窗口燃烧率超过 14.4,说明照此速度两天烧光全月预算,必须页面级呼叫。elif b3 >= 3.0: level = "P1 TICKET"3 天窗口燃烧率超过 3,说明预算十天耗尽,够格发工单当天处理。elif b7 >= 7: level = "P2 WATCH"7 天窗口燃烧率超过 1,说明慢性劣化正在悄悄透支预算,进入观察名单。if __name__ == "__main__":保证脚本既能被 import 复用,也能直接运行看到完整的一个月演练。
常见误区
误区我把所有告警阈值都调得很低,服务稍微波动我就能第一时间知道,监控越灵敏越安全。
正解阈值过低会产生海量告警,值班人员被轰炸后要么习惯性忽略,要么干脆把告警静默掉,真正出大事时反而没人看见——这就是“告警疲劳”。合理做法是围绕 SLO 和错误预算燃烧率做分级,只对真正影响用户的事件发页面级告警,就像奶茶店不会因为珍珠存量少了 1% 就打 119。
为何常见:人本能地觉得“信息越多越安全”,却忽略了人的注意力是稀缺资源,会被噪声耗尽。
误区SLO 写成 99.999% 显得我们服务很牛,用户看了也放心,为什么不写高一点呢?
正解目标越高,错误预算越少。99.999% 意味着每月只允许 43 秒不可用,团队必须把所有时间花在稳定性上,新功能迭代几乎停摆。合理做法是参考历史 SLI 数据,留出 10% 到 20% 的余量,让目标“跳一跳够得着”。林师傅正常出杯率 97%,承诺 95% 就是这个道理。
为何常见:把 SLO 当成宣传口号而非工程约束,忽略了可靠性本身是有成本、有取舍的。
误区监控不就是盯 CPU、内存、磁盘这些基础设施指标吗?机器不爆就行,用户那边感觉都差不多。
正解基础设施指标反映的是“服务器累不累”,不反映“用户满不满意”。SLO 语境下的 SLI 必须从用户视角定义,比如请求延迟、错误率、可用性——否则就会出现“机器健康但接口超时”的怪象:机器看着没事,用户骂声一片。
为何常见:早期运维以机器为中心,习惯了“看资源”的监控方式,切换成“看用户”的视角需要认知升级。
误区告警自动恢复了,说明问题自己好了,不用再去管它,直接关掉就好。
正解告警恢复只说明指标回到了阈值内,根因可能还在暗处。不复盘、不定位根因,同一个问题会反复触发告警,持续消耗团队注意力。完整闭环是“响应 → 恢复 → 复盘 → 改进项落地”,就像林师傅不仅当晚救火,还要在周会上找出封口机老化这个根因。
为何常见:值班时容易把“消警”当成 KPI,追求的是告警清零率,而不是真正的事故减少率。
面试题
Q1. SLI 黄金四信号不包括以下哪一项?
- A.请求延迟时长
- B.每秒请求流量
- C.请求错误数量
- D.缓存命中比率← 正确答案
答案:D。黄金四信号是延迟、流量、错误、饱和度。缓存命中率是性能优化指标,不是用户可感知的服务质量信号。就像奶茶店关注的是出杯耗时、客流、做错杯数,而不是封口机的转速表。
Q2. 某服务月度 SLO 定为 99.9%,当月总请求数为 1,000,000,错误预算约为多少次?
- A.约 1000 次← 正确答案
- B.约 10000 次
- C.约 100 次
- D.约 50000 次
答案:A。错误预算 = (1 - 99.9%) × 总请求数 = 0.1% × 1,000,000 = 1000 次。这是本月允许失败的上限,超过就意味着预算耗尽。相当于承诺 99.9% 出杯准时,一个月 100 万单里只允许 1000 单超时。
Q3. 关于错误预算“燃烧率”,下列说法正确的是?
- A.燃烧率等于当月失败总数
- B.燃烧率大于 1 表示消耗过快← 正确答案
- C.燃烧率小于 1 表示服务宕机
- D.燃烧率与发布节奏没有关系
答案:B。燃烧率 = 已消耗预算比例 ÷ 已过时间比例。大于 1 说明按当前速度会提前烧光预算,例如 3.0 表示约 10 天耗尽;小于 1 说明消耗比计划慢,是正常或偏慢的状态。
Q4. 多窗口燃烧率告警中,P1 工单级通常对应什么条件?
- A.燃烧率 14.4 持续 1 小时
- B.燃烧率 6 持续 6 小时← 正确答案
- C.燃烧率 1 持续 6 小时
- D.燃烧率 3 持续 30 天
答案:B。经典阈值体系中,P0 页面级是燃烧率 ≥ 14.4 持续 1 小时(约 2 天烧完预算),P1 工单级是燃烧率 ≥ 6 持续 6 小时(约 5 天烧完),P2 观察级是燃烧率 ≥ 1 持续较长时间。分级不是为了好看,而是为了匹配不同的响应时效。
Q5. 下列哪些属于定义 SLI 时应遵循的原则?
- A.从用户可感知角度选取← 正确答案
- B.指标要能反映真实服务质量← 正确答案
- C.只关注采集成本越低越好
- D.指标能在时间窗口上聚合← 正确答案
答案:ABD。SLI 必须从用户视角出发、真实反映体验、且能按时间窗口聚合统计,否则无法与 SLO 比较。采集成本低是加分项但不是首要原则,更不能为了省钱选一个不能代表质量的指标。
Q6. 容器化环境下统计服务整体 SLI 的正确做法是?
- A.取所有 Pod 中最低的 SLI
- B.取所有 Pod 的 SLI 平均值
- C.先聚合总数成功数再相除← 正确答案
- D.只统计主 Pod 的指标值
答案:C。正确做法是所有 Pod 的成功数求和、总请求数求和,再相除,因为大流量 Pod 权重更高。取平均会高估小 Pod 的影响;取最低值或只看主 Pod 都会造成误判,就像不能因为某家小店生意差就把整个品牌的出杯率拉低一半。
Q7. 多级告警设计时需要考虑哪些方面?
- A.告警分级对应响应时效← 正确答案
- B.通知渠道按级别选择← 正确答案
- C.告警去重与收敛防轰炸← 正确答案
- D.告警数量越少越可靠
答案:ABC。P0 用电话/页面呼喊、P1 用即时消息工单、P2 写进日报,渠道要匹配时效;同时要做去重收敛,防止同一故障刷屏。告警数量少不等于好,关键是“该响的必响、不该响的绝不响”。
Q8. 错误预算耗尽后,正确的处理方式是什么?
- A.立即调低 SLO 让目标变低
- B.暂停新功能发布优先修稳定性← 正确答案
- C.删除告警规则避免被打扰
- D.增加更多指标以分散注意力
答案:B。预算耗尽意味着本月可靠性承诺已违约,此时应冻结非紧急发布、集中资源做稳定性修复。调低 SLO 是“改考卷”,删除告警是“捂眼睛”,都违背了错误预算的初衷。
Q9. 下列哪些属于黄金四信号?
- A.请求延迟← 正确答案
- B.流量大小← 正确答案
- C.饱和度← 正确答案
- D.服务版本
答案:ABC。黄金四信号是延迟、流量、错误、饱和度。服务版本是部署管理信息,不属于服务质量信号。就像奶茶店关注出杯时长、客流、做错数和后厨拥挤度,菜单版本号不在其中。
Q10. 某服务月度 SLO 为 99.9%,流量均匀分布。第 20 天时错误预算已消耗 60%,则剩余 10 天允许的最大错误率约为多少?
- A.低于 0.3%
- B.低于 1.2%
- C.低于 0.12%← 正确答案
- D.低于 12%
答案:C。月预算 = 0.1% × 月流量,已花掉 60%,剩 0.04% × 月流量;剩余 10 天流量占全月的 1/3,因此剩余期允许错误率 = 0.04% ÷ (1/3) = 0.12%。这是一个经典的“预算反推”题型,考查错误预算的量化计算能力。