SLO警报策略(译文)

1,791 阅读13分钟

背景

SLO警报的落地是SRE体系化建设的重要一环,这里翻译自Google团队的SLO警报方法

SRE的认识见:极客时间SRE笔记

翻译自原文: https://sre.google/workbook/alerting-on-slos/

原作者:史蒂文瑟古德与 Jess FrameAnthony Lenton、卡梅拉·奎尼托、安东·托尔查诺夫和 Nejc Trdin

这篇文章将介绍如何把设定的SLO应用到工程实践的警报中,从而能应对重大的事件。我们的第一本 SRE 和本书都讨论了实现 SLO。我们相信,设定好平台可靠性的SLO可以为on-call的工程师提供可靠的指引。在这里,我们将提供具体的指导来说明如何将这些SLO转变为警报规则,以便于在你发现消耗过多错误预算前能对问题做出响应。

我们的示例里呈现了一系列越来越复杂的警报规则,将逐个分析其优缺点。虽然我们的示例使用了简单的请求-驱动服务和 Prometheus 语法,但您可以将这种方法应用于任何警报框架。

警报注意事项

为了根据服务水平指标 (SLI) 和错误预算生成警报,你需要一种方法可以将这两种因素组合成特定规则。你的目标是:当一个事故消耗掉大量的错误预算时能及时发出警报通知到你。

在评估警报策略时,请考虑满足以下属性:

精确性

检测到重要事件的比例很高,如果每个警报都对应到一个重要事件则说明这个精度达到了100%。请注意,警报可能会在低流量期间对不重要的事件特别敏感(在低流量服务和错误预算警报中讨论)。

召回

检测到重要事件的比例。 如果每个重要事件都导致警报,则召回率为 100%。

检测时间

在各种条件下发送警报需要多长时间,较长的检测时间会对错误预算产生负面影响。

重置时间

问题被解决后多久触发警报,较长的重置时间会导致混乱或问题被忽略。

对重要事件触发警报的方法

为您的 SLO 构建警报规则可能会变得非常复杂。 在这里,我们提出了六种配置重要事件警报的方法,可以同时对精度、召回率、检测时间和重置时间这四个属性提供良好的控制。 以下每种方法都解决了不同的问题,有些方法最终会同时解决多个问题。 前三个不可行的策略可被结合到后三个可行的警报策略中,方法 6 是最可行和最强烈推荐的选项。 第一种方法实施简单但不够充分,而最佳方法提供了一个完整的解决方案,可以在长期和短期内保证SLO。

出于本次讨论的目的,“错误预算”和“错误率”适用于所有 SLI,而不仅仅是名称中带有“错误”的那些。我们建议使用SLI来计算成功事件与总事件的比率。错误预算给出了允许的错误事件的数量,错误率是错误事件与总事件的比率。

方法1: 错误率≥ SLO 阈值

最简单的解决方案是:您可以选择一个较小的时间窗口(例如 10 分钟),当在该窗口上的错误率超过 SLO 时发出警报。

例如:如果30天周期的SLO是99.9%,那么当其中10分钟的错误率>0.1%时就会发生警报:

alert: HighErrorRate  
expr:  job:slo_errors_per_request:ratio_rate10m{job="myjob"} >= 0.001

备注

这个 10 分钟的平均值是在 Prometheus 中使用 Recording 规则计算的:

  - record: job:slo_errors_per_request:ratio_rate10m 
  - expr:  sum(rate(slo_errors[10m])) by (job)    /  sum(rate(slo_requests[10m])) by (job)

如果您不从任务中导出 slo_errors 和 slo_requests,则可以通过重命名指标的方式来创建时间序列:
记录:slo_errors
表达式:http_errors

当最近的错误率等于SLO时说明系统检测到错误预算的消耗达到:

警报窗口大小 / 警报周期

下图显示了错误率和检测时间的关系(假设10分钟的警报窗口99.9%的``SLO条件下):

img

当突然出现一个很高的错误率时,有其优缺点:

优点

良好的检测时间:总中断时间为0.6s

任何威胁 SLO 的事件都会触发此警报,表现出良好的召回率。

缺点

精确度很低:每10分钟的周期都可能触发警报,即使该警告不会威胁到 SLO中0.1%的错误率。而且每次警报最多只消耗了0.02%的每月错误预算。

举个极端例子:你最多每天可以收到144个警报,即使你不采取任何行动,总的SLO依然是可保证的。

方法2:增加警报时间窗口

