0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Prometheus新手常犯的6項錯誤你知道嗎?

馬哥Linux運維 ? 來源:51CTO ? 2023-12-26 10:18 ? 次閱讀

錯誤 1:高基數(shù)炸彈

這是 Prometheus 使用者經(jīng)常會犯的一個錯,因為 Prometheus 時序是基于多標(biāo)簽的,它非常靈活,有時你想新增一個標(biāo)簽,從而將一個粗粒度的指標(biāo)進行拆分,但切記添加的標(biāo)簽的值應(yīng)該做到盡量收斂,不然會導(dǎo)致同一指標(biāo)名的標(biāo)簽數(shù)量巨大而導(dǎo)致 Prometheus 嚴(yán)重的性能問題(OOM)。

舉個例子,您有一個只包含 method 標(biāo)簽的時間序列 http_requests_total:

http_requests_total{method="POST"}
http_requests_total{method="GET"}
http_requests_total{method="PUT"}
http_requests_total{method="DELETE"}

這個時間序列定義沒問題,因為 HTTP 的 method 類型是有限的,但有一天,您可能想根據(jù)用戶 id 進行區(qū)分,類似這樣:

http_requests_total{method="POST",user_id="1"}
http_requests_total{method="POST",user_id="2"}
http_requests_total{method="POST",user_id="3"}
[…更多…]
http_requests_total{method="POST",user_id="16434313"}




http_requests_total{method="GET",user_id="1"}
http_requests_total{method="GET",user_id="2"}
http_requests_total{method="GET",user_id="3"}
[…更多…]
http_requests_total{method="GET",user_id="16434313"}
[…更多…]

假設(shè)您有非常多的不同用戶,所以此時就存在嚴(yán)重的高基數(shù)問題,這將導(dǎo)致 Prometheus 內(nèi)存使用激增,直至 OOM。

所以請您牢記:指標(biāo)上標(biāo)簽的每一種唯一組合都會自動創(chuàng)建一個對應(yīng)時間序列,Prometheus 都會對其進行攝取、索引、存儲和處理。

雖然針對單個標(biāo)簽的不同值的數(shù)量沒有明確的限制,但因為不同值都是一個新的時間序列,您需要確保其數(shù)量保持在您 Prometheus 服務(wù)器容量之下(一個大型 Prometheus 單節(jié)點能夠處理數(shù)幾百萬個時間序列),所以你在設(shè)計時間序列的標(biāo)簽的時候,需要確保它們的所有組合總數(shù)在您 Prometheus 服務(wù)器可以承受的范圍內(nèi)。

對此,有一些標(biāo)簽值我們要特別注意避免,例如:

公網(wǎng) IP 或者郵件地址。

HTTP 請求 Path 全路徑,尤其這些路徑帶有動態(tài) ID 等信息。

進程ID(除非是有限集合)。

有時您想在不完全刪除標(biāo)簽的情況下解決標(biāo)簽高基數(shù)的問題,那么我們就要想辦法減少其值的基數(shù)。例如,對于 /api/users/739567637385/posts/28388445 的 HTTP 請求, 我們將動態(tài)信息部分使用 user_id 和 post_id 占位符統(tǒng)一替換,所以整個 path 可以替換為 /api/users/{user_id}/posts/{post_id} ,從而有效減少 path 標(biāo)簽的值數(shù)量。

錯誤 2:告警表達式中因聚合導(dǎo)致價值標(biāo)簽丟失

在做告警的時候,我們往往會通過聚合計算去除不關(guān)心的一些標(biāo)簽。例如,如果您想確定某個服務(wù)的總體錯誤率(跨所有標(biāo)簽維度)是否過高,您可以編寫如下規(guī)則:

sum(rate(errors_total{job="my-job"}[5m])) > 10

這看上去沒問題,但默認情況下,sum() 聚合器會去掉時序的所有標(biāo)簽。它不僅會刪除您想要聚合的維度(如實例、錯誤類型等),還會刪除一些比較通用的標(biāo)簽,這些標(biāo)簽對于 alertmanager 中進行告警的路由或靜默是有幫助的。特別是 job 標(biāo)簽,因為不同 job 通常由不同的運維團隊負責(zé)。因此我們應(yīng)該盡可能在聚合中保留此標(biāo)簽:sum by(job) (rate(errors_total{job=”my-job”}[5m])) > 10

一個更好的選擇是通過使用 without() 聚合修飾符替換 by() 聚合修飾符,從而顯示排除不想要的標(biāo)簽,而盡可能保留下一些你不確定需要刪除的標(biāo)簽:

