個人 Prometheus 到底啥時候報警?

最近又被問到了 Prometheus 爲啥不報警,剛好回憶起以前常常解答相關問題,不妨寫一篇文章來解決下面兩個問題:面試

  • 個人 Prometheus 爲啥報警?
  • 個人 Prometheus 爲啥不報警?
從 for 參數開始

咱們首先須要一些背景知識:Prometheus 是如何計算併產生警報的?redis


看一條簡單的警報規則:數據庫

- alert: KubeAPILatencyHigh annotations: message: The API server has a 99th percentile latency of {{ $value }} seconds for {{ $labels.verb }} {{ $labels.resource }}. expr: | cluster_quantile:apiserver_request_latencies:histogram_quantile{job="apiserver",quantile="0.99",subresource!="log"} > 4 for: 10m labels: severity: criticalapi

這條警報的*大體*含義是,假如 kube-apiserver 的 P99 響應時間大於 4 秒,並持續 10 分鐘以上,就產生報警。微信

首先要注意的是由 `for` 指定的 Pending Duration。這個參數主要用於降噪,不少相似響應時間這樣的指標都是有抖動的,經過指定 Pending Duration,咱們能夠 過濾掉這些瞬時抖動,讓 on-call 人員可以把注意力放在真正有持續影響的問題上。架構

那麼顯然,下面這樣的情況是不會觸發這條警報規則的,由於雖然指標已經達到了警報閾值,但持續時間並不夠長:運維

但偶爾咱們也會碰到更奇怪的事情。機器學習

爲何不報警?

(圖二: 爲啥不報警) post

相似上面這樣持續超出閾值的場景,爲何有時候會不報警呢?學習

爲何報警?

(圖三: 爲啥會報警)

相似上面這樣並未持續超出閾值的場景,爲何有時又會報警呢?

採樣間隔

這其實都源自於 Prometheus 的數據存儲方式與計算方式。

首先,Prometheus 按照配置的抓取間隔(`scrape_interval`)定時抓取指標數據,所以存儲的是形如 (timestamp, value) 這樣的採樣點。

對於警報, Prometheus 會按固定的時間間隔重複計算每條警報規則,所以警報規則計算獲得的只是稀疏的採樣點,而警報持續時間是否大於 `for` 指定的 Pending Duration 則是由這些稀疏的採樣點決定的。

而在 Grafana 渲染圖表時,Grafana 發送給 Prometheus 的是一個 Range Query,其執行機制是從時間區間的起始點開始,每隔必定的時間點(由 Range Query 的 `step` 請求參數決定) 進行一次計算採樣。

這些結合在一塊兒,就會致使警報規則計算時「看到的內容」和咱們在 Grafana 圖表上觀察到的內容不一致,好比下面這張示意圖:

上面圖中,圓點表明原始採樣點:

  • 40s 時,第一次計算,低於閾值
  • 80s 時,第二次計算,高於閾值,進入 Pending 狀態
  • 120s 時,第三次計算,仍然高於閾值,90s 處的原始採樣點雖然低於閾值,可是警報規則計算時並無」看到它「
  • 160s 時,第四次計算,高於閾值,Pending 達到 2 分鐘,進入 firing 狀態
  • 持續高於閾值
  • 直到 360s 時,計算獲得低於閾值,警報消除

因爲採樣是稀疏的,部分採樣點會出現被跳過的情況,而當 Grafana 渲染圖表時,取決於 Range Query 中採樣點的分佈,圖表則有可能捕捉到 被警報規則忽略掉的」低谷「(圖三)或者也可能沒法捕捉到警報規則碰到的」低谷「(圖二)。如此這般,咱們就被」圖表「給矇騙過去,質疑起警報來了。

如何應對

首先嘛, Prometheus 做爲一個指標系統天生就不是精確的——因爲指標自己就是稀疏採樣的,事實上全部的圖表和警報都是」估算」,咱們也就沒必要 太糾結於圖表和警報的對應性,可以幫助咱們發現問題解決問題就是一個好監控系統。固然,有時候咱們也得證實這個警報確實沒問題,那能夠看一眼 `ALERTS` 指標。`ALERTS` 是 Prometheus 在警報計算過程當中維護的內建指標,它記錄每一個警報從 Pending 到 Firing 的整個歷史過程,拉出來一看也就清楚了。

但有時候 ALERTS 的說服力可能還不夠,由於它自己並無記錄每次計算出來的值究竟是啥,而在咱們回頭去考證警報時,又沒法選取出和警報計算過程當中如出一轍的計算時間點, 所以也就沒法還原警報計算時看到的計算值到底是啥。這時候終極解決方案就是把警報所要計算的指標定義成一條 Recording Rule,計算出一個新指標來記錄計算值,而後針對這個 新指標作閾值報警。kube-prometheus 的警報規則中就大量採用了這種技術。

到此爲止了嗎?

Prometheus 警報不只包含 Prometheus 自己,還包含用於警報治理的 Alertmanager,咱們能夠看一看上面那張指標計算示意圖的全圖:

在警報產生後,還要通過 Alertmanager 的分組、抑制處理、靜默處理、去重處理和降噪處理最後再發送給接收者。而這個過程也有大量的因素可能會致使警報產生了卻最終 沒有進行通知。這部分的內容,以前的文章 搞搞 Prometheus:Alertmanager 已經涵蓋,這兩篇內容加在一塊兒,也算是能把開頭的兩個問題解答得差很少了吧😂。

做者:吳葉磊
原文:https://aleiwu.com/post/prome...

最新整理的 2TB 技術乾貨:包括系統運維、數據庫、redis、MogoDB、電子書、Java基礎課程、Java實戰項目、架構師綜合教程、架構師實戰項目、大數據、Docker容器、ELK Stack、機器學習、BAT面試精視頻等。在「 民工哥技術之路」微信公衆號對話框回覆關鍵字:1024便可獲取所有資料。

相關文章
相關標籤/搜索