记录规则与告警规则,以及测试
目标
设计两层记录规则,在其上添加告警规则,并编写计算预期值的单元测试。最后,将相同内容转换为 Prometheus Operator 可读取的 CR 形式。
为什么重要
记录规则不是“加速查询的缓存”,而是转移计算时机的设计决策。查询时的负载被移到评估时,并会永久产生新的时间序列。因此创建前必须计算数量。120 条路由乘以 5 种窗口,一条规则就会产生 600 个时间序列;50 条规则就是 3 万个。分层也是同样道理:第 1 层只扫描一次原始数据,第 2 层和告警规则只读取其结果,避免按规则数量重复扫描原始数据。规则就是生产代码,而生产代码不能未经测试就部署。
步骤
- 创建
/root/pca-rules/recording.yml,在groups下将第一个组写为name: http_sli、interval: 30s。 - 在该组的
rules中添加两条第 1 层规则。record: route:http_requests:rate5m使用sum(rate(http_requests_total[5m])) by (route),record: route:http_requests_errors:rate5m使用sum(rate(http_requests_total{status_class="5xx"}[5m])) by (route)。 - 在第 1 层下方添加第 2 层规则
record: route:http_error_ratio:rate5m。表达式用route:http_requests_errors:rate5m除以route:http_requests:rate5m,不得再次使用原始http_requests_total。 - 添加
record: route:http_request_duration_seconds:p99_rate5m。表达式为histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, route))。该文件总共应有 4 条记录规则。 - 创建
/root/pca-rules/alerting.yml,在组name: http_alerts下编写告警CheckoutHighErrorRatio。expr为route:http_error_ratio:rate5m > 0.01,for: 5m,labels.severity: page,annotations中包含summary和runbook_url(以 http 开头的 URL)。 - 在
/root/pca-rules/recording_test.yml中编写 promtool 单元测试。rule_files为recording.yml,evaluation_interval: 30s,tests[0].interval: 15s;input_series中包含 2xx(0+150x40)和 5xx(0+3x40)两条时间序列;promql_expr_test中的expr: route:http_error_ratio:rate5m、eval_time: 8m,以及exp_samples的value为 3 除以 153 的值(以 0.0196 开头)。 - 创建命名空间
pca-rules,并在/root/pca-rules/prometheusrule.yaml中编写 PrometheusRule。设置apiVersion: monitoring.coreos.com/v1、kind: PrometheusRule、metadata.name: checkout-sli、metadata.namespace: pca-rules、metadata.labels.release: kube-prometheus-stack、spec.groups[0].name: checkout_sli,并在其中同时加入record: route:http_error_ratio:rate5m和alert: CheckoutHighErrorRatio。
参考
expr可以写成一行,也可使用expr: |块写成多行。评分会忽略空白。- 请自行计算第 6 步的预期值。若每 15 秒 2xx 增加 150、5xx 增加 3,则 rate 比率为 3 / (150 + 3)。
- 常见错误 1:把第 2 层写在第 1 层上方。同一组按从上到下的顺序评估。
- 常见错误 2:遗漏记录规则名称中的冒号。冒号表示这是派生时间序列。
- 常见错误 3:在 PrometheusRule 中遗漏
release标签。Operator 的 ruleSelector 使用该标签选择规则。
创建规则组框架
创建 /root/pca-rules/recording.yml,在 groups 下将第一个组写为 name: http_sli、interval: 30s。
规则文件顶层是 groups 列表。每个组都有 name 和可选的 interval;省略 interval 时使用 global.evaluation_interval。同一组中的规则按顺序评估。
第 1 层——只扫描一次原始数据
在该组的 rules 中添加两条第 1 层规则。record: route:http_requests:rate5m 使用 sum(rate(http_requests_total[5m])) by (route),record: route:http_requests_errors:rate5m 使用 sum(rate(http_requests_total{status_class="5xx"}[5m])) by (route)。
在 record 字段写入新时间序列名称,在 expr 中写表达式。保持 rate 位于 sum 内部,并让两条规则都按相同维度(route)聚合,之后才能相除。
第 2 层——只引用第 1 层
在第 1 层下方添加第 2 层规则 record: route:http_error_ratio:rate5m。表达式用 route:http_requests_errors:rate5m 除以 route:http_requests:rate5m,不得再次使用原始 http_requests_total。
如果比率规则再次扫描原始指标,分层就失去意义。只使用前面创建的两个时间序列名称进行除法。组内从上到下评估,因此顺序也很重要。
p99 记录规则
添加 record: route:http_request_duration_seconds:p99_rate5m。表达式为 histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, route))。该文件总共应有 4 条记录规则。
名称遵循级别:指标:运算约定。没有冒号的名称无法与原始指标区分。表达式中对 bucket 使用 rate,并确保聚合时保留 le。
告警规则文件
创建 /root/pca-rules/alerting.yml,在组 name: http_alerts 下编写告警 CheckoutHighErrorRatio。expr 为 route:http_error_ratio:rate5m > 0.01,for: 5m,labels.severity: page,annotations 中包含 summary 和 runbook_url(以 http 开头的 URL)。
告警规则使用 alert 字段而不是 record。表达式应引用记录规则结果,避免每次评估都扫描原始数据。for 表示条件连续为真的时间;中间任何一次为假都会把计时器重置为 0。
promtool 单元测试文件
在 /root/pca-rules/recording_test.yml 中编写 promtool 单元测试。rule_files 为 recording.yml,evaluation_interval: 30s,tests[0].interval: 15s;input_series 中包含 2xx(0+150x40)和 5xx(0+3x40)两条时间序列;promql_expr_test 中的 expr: route:http_error_ratio:rate5m、eval_time: 8m,以及 exp_samples 的 value 为 3 除以 153 的值(以 0.0196 开头)。
input_series 的 values 使用 시작+증가x횟수 语法。若每 15 秒 2xx 增加 150、5xx 增加 3,错误比率就是 3 除以 153。明确写下预期值后,规则含义将来发生变化时 CI 就能发现。
转换为 PrometheusRule CR
创建命名空间 pca-rules,并在 /root/pca-rules/prometheusrule.yaml 中编写 PrometheusRule。设置 apiVersion: monitoring.coreos.com/v1、kind: PrometheusRule、metadata.name: checkout-sli、metadata.namespace: pca-rules、metadata.labels.release: kube-prometheus-stack、spec.groups[0].name: checkout_sli,并在其中同时加入 record: route:http_error_ratio:rate5m 和 alert: CheckoutHighErrorRatio。
Operator 通过 ruleSelector 选择 CR,因此标签不匹配时即使文件存在也会被忽略。spec.groups 的结构与规则文件相同,一个 CR 可同时包含记录规则和告警规则。当前环境没有 CRD,所以只需编写文件并实际创建命名空间。