sum without(instance, type) (rate(errors_total{job="my-job"}[5m])) > 10

這樣,聚合時您沒有明確指定刪除的標(biāo)簽在 Alertmanager 中仍然可以使用,這對于告警的聚合和路由非常有用,也能幫助您更好了解警報的來源。

錯誤 3:使用不帶任何限定范圍的(裸)選擇器

在編寫 PromQL 查詢(尤其是告警)的時候,我們需要格外小心,應(yīng)該從關(guān)心的業(yè)務(wù)或服務(wù)的數(shù)據(jù)中進行查詢,而不是全局范圍。因為不同的業(yè)務(wù)可能使用了相同的指標(biāo)名稱,它們甚至表達了不同的含義,隨著時間的推移,相同指標(biāo)名稱的服務(wù)會越來越多,這可能會完全影響您的告警規(guī)則或者儀表盤數(shù)據(jù)。

為避免不小心從不相關(guān)的任務(wù)或者服務(wù)中查詢數(shù)據(jù),我們一般使用 job 標(biāo)簽來限定選擇器的范圍,確保其查詢的數(shù)據(jù)都是您關(guān)心的業(yè)務(wù)或服務(wù)。

例如,以下查詢就是一個不安全的“裸”選擇器,它可能會從您不期望的其他 job 中選擇具有相同指標(biāo)名的數(shù)據(jù):

rate(errors_total[5m]) > 10

我們可以使用 {job=”my-job”} 的選擇器從而將指標(biāo)限定在 my-job 服務(wù)范圍:

rate(errors_total{job="my-job"}[5m]) > 10

這顯然是一個更安全的方式,它可以有效避免從無關(guān)服務(wù)中查詢數(shù)據(jù),對您告警產(chǎn)生干擾,也能大大提升查詢性能。

錯誤 4:告警規(guī)則沒有使用 for 字段

for 字段主要用于告警規(guī)則評估,它允許您能夠指定任意告警需要在連續(xù)的規(guī)則評估周期中出現(xiàn)多長時間才從 pending 狀態(tài)變?yōu)?firing。大多數(shù)告警規(guī)則可能我們可以忽略該字段,只需要兩個評估周期即可觸發(fā)告警,但有時,我們?yōu)榱伺懦秳拥母蓴_,比如一些 CPU 使用率,或者某個節(jié)點因為一兩次抓取異常就判定 down 了。

考慮一個警報規(guī)則,它使用 up 指標(biāo)來查找無法成功抓取的目標(biāo),并省略了可選的 for 修飾符:

alert: InstanceDownexpr: up == 0

一次失敗的抓?。ê苋菀装l(fā)生)將導(dǎo)致觸發(fā)此規(guī)則。通常你希望讓你的警報規(guī)則不那么容易觸發(fā),并至少等待幾分鐘,看看問題是否真的存在,然后再觸發(fā)通知:

alert: InstanceDownexpr: up == 0for: 5m # 一個實例只有真的掛掉或者無法訪問長達 5 分鐘才創(chuàng)建告警信息。

不帶 for 針對一些內(nèi)置的帶有平均數(shù)計算的查詢表達式也同樣有問題,例如表示高錯誤率的告警:

alert: HighErrorRateexpr: rate(my_errors_total{job="my-job"}[5m]) > 10

這個規(guī)則將在第一次查詢到最近 5m 中該錯誤數(shù)的平均值 > 10 就立即創(chuàng)建告警,雖然 5m 的平均周期能夠帶來一定的穩(wěn)健性,但是由于 Promtheus rate() 特性,我們考慮一下,一個完全新的服務(wù)或者一段時間未收集到數(shù)據(jù)會發(fā)生什么:

5 分鐘的 rate() 窗口只會考慮一些最近的樣本,實際上并不會對五分鐘的數(shù)據(jù)進行平均。

時間序列甚至根本還沒五分鐘數(shù)據(jù),該規(guī)則也可能會立即創(chuàng)建告警。

因此我們可以使用 for 修飾符來解決此問題:

alert: HighErrorRateexpr: rate(my_errors_total{job="my-job"}[5m]) > 10for: 5m

幾乎大多數(shù)的告警規(guī)則都可以添加此參數(shù),從而使使警報規(guī)則更加穩(wěn)健。但請記住,這也會導(dǎo)致警報的反應(yīng)時間變慢,因此找到這個平衡很重要。

錯誤 5:rate() 函數(shù)窗口時間太短

