1

什么是Recording Rules

在讲述什么是Recording Rules之前,让我们想想是否我们在使用Pronetheus过程中,遇到类似的场景:随着时间的推移,Prometheus中存储的指标数量增加了,查询的频次也增加了,在做一些复杂的查询的时候,经常会因为超时而导致Grafana中的图无法渲染。更坏的情况是,在你选择了较长时间维度的情况下,Prometheus 会OOM。

此时我们都能想到预聚合这个概念。其实Recording Rules就是 Prometheus的预聚合。官方对于Recording Rules的定义如下:

一致的记录规则命名方案使一目了然的解释规则的含义更加容易,并且通过使错误或无意义的计算脱颖而出来避免错误。

定义总是让人云里雾里,不知所以。所以我们拿一个示例来说明。

假如你用Prometheus监控Kubernetes,那么你对下面的两个指标应该不会陌生,container_cpu_usage_seconds_totalcontainer_memory_usage_bytes),分别表示容器的CPU和内存使用。

当我们需要监控Kubernetes node 节点的CPU和内存的实际利用率时,我们的实现方案如下:

通过使用滑动窗口将container_cpu_usage_seconds_total总数除以kube_node_status_allocatable_cpu_cores总数得出的CPU利用率:

sum(rate(container_cpu_usage_seconds_total[5m])) / avg_over_time(sum(kube_node_status_allocatable_cpu_cores)[5m:5m])
Load time: 15723ms

通过使用滑动窗口将container_memory_usage_bytes总数除以kube_node_status_allocatable_memory_bytes总数来计算内存利用率:

avg_over_time(sum(container_memory_usage_bytes)[15m:15m]) / avg_over_time(sum(kube_node_status_allocatable_memory_bytes)[5m:5m])
Load time: 18656ms

当容器比较少的时候,当然这没有什么问题。但是当我们运行了成千上万个容器的时候,这种查询就比较耗时了。

这个时候需要Recording Rules出场了。它允许你基于其他时间序列创建自定义的元时间序列。

其实用过Prometheus Operator的话,会发现使用了大量的Recording Rules。

groups:
  - name: k8s.rules
    rules:
    - expr: |
        sum(rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m])) by (namespace)
      record: namespace:container_cpu_usage_seconds_total:sum_rate
    - expr: |
        sum(container_memory_usage_bytes{job="kubelet", image!="", container_name!=""}) by (namespace)
      record: namespace:container_memory_usage_bytes:sum

现在,我可以将查询更改为如下所示:通过使用滑动窗口将container_cpu_usage_seconds_total总数除以kube_node_status_allocatable_cpu_cores总数得出的CPU利用率:

sum(namespace:container_cpu_usage_seconds_total:sum_rate) / avg_over_time(sum(kube_node_status_allocatable_cpu_cores)[5m:5m])
Load time: 1077ms

比之前的查询快了14倍。

通过使用滑动窗口将container_memory_usage_bytes总数除以kube_node_status_allocatable_memory_bytes总数来计算内存利用率:

sum(namespace:container_memory_usage_bytes:sum) / avg_over_time(sum(kube_node_status_allocatable_memory_bytes)[5m:5m])
Load time: 677ms

比之前的查询快了27倍。

如何使用Recording Rules

顾名思义,Recording Rules是在rule_files定义。

每一个规则文件通过以下格式进行定义:

groups:
    [ - <rule_group> ]

示例:

- record: instance_path:request_latency_seconds_count:rate5m
  expr: rate(request_latency_seconds_count{job="myjob"}[5m])

- record: instance_path:request_latency_seconds_sum:rate5m
  expr: rate(request_latency_seconds_sum{job="myjob"}[5m])

这些规则文件的计算频率与告警规则计算频率一致,都通过global.evaluation_interval定义:

global:
  [ evaluation_interval: <duration> | default = 1m ]

总结

Recording Rules 其实就是拿空间换时间的典型,周期性通过复杂的查询,形成一个新的自定义metric。此时,我们就可以直接查询这个metric。由此带来的好处是,查询快速,因为不涉及到复杂的运算和不需要读取海量的点。


iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。