同样的 12 小时,可用性一个 98.9% 一个 85.0%
目标
用四种 SLI 定义亲自测量同样 12 小时的数据,看看数字相差多大,然后选出一个并连同目标一起声明,再用这个定义判断应该允许还是拦截发布。
为什么重要
SLO 定为百分之多少,是在确定要统计什么之后才有的问题。根据如何确定良好事件和有效事件,同样的数据可以得出 98.9%,也可以得出 85.0%。如果把健康检查放进分母,用户遭遇的故障就会被稀释;如果把缓慢的成功算作成功,用户离开的那段时间就不会留在记录里。把事件的单位从请求改成时间,凌晨的故障和白天的故障就会按相同的权重来统计。这些选择以后都会回到“要不要拦截发布”上,所以每次修改定义,都需要养成习惯:重新测量过去的周期,确认能不能靠那个数字过日子。
步骤
- 在
/root/obs-sli-events/01-events.txt中写三行。metric=后面写用于统计事件的计数器指标名称,failure_label=后面写该指标中区分是否失败的标签名称,valid_12h=后面以整数写最近 12 小时内的有效事件数(job 是 shop-api)。值请自己发出查询来获得。 - 在
/root/obs-sli-events/a-request.promql中用一行或多行写出求“最近 12 小时内非 5xx 请求的比例”的 PromQL,并把结果以一个数字、保留到小数点后第四位,写入/root/obs-sli-events/a-request.txt。可以保留注释(#)。 - 把同样的 12 小时,按“只有 2xx 响应才是良好事件”重新测量。查询写入
/root/obs-sli-events/b-strict.promql,值写入/root/obs-sli-events/b-strict.txt,保留到小数点后第四位。分母必须与上一步相同。 - 用把“在 100 毫秒内完成的请求”视为良好事件的定义测量这 12 小时。查询写入
/root/obs-sli-events/c-latency.promql,值写入/root/obs-sli-events/c-latency.txt,保留到小数点后第四位。然后在/root/obs-sli-events/04-note.txt中用一行写下“按这个定义,无法在一个查询中同时查看状态码和延迟”这一事实及其原因——以reason=开头,且至少 40 个字符。 - 用把 1 分钟窗口当作事件的定义测量同样的 12 小时。如果在某 1 分钟内 5xx 比例低于 1%,就把这 1 分钟视为良好事件。查询写入
/root/obs-sli-events/d-window.promql,值写入/root/obs-sli-events/d-window.txt,保留到小数点后第四位。然后在/root/obs-sli-events/05-badminutes.txt中以整数写下 12 小时(720 分钟)中有多少分钟是坏的分钟。 - 创建
/root/obs-sli-events/budget.tsv。没有表头,共四行,每行是以制表符分隔的三个字段<id> <가용성> <30일 허용 다운타임 분>(占位符依次为 id、可用性、30 天允许停机时间的分钟数)。id 依次为a、b、c、d,可用性是前面几步写下的值,第三个字段是在该可用性下,30 天(43200 分钟)内允许变差的时间有多少分钟,写到小数点后第一位。 - 在
/root/obs-sli-events/choice.txt中写四行。sli=后面写选中的 id(a、b、c、d 之一),query=后面写该定义的查询文件名称(例如d-window.promql),target=后面以 0 到 1 之间的小数写要设定的目标,reason=后面用至少 60 个字符写明为什么选这个定义。评分器会真正发出query=所指向的文件,确认它与sli=是否相符。 - 在
/root/obs-sli-events/decision.txt中写两行。每行是target=<목표> consumed=<소진비율> release=<allow|hold>(占位符依次为目标、消耗比例、allow 或 hold 之一),目标第一行是0.99,第二行是0.95。消耗比例按 (1 − 测得的可用性) ÷ (1 − 目标) 计算,保留到小数点后第三位;判定为:消耗比例大于等于 1 是hold,小于 1 是allow。测得的可用性使用第 7 步所选定义的值。
参考
- 工作目录是
/root/obs-sli-events。如果不存在,请先创建。 - 查询可以用
promq "<PromQL>"直接发出试试,原始 JSON 用promq -r。在脚本中使用curl -sG --data-urlencode "query=..." http://127.0.0.1:9090/api/v1/query。 - Pod 的 Prometheus 中预先放入了 12 小时的数据。其中包含一次 20 分钟的错误激增。
- 常见错误:不使用 increase 就直接对计数器做除法。计数器是累计值,比率会被抹平成整个周期的平均值。
- 常见错误:假定延迟直方图带有状态码标签。本实验的第 4 步正是那堵墙。
- Implementing SLOs (SRE Workbook)、Service Level Objectives (SRE Book 第 4 章)、Querying basics、Query functions、Histograms and summaries
先确定把什么算作一个
在 /root/obs-sli-events/01-events.txt 中写三行。metric= 后面写用于统计事件的计数器指标名称,failure_label= 后面写该指标中区分是否失败的标签名称,valid_12h= 后面以整数写最近 12 小时内的有效事件数(job 是 shop-api)。值请自己发出查询来获得。
有哪些指标,可以用 promq "{__name__=~\"http.*\"}" 或 curl -s http://127.0.0.1:9090/api/v1/label/__name__/values | jq 查看。12 小时内计数器的增加量用 increase 求得。标签名称只写名称,不写值。
以请求为准——只把 5xx 算作失败
在 /root/obs-sli-events/a-request.promql 中用一行或多行写出求“最近 12 小时内非 5xx 请求的比例”的 PromQL,并把结果以一个数字、保留到小数点后第四位,写入 /root/obs-sli-events/a-request.txt。可以保留注释(#)。
计数器是累计的,所以必须转换成区间内的增加量。分子和分母分别用 sum 汇总后再相除。选出 5xx 的标签匹配,使用正则匹配器。
如果把 400 系列也算作失败,会有多大变化
把同样的 12 小时,按“只有 2xx 响应才是良好事件”重新测量。查询写入 /root/obs-sli-events/b-strict.promql,值写入 /root/obs-sli-events/b-strict.txt,保留到小数点后第四位。分母必须与上一步相同。
400 系列通常是客户端的错,所以一般不算作服务的失败,但也有像认证失败激增这样的事故,属于我们责任范围内的 4xx。看一看修改定义后,数字向哪个方向移动。
缓慢的成功算成功吗
用把“在 100 毫秒内完成的请求”视为良好事件的定义测量这 12 小时。查询写入 /root/obs-sli-events/c-latency.promql,值写入 /root/obs-sli-events/c-latency.txt,保留到小数点后第四位。然后在 /root/obs-sli-events/04-note.txt 中用一行写下“按这个定义,无法在一个查询中同时查看状态码和延迟”这一事实及其原因——以 reason= 开头,且至少 40 个字符。
直方图的桶是累计的。请看 le 为某个值的桶,是不是“在该值以内完成的请求数”。用作分母的全部请求数,在直方图的 count 系列里。关键在于两个指标的标签集合互不相同。
不数请求,来数分钟
用把 1 分钟窗口当作事件的定义测量同样的 12 小时。如果在某 1 分钟内 5xx 比例低于 1%,就把这 1 分钟视为良好事件。查询写入 /root/obs-sli-events/d-window.promql,值写入 /root/obs-sli-events/d-window.txt,保留到小数点后第四位。然后在 /root/obs-sli-events/05-badminutes.txt 中以整数写下 12 小时(720 分钟)中有多少分钟是坏的分钟。
用子查询(subquery)[12h:1m] 生成 1 分钟间隔的值,在比较运算符后面加上 bool,就会得到真为 1、假为 0 的系列。该系列的平均值就是良好分钟的比例。坏分钟的数量从 720 倒着数。
把四种定义换算成 30 天的允许停机时间
创建 /root/obs-sli-events/budget.tsv。没有表头,共四行,每行是以制表符分隔的三个字段 <id> <가용성> <30일 허용 다운타임 분>(占位符依次为 id、可用性、30 天允许停机时间的分钟数)。id 依次为 a、b、c、d,可用性是前面几步写下的值,第三个字段是在该可用性下,30 天(43200 分钟)内允许变差的时间有多少分钟,写到小数点后第一位。
允许停机时间是 (1 − 可用性) × 43200。这一步的关键是四行数字相差多大——只改变一个定义,运维团队需要承担的时间就会相差好几倍。
以机器可读的方式声明所选的定义
在 /root/obs-sli-events/choice.txt 中写四行。sli= 后面写选中的 id(a、b、c、d 之一),query= 后面写该定义的查询文件名称(例如 d-window.promql),target= 后面以 0 到 1 之间的小数写要设定的目标,reason= 后面用至少 60 个字符写明为什么选这个定义。评分器会真正发出 query= 所指向的文件,确认它与 sli= 是否相符。
正确答案不止一个。不过所选的依据必须与前面几步的数字衔接起来——例如,如果选了延迟标准,就要先在第 6 步的表中确认 30 天允许停机时间是否能够承受,再做选择。
同样的数据,不同的目标——要不要允许发布
在 /root/obs-sli-events/decision.txt 中写两行。每行是 target=<목표> consumed=<소진비율> release=<allow|hold>(占位符依次为目标、消耗比例、allow 或 hold 之一),目标第一行是 0.99,第二行是 0.95。消耗比例按 (1 − 测得的可用性) ÷ (1 − 目标) 计算,保留到小数点后第三位;判定为:消耗比例大于等于 1 是 hold,小于 1 是 allow。测得的可用性使用第 7 步所选定义的值。
消耗比例为 1,意味着“在这个周期内可用的错误预算刚好用完”。即使是同样的数据,目标定在哪里,发布决定就会颠倒——所以目标不是数字,而是共识。