在太短的時間窗口內(nèi)計算速率時,您是否曾對間隙或完全空的圖表感到沮喪,例如 rate(my_counter[1m])?rate() 和其他 PromQL 函數(shù)(如 increase()、irate()、deriv())告訴您時間序列在給定時間窗口內(nèi)上升或下降的速度,在輸入時間窗口下至少需要兩個樣本,從而能夠告訴你這兩個樣本之間的序列是如何發(fā)展的。如果將時間窗口設(shè)置得太小,則在該窗口下可能只有一個或零個樣本,在這種情況下,輸出結(jié)果為空。

例如,如果您采用 20s 的時間窗口對一個 15s 抓取間隔的指標(biāo)進行 rate(),那么在這 20 秒時間窗口內(nèi)很可能不會涵蓋兩個樣本,因此您會得到一個與實際結(jié)果差異很大的比率:

c7a6bc96-a30f-11ee-8b88-92fbcf53809c.jpg

采取極端的做法:如果將 rate 窗口縮小到 16s,當(dāng)兩個相距 15s 的點恰好落在任意對齊的 16s 窗口中時,您只會偶爾得到一個輸出點:

c7bc1de8-a30f-11ee-8b88-92fbcf53809c.jpg

因此,您需要選擇一個足夠大的時間窗口——不僅僅是抓取間隔的 2 倍,因為您還需要面對偶爾抓取失敗和不幸的窗口對齊。所以通常我們選擇 rate 窗口大小至少為抓取間隔的 4 倍:

c7d88ca8-a30f-11ee-8b88-92fbcf53809c.jpg

提示:使用 Grafana 時,可以使用 $__rate_interval 模板變量自動為您選擇一個安全間隔。

錯誤 6:rate() 相關(guān)函數(shù)用錯了指標(biāo)類型

查詢函數(shù)與指標(biāo)類型用錯的典型例子有:

rate() 函數(shù)用在 gauge 類型指標(biāo)

rate()、irate() 和 increase() 函數(shù)被設(shè)計成為僅適用于 counter 類型指標(biāo)。counter 類型是追蹤累計計數(shù)的指標(biāo),這些計數(shù)只會上升(永遠不會下降),除了在追蹤過程中偶爾因為重啟而重置為 0。為了在 rate 計算中盡可能消除計數(shù)器重置的影響,這些函數(shù)嘗試將提供的時間窗口內(nèi)樣本的值的任何減小都解釋為重置并對其進行補償。這種計數(shù)器的重置檢測和補償意味著您只能從這些函數(shù)中獲得正數(shù)的結(jié)果(或 0)。

如果你不小心傳入了一個可以自然上升和下降的指標(biāo)(比如內(nèi)存使用量),PromQL 將無法判斷這個錯誤,而只會返回一個不正確的輸出值。這是因為每次您的儀表指標(biāo)下降時,rate() 都會將其理解為計數(shù)器重置并且會錯誤地“糾正”它。

deriv() 函數(shù)用在 counter 類型指標(biāo)

您可以認為 deriv() 函數(shù)大致等同于 rate(),但它作用于 gauge 類型。deriv() 告訴您在輸入時間窗口內(nèi) gauge 類型指標(biāo)每秒上升或下降的速度。雖然并不常見,但這里與 rate() 相同的陷阱可能會給你帶來另外的困擾:因為 deriv() 函數(shù)沒有實現(xiàn)任何圍繞 counter 類型重置的邏輯(gauge 沒有這些),試圖使用 deriv() 計算一個在提供的窗口下有重置的 counter 的類型指標(biāo),就會得到一個不正確的結(jié)果,有時甚至是一個負數(shù)。

如何避免傳入錯誤類型的指標(biāo)?

由于 PromQL 無法自動檢測這種不正確的用法,所以您在使用這些函數(shù)時必須格外小心。我們除了經(jīng)驗和已有知識外,還可以依賴一些開源項目,例如 PromLens 查詢構(gòu)建器這樣的工具來輔助您檢測是否傳了錯誤的指標(biāo)類型:

c7e2fe04-a30f-11ee-8b88-92fbcf53809c.jpg

結(jié)論

以上 6 點就是一些剛開始使用 Prometheus 的朋友經(jīng)常會犯的錯誤,希望這些技巧對您使用 Prometheus 的有所幫助!

鏈接:https://blog.51cto.com/u_15576159/8963563

本文翻譯自文章 https://promlabs.com/blog/2022/12/11/avoid-these-6-mistakes-when-getting-started-with-prometheus,感覺作者總結(jié)比較深刻,都是 Prometheus 新人們經(jīng)常犯的錯誤,故簡要翻譯一下,方便和大家一起審查與自省。