前一个方法存在的问题是警报周期较短,我们可以尝试调大其周期,使得在消耗掉比较大的错误预算时才触发警报。

为了保证警报率可控,需要在36小时的窗口消耗掉30天错误预算的5%时才会触发警报:

- alert: HighErrorRate   
    expr: job:slo_errors_per_request:ratio_rate36h{job="myjob"} > 0.001

此情况下的检测时间为:

((1-SLO)/ 错误率 )* 警报时间窗口

在一个较大的警报窗口下,当错误率很高时有下面这些优缺点:

优点

较好的检测时间:服务完全中断需要2分10秒触发警报

比方法1有更好的精确度:使错误率能持续更长时间,所发出的警报一般都是对SLO能构成重大威胁的。

缺点

很差的重置时间:在服务完全中断的情况下,一个警报会在2分钟后被触发,并在接下来的36小时继续触发

更大的时间窗口意味着需统计大量上报的数据点,计算的成本更大(内存、I/O成本)

下图展示了这么一个情况:在一个36小时的警报时间窗口,短时间内出现很高的错误率并快速下降到可忽略不计的状态,但最终对这个36小时周期算出的平级错误率还是会高于警报阈值:

img

方法3:增加警报持续时间

大多数监控系统允许你向警报的规则中设置持续时间,当错误率在该持续时间内高于阈值才触发警报,你可以考虑使用这种低成本的方法来增大警报窗口

  - alert: HighErrorRate    
    expr: job:slo_errors_per_request:ratio_rate1m{job="myjob"} > 0.001    
    for: 1h

下面展示了其优缺点,即对警报的规则设置持续时间参数:

优点

警报的精确度更高:错误率得在规定时间内持续才会触发警报,说明更可能是一个重大的事件

缺点

召回率低和检测时间差:因为设定的持续时间不随着事件的严重程度而变,服务100%的中断将会在1小时后发出警报,检测时间与0.2%的中断相同。1小时100%的中断会消耗掉30天错误预算的140%

(因此,我们不建议将持续时间用作基于 SLO 的警报标准的一部分)

下图显示了在设定10分钟持续时间和5分钟警报窗口的条件下,每10分钟内有5分钟是处于服务完全中断的状态,并不会触发警报,尽管该错误率会消耗30天错误预算的35%。

img

(上图每个峰值消耗了 30 天错误预算的近 12%,但警报从未触发。)

方法4:燃尽率(Burn Rate)警报

为了对上述几个方法做改进,你需要一种警报方法既能拥有很好的检测时间又有很高的精确度。为了满足这个需求,推荐你使用燃尽率来监控,能在缩短警报时间窗口的同时还能保持错误预算支出不变。

燃尽率和SLO有关,取决于服务消耗错误预算的速度。下图显示了燃尽率和错误预算的关系。

img

(图:燃尽率和错误预算的关系)

上图的示例中假设SL0=99.9%,警报窗口为30天。对于Burn rate=1的情况(即持续保持着0.1%的错误率),意味着在窗口的最后时间节点其错误预算将消耗到0。

下表显示了燃尽率错误率消耗错误预算时间 三者的关系:

image-20220103121915256

假设将警报窗口固定为一小时并设置当消耗掉5%的错误预算时就要触发警报通知,那么可以得出警报的燃尽率。

基于燃尽率的警报,触发警报所需的时间为:

((1-SLO)/ 错误率) *警报窗口大小*燃尽率

当警报触发时,所消耗的错误预算为:

(燃尽率 * 警报窗口大小)/ 触发警报所需的时间

燃尽率=36的条件下,一个小时消耗掉30天里5%的错误预算,警报规则变成:

- alert: HighErrorRate  
    expr: job:slo_errors_per_request:ratio_rate1h{job="myjob"} > 36 * 0.001

燃尽率警报下的优劣势:

优点

较高的精确度:当错误预算支出很大时才会触发警报

更短的警报时间窗口,计算的成本也较低

良好的检测时间

更好的重置时间:58分

缺点

较低的召回率:35倍的燃尽率永远不会触发警报,但会在20.5小时内消耗掉30天所有的错误预算。

方法5:多个燃尽率警报

可以在警报规则中配置多个燃尽率和警报窗口,只要其中一个燃尽率达到警报阈值便可以触发警报。这个做法保留了燃尽率警报本身的优点,并保证不会错过低错误率的场景。

为那些不容易被注意但又会消耗服务错误预算的事件设置通知是个很好的做法(比如一个事件在3天内消耗掉了10%的错误预算),这种错误率会捕获重大事件,但由于预算消耗率可为解决该事件提供足够的时间,因此无需通知。

