<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Prometheus 不完全避坑指南

          共 4374字,需瀏覽 9分鐘

           ·

          2020-08-12 02:06

          點擊上方藍色“Go語言中文網(wǎng)”關(guān)注我們,領(lǐng)全套Go資料,每天學習?Go?語言

          Prometheus[1] 是一個開源監(jiān)控系統(tǒng),它本身已經(jīng)成為了云原生中指標監(jiān)控的事實標準,幾乎所有 k8s 的核心組件以及其它云原生系統(tǒng)都以 Prometheus 的指標格式輸出自己的運行時監(jiān)控信息。我在工作中也比較深入地使用過 Prometheus,最大的感受就是它非常容易維護,突出一個簡單省心成本低。當然,這當中也免不了踩過一些坑,下面就總結(jié)一下。

          假如你沒有用過 Prometheus,建議先看一遍 官方文檔[2]

          接受準確性與可靠性的權(quán)衡

          Prometheus 作為一個基于指標(Metric)的監(jiān)控系統(tǒng),在設計上就放棄了一部分數(shù)據(jù)準確性:

          • 比如在兩次采樣的間隔中,內(nèi)存用量有一個瞬時小尖峰,那么這次小尖峰我們是觀察不到的;
          • 再比如 QPS、RT、P95、P99 這些值都只能估算,無法和日志系統(tǒng)一樣做到 100% 準確,下面也會講一個相關(guān)的坑;

          放棄一點準確性得到的是更高的可靠性,這里的可靠性體現(xiàn)為架構(gòu)簡單、數(shù)據(jù)簡單、運維簡單。假如你維護過 ELK 或其它日志架構(gòu)的話,就會發(fā)現(xiàn)相比于指標,日志系統(tǒng)想要穩(wěn)定地跑下去需要付出幾十倍的機器成本與人力成本。既然是權(quán)衡,那就沒有好或不好,只有適合不適合,我推薦在應用 Prometheus 之初就要先考慮清楚這個問題,并且將這個權(quán)衡明確地告訴使用方。

          首先做好自監(jiān)控

          不知道你有沒有考慮過一個問題,其它系統(tǒng)都用 Prometheus 監(jiān)控起來了,報警規(guī)則也設置好了,那 Prometheus 本身由誰來監(jiān)控?

          答案是”另一個監(jiān)控系統(tǒng)”,而這個監(jiān)控系統(tǒng)可以是另一個 Prometheus。按照官方的 quickstart 或 helm 部署的 Prometheus 單實例自己監(jiān)控自己的,我們當然不能指望一個系統(tǒng)掛掉之后自己發(fā)現(xiàn)自己掛了。因此我強烈建議**在上生產(chǎn)環(huán)境之前,一定要確保至少有兩個獨立的 Prometheus 實例互相做交叉監(jiān)控。**交叉監(jiān)控的配置也很簡單,每臺 Prometheus 都拉取其余所有 Prometheus 的指標即可。

          還有一個點是警報系統(tǒng)(Alertmanager),我們再考慮一下警報系統(tǒng)掛掉的情況:這時候 Prometheus 可以監(jiān)控到警報系統(tǒng)掛了,但是因為警報掛掉了,所以警報自然就發(fā)不出來,這也是應用 Prometheus 之前必須搞定的問題。這個問題可以通過給警報系統(tǒng)做 HA 來應對。除此之外還有一個經(jīng)典的兜底措施叫做 “Dead man’s switch”[3]: 定義一條永遠會觸發(fā)的告警,不斷通知,假如哪天這條通知停了,那么說明報警鏈路出問題了。

          不要使用 NFS 做存儲

          如題,Prometheus 維護者也在 issue 中表示過不支持 NFS[4]。這點我們有血淚教訓(我們曾經(jīng)有一臺 Prometheus 存儲文件發(fā)生損壞丟失了歷史數(shù)據(jù))。

          盡早干掉維度(Cardinality)過高的指標

          根據(jù)我們的經(jīng)驗,Prometheus 里有 50% 以上的存儲空間和 80% 以上的計算資源(CPU、內(nèi)存)都是被那么兩三個維度超高的指標用掉的。而且這類維度超高的指標由于數(shù)據(jù)量很大,稍微查得野一點就會 OOM 搞死 Prometheus 實例。

          首先要明確這類指標是對 Prometheus 的濫用,類似需求完全應該放到日志流或數(shù)倉里去算。但是指標的接入方關(guān)注的往往是業(yè)務上夠不夠方便,假如足夠方便的話什么都可以往 label 里塞。這就需要我們防患于未然,一個有效的辦法是用警報規(guī)則找出維度過高的壞指標,然后在 Scrape 配置里 Drop 掉導致維度過高的 label。

          警報規(guī)則的例子:

          #?統(tǒng)計每個指標的時間序列數(shù),超出?10000?的報警
          count?by?(__name__)({__name__=~".+"})?>?10000

          “壞指標”報警出來之后,就可以用 metric_relabel_configdrop 操作刪掉有問題的 label(比如 userId、email 這些一看就是問題戶),這里的配置方式可以查閱文檔

          對了,這條的關(guān)鍵詞是盡早,最好就是部署完就搞上這條規(guī)則,否則等哪天 Prometheus 容量滿了再去找業(yè)務方說要刪 label,那業(yè)務方可能就要忍不住扇你了……

          Rate 類函數(shù) + Recording Rule 的坑

          可能你已經(jīng)知道了 PromQL 里要先 rate()sum(),不能 sum() 完再 rate()(不知道也沒事,馬上講)。但當 rate() 已經(jīng)同類型的函數(shù)如 increase() 和 recording rule 碰到一起時,可能就會不小心掉到坑里去。

          當時,我們已經(jīng)有了一個維度很高的指標(只能繼續(xù)維護了,因為沒有盡早干掉),為了讓大家查詢得更快一點,我們設計了一個 Recording Rule,用 sum() 來去掉維度過高的 bad_label,得到一個新指標。那么只要不涉及到 bad_label,大家就可以用新指標進行查詢,Recording Rule 如下:

          sum(old_metric)?without?(bad_label)

          用了一段時候后,大家發(fā)現(xiàn) new_metricrate() 得到的 QPS 趨勢圖里經(jīng)常有奇怪的尖峰,但 old_metric 就不會出現(xiàn)。這時我們恍然大悟:繞了個彎踩進了 rate() 的坑里。

          這背后與 rate() 的實現(xiàn)方式有關(guān),rate() 在設計上假定對應的指標是一個 Counter,也就是只有 incr(增加) 和 reset(歸0) 兩種行為。而做了 sum() 或其他聚合之后,得到的就不再是一個 Counter 了,舉個例子,比如 sum() 的計算對象中有一個歸0了,那整體的和會下降,而不是歸零,這會影響 rate() 中判斷 reset(歸0) 的邏輯,從而導致錯誤的結(jié)果。寫 PromQL 時這個坑容易避免,但碰到 Recording Rule 就不那么容易了,因為不去看配置的話大家也想不到 new_metric 是怎么來的。

          要完全規(guī)避這個坑,可以遵守一個原則:Recording Rule 一步到位,直接算出需要的值,避免算出一個中間結(jié)果再拿去做聚合。

          警報和歷史趨勢圖未必 Match

          最近半年常常被問兩個問題:

          • 我的歷史趨勢圖看上去超過水位線了,警報為什么沒報
          • 我的歷史趨勢圖看上去挺正常的,警報為什么報了

          這其中有一個原因是:趨勢圖上每個采樣點的采樣時間和警報規(guī)則每次的計算時間不是嚴格一致的。當時間區(qū)間拉得比較大的時候,采樣點非常稀疏,不如警報計算的間隔來得密集,這個現(xiàn)象尤為明顯,比如時序圖采樣了 0秒,60秒,120秒三個點。而警報在15秒,30秒,45秒連續(xù)計算出了異常,那在圖上就看不出來。另外,經(jīng)過越多的聚合以及函數(shù)操作,不同時間點的數(shù)據(jù)差異會來得越明顯,有時確實容易混淆。

          這個其實不是問題,碰到時將趨勢圖的采樣間隔拉到最小,仔細比對一下,就能驗證警報的準確性。而對于聚合很復雜的警報,可以先寫一條 Recording Rule, 再針對 Recording Rule 產(chǎn)生的新指標來建警報。這種范式也能幫助我們更高效地去建分級警報(超過不同閾值對應不同的緊急程度)

          Alertmanager 的 group_interval 會影響 resolved 通知

          Alertmanager 里有一個叫 group_interval 的配置,用于控制同一個 group 內(nèi)的警報最快多久通知一次。這里有一個問題是 firing(激活) 和 resolved(已消除) 的警報通知是共享同一個 group 的。也就是說,假設我們的 group_interval 是默認的 5 分鐘,那么一條警報激活十幾秒后立馬就消除了,它的消除通知會在報警通知的 5 分鐘之后才到,因為在發(fā)完報警通知之后,這個 Group 需要等待 5 分鐘的 group_interval 才能進行下一次通知。

          這個設計讓”警報消除就立馬發(fā)送消除通知”變得幾乎不可能,因為假如把 group_interval 變得很小的話,警報通知就會過于頻繁,而調(diào)大的話,就會拖累到消除通知。

          這個問題修改一點源碼即可解決,不過無傷大雅,不修也完全沒問題。

          最后一條:不要忘記因何而來

          最后一條撒點雞湯:監(jiān)控的核心目標還是護航業(yè)務穩(wěn)定,保障業(yè)務的快速迭代,永遠不要忘記因何而來

          曾經(jīng)有一端時間,我們追求”監(jiān)控的覆蓋率”,所有系統(tǒng)所有層面,一定要有指標,而且具體信息 label 分得越細越好,最后搞出幾千個監(jiān)控項,不僅搞得眼花繚亂還讓 Prometheus 變慢了;

          還有一段時間,我們追求”警報的覆蓋率”,事無巨細必有要有警報,人人有責全體收警報(有些警報會發(fā)送給幾十個人)。最后當然你也能預想到了,告警風暴讓大家都對警報疲勞了;

          這些事情乍看起來都是在努力工作,但其實一開始的方向就錯了,監(jiān)控的目標絕對不是為了達到 xxx 個指標,xxx 條警報規(guī)則,這些東西有什么意義?依我看,負責監(jiān)控的開發(fā)就算不是 SRE 也要有 SRE 的心態(tài)和視野,不要為監(jiān)控系統(tǒng)的功能或覆蓋面負責(這樣很可讓導致開發(fā)在監(jiān)控里堆砌功能和內(nèi)容,變得越來越臃腫越來越不可靠),而要為整個業(yè)務的穩(wěn)定性負責,同時站在穩(wěn)定性的投入產(chǎn)出比角度去考慮每件事情的性質(zhì)和意義,不要忘記我們因何而來。

          參考資料

          [1]

          Prometheus: https://github.com/prometheus/prometheus

          [2]

          官方文檔: https://prometheus.io/docs/introduction/overview/

          [3]

          “Dead man’s switch”: https://en.wikipedia.org/wiki/Dead_man's_switch

          [4]

          在 issue 中表示過不支持 NFS: https://github.com/prometheus/prometheus/issues/3534



          推薦閱讀


          學習交流 Go 語言,掃碼回復「進群」即可


          站長 polarisxu

          自己的原創(chuàng)文章

          不限于 Go 技術(shù)

          職場和創(chuàng)業(yè)經(jīng)驗


          Go語言中文網(wǎng)

          每天為你

          分享 Go 知識

          Go愛好者值得關(guān)注


          瀏覽 74
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99久久久无码国产精品性波多 | 微信约操情人高潮在线 | 超碰人人澡人人看 | 亚洲视屏在线免费观看 | 青青久操视频 |