審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 計數(shù)器
    +關(guān)注

    關(guān)注

    32

    文章

    2256

    瀏覽量

    94561
  • HTTP
    +關(guān)注

    關(guān)注

    0

    文章

    505

    瀏覽量

    31222
  • 選擇器
    +關(guān)注

    關(guān)注

    0

    文章

    108

    瀏覽量

    14539

原文標(biāo)題:Prometheus 新手常犯的 6 項錯誤,你該如何避免?

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    關(guān)于C語言編程時常犯錯誤匯總

    17個C語言新手編程時常犯錯誤及解決方式
    的頭像 發(fā)表于 06-26 09:19 ?6142次閱讀
    關(guān)于C語言編程時<b class='flag-5'>常犯</b>的<b class='flag-5'>錯誤</b>匯總

    18個C語言新手編程時常犯錯誤及解決方式

    ,經(jīng)常會出一些連自己都不知道錯在哪里的錯誤??粗绣e的程序,不知該如何改起,本人通過對C的學(xué)習(xí),積累了一些C編程時常犯錯誤,寫給各位學(xué)員以供參考。
    發(fā)表于 01-03 15:35 ?1035次閱讀

    【每日一貼日志】親愛的,知道嗎

    親愛的,知道嗎?從我們的相識到相知,我為了而改變了多少。知道,只要我不說,就永遠不
    發(fā)表于 09-29 15:18

    電池的危害有哪些,知道嗎

    電池的危害有哪些,知道嗎?,學(xué)習(xí)資料,感興趣的可以瞧一瞧。
    發(fā)表于 10-26 17:00 ?0次下載

    無線充電IC知道嗎

    無線充電IC知道嗎
    發(fā)表于 01-22 19:37 ?47次下載

    機器學(xué)習(xí)新手常犯錯誤怎么避免?

    ,上面列出了機器學(xué)習(xí)工程師新手常犯錯誤。希望你能從這些常見的錯誤中吸取教訓(xùn),創(chuàng)建更健壯的解決方案,從而帶來真正的價值。
    的頭像 發(fā)表于 11-13 17:44 ?3344次閱讀

    關(guān)于變壓器的這些冷知識,知道嗎?

    變壓器的這些冷知識,知道嗎?
    的頭像 發(fā)表于 02-04 15:28 ?4601次閱讀

    基于STM32的多種printf用法 知道嗎?

    基于STM32的多種printf用法,知道嗎?
    的頭像 發(fā)表于 02-29 17:02 ?4489次閱讀

    關(guān)于STM32的這幾個寄存器, 知道嗎

    關(guān)于STM32的這幾個寄存器,知道嗎?
    的頭像 發(fā)表于 03-06 15:19 ?1w次閱讀

    電工常犯的15大錯誤

    電工常犯的15大錯誤(航空直流電源技術(shù)特點)-電工常犯的15大錯誤? ? ? ? ? ? ? ? ? ??
    發(fā)表于 09-24 10:13 ?6次下載
    電工<b class='flag-5'>常犯</b>的15大<b class='flag-5'>錯誤</b>

    示波器的這些安全操作知道嗎

    示波器的這些安全操作知道嗎?示波器維修。很多人都知道示波器是用來干什么的,也知道示波器都有哪些種類和品牌,當(dāng)然也知道如何操作。但是,有人
    發(fā)表于 11-05 11:19 ?1698次閱讀

    ESD模型有哪幾種知道嗎?

    ESD模型有哪幾種知道嗎
    的頭像 發(fā)表于 05-09 10:00 ?1892次閱讀
    ESD模型有哪幾種<b class='flag-5'>你</b><b class='flag-5'>知道嗎</b>?

    無源與有源器件的這些區(qū)別知道嗎

    無源與有源器件的這些區(qū)別知道嗎?
    的頭像 發(fā)表于 10-26 15:27 ?4787次閱讀
    無源與有源器件的這些區(qū)別<b class='flag-5'>你</b>都<b class='flag-5'>知道嗎</b>?

    運算放大器的種類都有哪些?知道嗎?

    運算放大器的種類都有哪些?知道嗎
    的頭像 發(fā)表于 12-13 15:14 ?790次閱讀
    運算放大器的種類都有哪些?<b class='flag-5'>你</b><b class='flag-5'>知道嗎</b>?

    5大高精密多層pcb的特點知道嗎

    5大高精密多層pcb的特點知道嗎
    的頭像 發(fā)表于 12-08 16:10 ?913次閱讀