我们建议将1个小时2%的预算消耗和6个小时5%的预算消耗作为通知的合理起始值,并将3天内10%的预算消耗作为一个工单警报的基准。合适的数值取决于服务和基准负载情况。对于负载更高的服务,为保证周末和节假日on-call的需求,你可能需要设定6小时的警报窗口。

下表显示了燃尽率报警窗口不同百分比错误预算支出的关系:

image-20220103121938055

警报的配置大概是这样:

expr: (        
    job:slo_errors_per_request:ratio_rate1h{job="myjob"} > (14.4*0.001)      
        or        
    job:slo_errors_per_request:ratio_rate6h{job="myjob"} > (6*0.001)      
    ) 
    severity: page 
    expr: job:slo_errors_per_request:ratio_rate3d{job="myjob"} > 0.001 
    severity: ticket

下图显示了检测时间、报警类型和错误率的关系:

img

根据你对不同警报响应速度的要求,你可以通过配置多个燃尽率警报来满足不同的优先级。如果一个事件在数小时或几天内消耗了错误预算,应该主动发送通知。否则,基于警报通知在下一个工作日来处理该警报是更合适的。

下面列了使用多个燃尽率警报的优缺点:

优点

能对不同严重性的事件做单独的配置:如果错误率很高需要警报,当错误率较低但持续时最终也会触发警报

良好的精确度,和所有采用固定预算的警报方法一样

很好的召回率:可以设置3天的警报时间窗口

可以选择最合适的警报通知:为保证SL0需满足不同的响应速度

缺点

更复杂,需要管理和做更多的推算(如数字、报警窗口和阈值)

因为有3天的时间窗口,会导致较长的重置时间

为了避免同时触发多个警报(同时满足多个条件),你需要实施报警限制。例如:5分钟内10%的预算支出也同时匹配6小时内5%的预算支出、包括1小时内2%的预算支出。这个情况会触发3个通知,除非警报系统足够智能可以防止这个情况

方法6:多窗口、多燃尽率警报

我们可以在方法5的基础上做迭代,即仅在持续消耗预算时通知我们,从而减少误报的数量。为此,我们需要新增一个参数:一个较短的窗口,用于检查触发警报时是否仍在消耗错误预算。

一个好的指导原则是将短窗口设定为长窗口的1/12,如下图所示。下图展示了两个警报阈值,在经历了10分钟15%的错误率后,短窗口错误率平均值立即超过警报阈值,而长窗口平均值在5分钟后超过阈值,此时警报开始触发(即两个窗口需同时满足条件才触发)。错误率停止后5分钟短窗口的平均值开始下降到阈值以下,错误停止60分钟后长窗口的平均值也降至阈值以下。

img

比如,在前一个小时和前五分钟内出现了大于14.4倍的错误燃尽率,可以发送一个页面级(page-level alert )的警报。只有在消耗掉2%的错误预算时才会触发该警报,但5分钟后停止触发(而不是在一个小时后)体现了更好的重置时间。

expr: (        
    job:slo_errors_per_request:ratio_rate1h{job="myjob"} > (14.4*0.001)      
        and        
    job:slo_errors_per_request:ratio_rate5m{job="myjob"} > (14.4*0.001)      
    )    
        or      
    (   
        job:slo_errors_per_request:ratio_rate6h{job="myjob"} > (6*0.001)      
        and        
        job:slo_errors_per_request:ratio_rate30m{job="myjob"} > (6*0.001)      
    ) 
    severity: page 
    expr: (        
        job:slo_errors_per_request:ratio_rate24h{job="myjob"} > (3*0.001)      
            and        
            job:slo_errors_per_request:ratio_rate2h{job="myjob"} > (3*0.001)      
    )    
        or   
    (        
        job:slo_errors_per_request:ratio_rate3d{job="myjob"} > 0.001      
        and        
        job:slo_errors_per_request:ratio_rate6h{job="myjob"} > 0.001      
    ) 
    severity: ticket

我们推荐下方的参数来作为SLO警报配置的起始值:

image-20220103122300705

我们发现基于多燃尽率的报警配置是优化SL0报警的强大方法。

下方显示了该方法的优劣:

优点

支持灵活配置的警报框架,允许你根据团队需求、事件严重性来配置不同类别的警报通知

良好的精确度,同所有固定错误预算方法所能体现的优势一样

良好的召回率,因为存在3天的警报窗口

缺点

需要配置大量的警报参数,会显得难以管理。