1. 程式人生 > >Prometheus 原始碼解讀(一)

Prometheus 原始碼解讀(一)

Prometheus 原始碼解讀(一)

Prometheus 是雲原生監控領域的事實標準,越來越來的開源專案開始支援 Prometheus 監控資料格式。從本篇開始,我將和大家一起閱讀分析 Prometheus 原始碼。學習 Prometheus 的設計理念,瞭解 Prometheus 的侷限性與不足。本系列分八個板塊逐一拆解 Prometheus 原始碼。本文基於 Prometheus v2.13.0。

  • 工作原理與架構
  • 時序資料庫模組(TSDB)
  • 配置檔案載入模組(Configuration Reloader)
  • 服務發現模組(Service Discovery Manager)
  • 資料抓取模組(Scrape Manager)
  • RES API 模組(Web Handler)
  • 查詢引擎(Query Engine & PromQL)
  • 效能與優劣勢總結

1. Prometheus 介紹

Prometheus 是基於時序資料庫(Time Series Database, TSDB)的監控告警系統。Prometheus 在 2016 年加入 CNCF 基金會,成為繼 Kubernetes 後第二個畢業專案,其火熱程度可見一斑。相比於傳統的監控方案,Prometheus 有以下幾個優勢:

  • 高效的儲存引擎

Prometheus 將監控指標以時序數列的格式儲存在時序資料庫 TSDB 中。相比於傳統的關係型資料庫,時序資料庫便於對已有資料進行聚合;在高併發的情況下,讀寫效能也遠高於關係型資料庫。Prometheus 2.0 版本重構了底層時序儲存引擎。目前,單個 Prometheus 伺服器可以做到每秒儲存百萬條指標資料,同時佔用磁碟空間也很小

  • 強大的查詢能力:PromQL

Prometheus 有獨立的 PromQL 查詢語言,另外還提供了很多內建的基於時間的處理函式,降低資料聚合的難度

  • 面向服務的架構

Prometheus 採用拉模型收集時序資料,資料拉取行為是由服務端來決定的。服務端可以通過某種服務發現機制來自動發現監控物件。而對於推模型的監控系統,客戶端需要負責在服務端上進行註冊及監控資料推送,這在微服務架構裡實現起來比較難的。當大量客戶端向服務的主動推送資料時,服務端的壓力較大

  • 與 Kubernetes 天然整合

Kubernetes 本身的指標也是以 Prometheus 格式暴露出來的

  • 逐步完善的生態

OpenMetrics:Prometheus 的資料格式逐漸成為一種標準。OpenMetrics 正在從 Prometheus 的資料格式中分離出來,逐漸成為監控資料格式的國際標準

Thanos:支援資料儲存的可伸縮,彌補 Prometheus 資料持久化方面的不足Prometheus

Prometheus Operator:簡化 Prometheus 配置管理

2. 架構分析

圖的左邊開始是監控資料來源。任何應用服務想要接入 Prometheus,都需要提供 HTTP 介面(通常是 x.x.x.x/metrics 地址),並暴露 Prometheus 格式的監控資料。Prometheus Server 通過 HTTP 協議週期性抓取監控目標的監控資料。Prometheus 提供了 Client 庫幫助開發人員在自己的應用中整合 Prometheus 指標。

而對於不適合直接在程式碼中整合 Client 庫的場景,比如應用來自第三方、不是由自己維護,應用不支援 HTTP 協議,那就需要為這些場景單獨編寫 Exporter 程式。Exporter 作為代理,把監控資料暴露出來。比如 Mysql Exporter,Node Exporter。

Prometheus 將採集到的資料儲存在本地時序資料庫中,但缺少資料副本。這也是 Prometheus 自身在資料持久化方面做的不足的地方。但這些儲存問題都有其他的解決方案,Prometheus 支援 remote write 方式將資料儲存到遠端。

Prometheus 支援通過 Kubernetes、靜態文字、Consul、DNS 等多種服務發現方式來獲取抓取目標(targets)。最後,使用者編寫 PromQL 語句查詢資料並進行視覺化。

3. 核心元件

Prometheus 的功能由多個互相協作的元件共同完成。這些元件也即本文開頭所列出的模組,比如 Service Discovery Manager。我們後續會逐一介紹。Prometheus 原始碼入口 main() 函式 完成引數初始化工作,並依次啟動各依賴元件。

