照顧 Prometheus 的生活起居
Background
Prometheus 已經成為 Metric 界的翹楚,目前正想要跨到 Log 領域當中 ( Loki ),不過有 ElasticSearch 擋在前面,看起來是沒有這麼容易達成;而同樣在 Elastic 這邊也想要踏足 Metric 的收集跟監控,不過也遇到一樣的問題,就是有一個好用的 Prometheus 競爭對手擋在那裡XD 距離上一篇撰寫如何使用 Kubernetes Operator 來架設 Prometheus 的文章不知不覺也過了兩年@@ 而今天這篇文章則是想要接著來探討每天維運 Prometheus 的小小經驗,到底該怎麼好好地照顧 Prometheus,才能讓系統發生不預期的事件時,他會乖乖地發出通知呢?在此篇分享文章中會談到的主題如下:
- Prometheus Storage & Scalability
- Incident Management
- Architecture in Production Environment
- Who Monitor Prometheus?
Prometheus Storage & Scalability
Prometheus 安裝好之後就可以馬上開始使用,但經過一段時間之後就會開始發現,怎麼幾天前的資料看不到了,假如不在意的話,那也就算了 (因為有人真的只需要看到短期的數據就夠了),但偏偏有時候就是會需要查詢幾個禮拜前的資料,這時候無力感就會油然而生,在官方的文件中,其實可以找到透過參數 storage.tsdb.retention.time 跟 storage.tsdb.retention.size 就可以控制儲存資料的期限,不過…在 Prometheus 的用量越來越大,而且又是安裝在 Kubernetes 中的情況之下,其實我個人傾向不使用 Persistent Volume,而一兩年前的選擇並不多,只有 Thanos 可以用XD 在研究完之後發現他還滿不賴的,真的可以解掉我自己組織遇到的痛點
Thanos 利用到近年來很紅的 Sidecar Pattern,讓對於 Prometheus 的請求需要先透過他幫忙轉一手,而在 Thanos 中主要有幾個重要的元件:
- Store Gateway: 當想要讀取的 Prometheus Metric 已經被儲存到 Object Storage 時,就會透過 Store Gateway 將其撈出來
- Compactor: 負責將存放在 Cloud Storage 中的 Metric 資料做壓縮,降採樣,以及移除太舊的資料
- Receiver: 假如 Prometheus 使用 Remote Write 的方式將 Metric 往外傳送的話,就可以透過 Thanos Reveiver 對外提供的端點接收,然後 1) 將 Metric 提供給外部做查詢使用,2) 或是往後丟到 Cloud Storage 存放
- Ruler/Rule: 雖然 Prometheus 裡面有設定 Alert Rule 了,但假如擔心 Prometheus 存放資料的時間區間不夠長,或是想要有全面性的 Alert,例如跨 Cluster 的情況,那麼就可以使用 Ruler 來設定 Alert,透過由 Thanos Querier 所取得的資料來判斷是否需要觸發 Alert
- Querier/Query: 上面提到的 Thanos Sidecar, Store Gateway, Receiver 其實對外都是一致提供由 GRPC 所實作出來的 Store API,接著統一由 Thanos Query 去串接跟做資料整合,最後透過 Querier 實作出跟 Prometheus 一模一樣的 HTTP API ,因此可以讓外部工具直接使用,例如 Grafana
- Query Frontend: 為了增進查詢的效率,可以在 Query 前面再多一層 Query Fronten,他有點像是 Query 的 Proxy,對外一樣提供 Prometheus 的標準 HTTP v1 API,但他會以天為單位來對查詢的回傳資料做切割然後暫存起來,就不用每次都需要透過 Query 再去撈一次相同的 Metric 資料
所以我在公司內把 Prometheus Kubernetes Operator 與 Thanos 做完結合之後,就順利解掉了 Prometheus 的長期儲存及擴展問題,不過其實目前又有更多的解決方案可以選擇,例如官方的 Cortex,Uber 的 M3…等,這邊有一篇好文分享了目前各種解決方案的優缺點供大家在做選擇的時候可以有個依據,根據自己個人目前的情況來做選擇的話還是偏好使用 Thanos 就是了~
Incident Management
Prometheus Alert Manager 的 Notification 可以整合的東西滿多的,但在沒有想要花錢買 Incident Management 服務的情況之下,便自己用 Serverless 服務寫了一個陽春版的來使用,串接的方式當然就是採用 Prometheus Alerting 的 Webhook Config 選項,然後自己去把要被觸發的端點給實作出來,而在這個系統中,當 Prometheus 送出 Event 時…
- Webhook Endpoint 接收到 Prometheus Alert Event 之後,它會先去 Calendar Service 撈出目前主要跟次要 On Duty 的人是誰,並且還要加上目前正遭遇問題的服務負責人 (就是主管等級的XD)
- 接著把訊息丟到 IM Service 裡面,讓相關人等可以知道,畢竟目前大家對於 IM 的黏著度都滿高的,所以使用 IM 來傳送訊息的即時性還滿高的
- 然後再到 Ticket Service 裡面開一張 Ticket 來記錄這個事件,之後查找問題的紀錄都可以留在這邊,避免一些重要的討論,跟追查問題的狀態消失在茫茫訊息中
- 最後則是根據在 Calendar Service 撈出來的電話名單直接進行最有效的打電話動作,而這邊我並沒有設計太難的規則,就只是簡單的從第一個人開始打,沒人接就換第二個,一直打到有人接為止
Architecture in Production Environment
目前我在所有的 K8S Cluster 中都有安裝好 Prometheus + Thanos 不過只有在某一台共用的 K8S Cluster 中有安裝 Grafana,因此他會把其他的 Thanos 當作 Data Source 來呈現 Dashboard
這樣做的好處是每一個 Prometheus 可以專心負責監控他的所在的 K8S Cluster 或是相關專案或是環境內的服務就好,而且相同的設定可以被複製到不同的 K8S Cluster 中,所有的 Dashboard 只需要在其中一台共用的 K8S Cluster 管理就好,不會讓使用者造成混肴
Who Monitor Prometheus?
不管是在內部或是跟外部開會,總是會有人提到那誰要來幫忙監控你的監控系統這種雞生蛋,蛋生雞的問題,但其實這也是真的會遇到的尷尬情況,除此之外有一些東西也不是可以依靠 Prometheus 可以監控得到的,在這邊我個人自己有幾點建議
- 首先把系統內所有可以監控的東西都列出來,譬如 K8S Cluster, Database, Queue, Backend Service, Frontend Service…等,而 Prometheus 算是一個滿成熟的產品了,所以各種 Exporter 應有盡有,沒有的話,也可以很簡單的自己把 /metric 給實作出來讓他抓取,把這些項目做個八成的話,系統內部有出什麼問題的話應該都可以被偵測到才對
- 其實有些監控的面向必須要從外部來,而且甚至可能要從全球多個國家來測試才行,以最常見的 CDN 來說好了,今天自己服務在歐洲區的 CDN Edge 壞掉了,Prometheus 應該永遠都不會知道,非要等到歐洲的同事或是顧客來通報才有可能得知,而這種 Multi-Region Monitor 自己實作其實太浪費時間了,建議可以把自己服務比較重要的對外端點給列出來,然後去購買第三方服務 (例如:Site24x7, Monitis…等) 來幫忙從多個 Region 來做監控,避免服務明明已經出問題了,還自我感覺良好
- 假設有些服務真的很重要,而且從外面也不好監控到,這時候可以把 K8S Cluster 的 Node Group 特別多開一組給 Prometheus 專門使用,避免其他的應用程式來跟他搶奪運算資源導致他出問題無法正常監控
Conclusion & Future Work
把上述的這些都做完之後,應該可以大幅度地縮短 Incident Response Time,避免自己的服務已經死掉了還不知道,不過在經過一段時間的使用之後,發現自己先前規劃的大一統架構開始不勘使用當中,所以目前正在找時間要來規劃新版的架構,打算讓共用有安裝 Grafana 的 K8S Cluster 分成兩個,分別負責 Production 跟 Non-Production 環境;而且希望在一般的 K8S Cluster 中的 Thanos 只有安裝 Sidecar 元件,而資料的儲存跟讀取都從共用的 K8S Cluster 去做處理,不過目前還在 Plan & POC 階段而已,等到有實作成功的話,再來寫一篇文章分享好了 ==+