Prometheus 做爲如今最火的雲原生監控工具,它的優秀表現是毋庸置疑的。可是在咱們使用過程當中,隨着時間的推移,存儲在 Prometheus 中的監控指標數據愈來愈多,查詢的頻率也在不斷的增長,當咱們用 Grafana 添加更多的 Dashboard 的時候,可能慢慢地會體驗到 Grafana 已經沒法按時渲染圖表,而且偶爾還會出現超時的狀況,特別是當咱們在長時間彙總大量的指標數據的時候,Prometheus 查詢超時的狀況可能更多了,這時就須要一種可以相似於後臺批處理的機制在後臺完成這些複雜運算的計算,對於使用者而言只須要查詢這些運算結果便可。Prometheus 提供一種記錄規則(Recording Rule) 來支持這種後臺計算的方式,能夠實現對複雜查詢的 PromQL 語句的性能優化,提升查詢效率。node
好比咱們想要了解 Kubernetes 節點之間 CPU 和內存的實際利用率,咱們能夠經過使用 container_cpu_usage_seconds_total 和 container_memory_usage_bytes 這兩個指標來查詢 CPU 和內存的利用率。由於每一個運行中的容器都會收集這兩個指標進行,可是須要知道,對於稍微大點的線上環境,可能咱們同時運行着成千上萬的容器,好比如今咱們以每5分鐘的頻率去查詢下一週內數千個容器的數據的時候,Prometheus 就比較難以快速進行數據查詢了。性能優化
好比咱們用 container_cpu_usage_seconds_total 總數除以 kube_node_status_allocatable_cpu_cores 總數得出 CPU 利用率:ide
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
咱們說了 Prometheus 提供了一種叫作 記錄規則(Recording Rule)的方式能夠來優化咱們的查詢語句,記錄規則的基本思想是,它容許咱們基於其餘時間序列建立自定義的 meta-time 序列,若是你使用 Prometheus Operator 的話能夠發現 Prometheus 中已經有了大量此類規則,好比:性能
groups: - name: k8s.rules rules: - expr: | sum(rate(container_cpu_usage_seconds_total{image!="", container!=""}[5m])) by (namespace) record: namespace:container_cpu_usage_seconds_total:sum_rate - expr: | sum(container_memory_usage_bytes{image!="", container!=""}) by (namespace) record: namespace:container_memory_usage_bytes:sum
上面的這兩個規則就徹底能夠執行上面咱們的查詢,它們會連續執行並以很小的時間序列將結果存儲起來。sum(rate(container_cpu_usage_seconds_total{job="kubelet",image!="",container_name!=""}[5m]))by(namespace)將以預約義的時間間隔進行評估,並存儲爲新的指標:namespace:container_cpu_usage_seconds_total:sum_rate,與內存查詢相同。優化
如今,我能夠將查詢更改成以下所示得出 CPU 利用率:lua
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倍!spa
一樣的方式計算內存利用率:code
sum(namespace:container_memory_usage_bytes:sum) / avg_over_time(sum(kube_node_status_allocatable_memory_bytes)[5m:5m]) Load time: 677ms
如今運行速度提升了27倍!blog
在 Prometheus 配置文件中,咱們能夠經過 rule_files 定義 recoding rule 規則文件的訪問路徑,和定義報警規則的方式基本一致:
rule_files: [ - <filepath_glob> ... ]
每個規則文件經過如下格式進行定義:
groups: [ - <rule_group> ]
一個簡單的規則文件多是這個樣子的:
groups: - name: example rules: - record: job:http_inprogress_requests:sum expr: sum(http_inprogress_requests) by (job)
rule_group 的具體配置項以下所示:
# 分組的名稱,在一個文件中必須是惟一的 name: <string> # 評估分組中規則的頻率 [ interval: <duration> | default = global.evaluation_interval ] rules: [ - <rule> ... ]
與告警規則一致,一個 group 下能夠包含多條規則 rule。
# 輸出的時間序列名稱,必須是一個有效的 metric 名稱 record: <string> # 要計算的 PromQL 表達式,每一個評估週期都是在當前時間進行評估的,結果記錄爲一組新的時間序列,metrics 名稱由 record 設置 expr: <string> # 添加或者覆蓋的標籤 labels: [ <labelname>: <labelvalue> ]
根據規則中的定義,Prometheus 會在後臺完成 expr 中定義的 PromQL 表達式計算,而且將計算結果保存到新的時間序列 record 中,同時還能夠經過 labels 標籤爲這些樣本添加額外的標籤。
這些規則文件的計算頻率默認與告警規則計算頻率一致,都經過 global.evaluation_interval 進行定義:
global: [ evaluation_interval: <duration> | default = 1m ]