首先,main 函式解析命令列引數(詳見附錄 A),並讀取配置檔案資訊(由 --config.file 引數提供)。Prometheus 特別區分了命令列引數配置(flag-based configuration)和檔案配置(file-based configuration)。前者用於簡單的設定,並且不支援熱更新,修改需要啟停 Prometheus Server 一次;後者支援熱更新。

main 函式完成初始化、啟動所有的元件。這些元件包括:Termination Handler、Service Discovery Manager、Web Handler 等。各元件是獨立的 Go Routine 在執行,之間又通過各種方式相互協調,包括使用 Channel、引用物件 Reference、傳遞 Context。

這些 Go Routine 的協作使用了 oklog/run 框架。oklog/run 是一套基於 Actor 設計模式的 Go Routine 編排框架,實現了多個 Go Routine 作為統一整體執行並有序依次退出。這在很多開源專案中都有使用,進一步瞭解可參考作者的另一篇文章《Go routine 編排框架:oklog/run 包》

4. 參考文件

「K8S 技術落地實踐」Prometheus 在 K8S 上的監控實踐 來自本文作者在杭州容器 Meetup 的分享

Prometheus Internal architecture

附錄 A:Prometheus 啟動引數

  • web:Prometheus 伺服器 HTTP 連線引數,REST API 啟用相關引數,Prometheus Console 網頁配置
  • storage:TSDB 相關配置
  • query:查詢執行相關配置
<
引數名 解釋
config.file 配置檔案的位置,包含抓取監控物件列表(用於服務發現)和 recording rules 檔案位置
web.listen-address Prometheus server 端監聽請求(API 請求、Dashboard 介面)的地址和埠,預設本地埠 9090
web.read-timeout 設定 Prometheus server 讀取客戶端請求的超時時間。以此來避免客戶端因超慢的寫操作,長時間佔用連結資源。ReadTimeout 覆蓋了從連線請求被接受到請求報文被完全讀取的時間。預設 5m
web.max-connections 最大連線數,預設 512
web.external-url 設定 Prometheus 對外的 URL。需要設定外部訪問的 Prometheus 通常因為啟用了反向代理。如果 external-url 包含路徑,則 Prometheus 所有對外的介面,都會帶上該路徑作為字首。eg. http://<host>:<port>/<path>/api/v1/query?query=up
web.route-prefix 用於替換 external-url 的路徑字首,eg. http://<host>:<port>/<route-prefix>/api/v1/query?query=up
web.user-assets 網頁靜態 asset 資料夾路徑
web.enable-lifecycle 開啟後,可以實現通過請求 /-/reload 熱載入更新配置,預設 false
web.enable-admin-api 開啟後,允許使用一些管理員級別的 api,包括刪除時間序列等,/api/v1/admin/tsdb/delete_series。預設 false
web.console.templates Prometheus Console 網站模板資料夾路徑
web.console.libraries Prometheus Console 使用的庫路徑
web.page-title Console 頁面標題
web.cors.origin 設定 Prometheus 服務端允許的域,用正則表示式表示。eg. https?://(domain*)\.com
storage.tsdb.path 監控資料儲存路徑,預設 data/
storage.tsdb.min-block-duration 設定資料塊最小時間跨度,預設 2h 的資料量。監控資料是按塊(block)儲存,每一個塊中包含該時間視窗內的所有樣本資料(data chunks)
storage.tsdb.max-block-duration 設定資料塊最大時間跨度,預設為最大保留時間的 10%
storage.tsdb.wal-segment-size 設定 WAL 分段儲存每個分段的大小。預設 128MB
storage.tsdb.retention.time 監控資料最大保留時間,預設 15d
storage.tsdb.no-lockfile 不在資料儲存目錄中建立檔案鎖
storage.tsdb.wal-compression 開啟後,會對 WAL 檔案進行壓縮(成本是帶來 CPU 開銷)。預設 false
storage.remote.flush-deadline
storage.remote.read-sample-limit 一次最多從遠端儲存中讀取取樣資料量,預設 5e7 條,0 表示無限制
storage.remote.read-concurrent-limit 最大併發讀,預設 10 個請求,0 表示無限制
rules.alert.for-outage-tolerance
rules.alert.for-grace-period
rules.alert.resend-delay
alertmanager.notification-queue-capacity
alertmanager.timeout
query.lookback-delta 在計算 PromQL 表示式結果時,最大回看時間
query.timeout 查詢超時時間
query.max-concurrency 最大併發處理查詢請求數,預設 20 個請求
query.max-samples 能載入到記憶體中最大采樣資料量,預設 5e7 條