Prometheus監控k8s(1)-Prometheus簡介
https://github.com/prometheus/prometheus
https://github.com/yunlzheng/prometheus-book
https://www.cnblogs.com/xzkzzz/p/10208115.html
Prometheus介紹
Prometheus是一個最初在SoundCloud上構建的開源監控系統 。它現在是一個獨立的開源項目,為了強調這一點,並說明項目的治理結構,Prometheus 於2016年加入CNCF,作為繼Kubernetes之后的第二個托管項目。
Prometheus是由SoundCloud開發的開源監控報警系統和時序列數據庫。從字面上理解,Prometheus由兩個部分組成,一個是監控報警系統,另一個是自帶的時序數據庫(TSDB)
特點
- 具有由 metric 名稱和鍵/值對標識的時間序列數據的多維數據模型
- PromQL,有一個靈活的查詢語言
- 不依賴分布式存儲,只和本地磁盤有關
- 通過 HTTP 的服務拉取時間序列數據
- 也支持推送的方式來添加時間序列數據
- 通過服務發現或靜態配置發現目標
- 多種圖形和儀表板支持
架構圖
此圖說明prometheus的體系結構及其一些系統組件

圖片左側是各種數據源主要是各種符合 Prometheus 數據格式的 exporter,除此之外為了支持推動數據 類型的 Agent,可以通過 Pushgateway 組件,將 Push 轉化為 Pull。Prometheus 甚至可以從其它的 Prometheus 獲取數據,組建聯邦集群。 Prometheus 的基本原理是通過 HTTP 周期性抓取被監控組件的狀態,任意組件只要提供對應的 HTTP 接口 並且符合 Prometheus 定義的數據格式,就可以接入 Prometheus 監控。
圖片的上側是服務發現,Prometheus 支持監控對象的自動發現機制,從而可以動態獲取監控對象。 圖片中間是 Prometheus Server,Retrieval 模塊定時拉取數據,並通過 Storage 模塊保存數據。PromQL 為 Prometheus 提供的查詢語法,PromQL 模塊通過解析語法樹,調用 Storage 模塊查詢接口獲取監控數據。 圖片右側是告警和頁面展現,Prometheus 將告警推送到 alertmanger,然后通過 alertmanger 對告警進行處 理並執行相應動作。數據展現除了 Prometheus 自帶的 webui,還可以通過 grafana 等組件查詢 Prometheus 監控數據。
與其他監控系統的比較
在Prometheus 之前市面已經出現了很多的監控系統,如 Zabbix、Open-falcon 等。那么 prometheus 和這些監控系統有啥異同呢?我們先簡單介紹一下這些監控系統
Zabbix 是由 Alexei Vladishev 開源的分布式監控系統,支持多種采集方式和采集客戶端,同時支持 SNMP、 IPMI、JMX、Telnet、SSH 等多種協議,它將采集到的數據存放到數據庫中,然后對其進行分析整理,如果 符合告警規則,則觸發相應的告警。
Zabbix 核心組件主要是 Agent 和 Server,其中 Agent 主要負責采集數據並通過主動或者被動的方式采集數據發送到 Server/Proxy,除此之外,為了擴展監控項,Agent 還支持執行自定義腳本。Server 主要負責 接收 Agent 發送的監控信息,並進行匯總存儲,觸發告警等。 為了便於快速高效的配置 zabbix 監控項,zabbix 提供了模板機制,從而實現批量配置的目的。
Zabbix Server 將收集的監控數據存儲到 Zabbix Database 中。Zabbix Database 支持常用的關系型 數據庫,如果 MySQL、PostgreSQL、Oracle 等,默認 是 MySQL。Zabbix Web 頁面(PHP 編寫)負責數據 查詢。Zabbix 由於使用了關系型數據存儲時序數據,所以在監控大規模集群時常常在數據存儲方面捉襟見 肘。為此 zabbix 4.2 版本后也開始支持時序數據存儲,不過目前還不成熟。

Open-Falcon 是小米開源的企業級監控工具,用 Go 語言開發而成,包括小米、滴滴、美團等在內的互 聯網公司都在使用它,是一款靈活、可擴展並且高性能的監控方案,主要組件包括:
Falcon-agent:用 Go 語言開發的 Daemon 程序,運行在每台 Linux 服務器上,用於采集主機上的各種 指標數據,主要包括 CPU、內存、磁盤、文件系統、內核參數、Socket 連接等,目前已經支持 200 多項監 控指標。並且,Agent 支持用戶自定義的監控腳本,
Hearthbeat server:簡稱 HBS 心跳服務,每個 Agent 都會周期性地通過 RPC 方式將自己的狀態上報給 HBS,主要包括主機名、主機 IP、Agent 版本和插件版本,Agent 還會從 HBS 獲取自己需要執行的采集任務 和自定義插件。
Transfer:負責接收 Agent 發送的監控數據,並對數據進行整理,在過濾后通過一致性 Hash 算法發送 到 Judge 或者 Graph
Graph:RRD 數據上報、歸檔、存儲的組件。Graph 在收到數據以后,會以 rrdtool 的數據歸檔方式來存 儲,同時提供 RPC 方式的監控查詢接口。
Judge:告警模塊,Transfer 轉發到 Judge 的數據會觸發用戶設定的告警規則,如果滿足,則會觸發郵 件、微信或者回調接口。這里為了避免重復告警引入了 Redis 暫存告警,從而完成告警的合並和抑制。
Dashboard:面向用戶的監控數據查詢和告警配置界面

從開發語言上看,為了應對高並發和快速迭代的需求,監控系統的開發語言已經慢慢從 C 語言轉移到 Go。不得不說,Go 憑借簡潔的語法和優雅的並發,在 Java 占據業務開發,C 占領底層開發的情況下,准確 定位中間件開發需求,在當前開源中間件產品中被廣泛應用。
從系統成熟度上看,Zabbix 是老牌的監控系統:Zabbix 是在 1998 年出現的,系統功能比較穩定,成熟 度較高。而 Prometheus 和 Open-Falcon 都是最近幾年才誕生的,雖然功能還在不斷迭代更新,但站在巨人 的肩膀之上,在架構設計上借鑒了很多老牌監控系統的經驗;
從系統擴展性方面看,Zabbix 和 Open-Falcon 都可以自定義各種監控腳本,並且 Zabbix 不僅可以做到 主動推送,還可以做到被動拉取,Prometheus 則定義了一套監控數據規范,並通過各種 exporter 擴展系統 采集能力;
從數據存儲方面來看,Zabbix 采用關系數據庫保存,這極大限制了 Zabbix 采集的性能,Open-Falcon 采用 RDD 數據存儲,並且可以對接到 OpenTSDB,而 Prometheus 自研一套高性能的時序數據庫,在 V3 版 本可以達到每秒千萬級別的數據存儲,通過對接第三方時序數據庫擴展歷史數據的存儲;
從配置和維護的復雜度上看,prometheus 只有一個核心 server 組件,一條命令便可以啟動,相比而言, 其他系統配置相對麻煩,尤其是 open-falcon。
從社區活躍度上看,目前 Zabbix 社區活躍度比較低,Open-Falcon 雖然也比較活躍,但基本都是國內 的公司參與,Prometheus 在這方面占據絕對優勢,社區活躍度最高,並且受到 CNCF 的支持,后期的發展 值得期待;
從容器支持角度看,由於 Zabbix 出現得比較早,當時容器還沒有誕生,自然對容器的支持也比較差。 Open-Falcon 雖然提供了容器的監控,但支持力度有限。Prometheus 的動態發現機制,不僅可以支持 swarm 原生集群,還支持 Kubernetes 容器集群的監控,是目前容器監控最好解決方案。Zabbix 在傳統監控系統中, 尤其是在服務器相關監控方面,占據絕對優勢。伴隨着容器的發展,Prometheus 開始成為主導及容器監控 方面的標配,並且在未來可見的時間內被廣泛應用。總體來說,對比各種監控系統的優劣,Prometheus 可 以說是目前監控領域最鋒利的“瑞士軍刀”了。
Prometheus 數據結構和類型

指標格式分為兩個部分:一份是指標名稱,另一個是指標標簽。
標簽可體現指標的維度特征,用於過濾和聚合。它通過標簽名(label name)和標簽值(label value) 這種鍵值對的形式,形成多種維度。
例如 , 對 於 指 標 http_request_total , 可 以 有 {status="200", method="POST"} 和 {status="200", method="GET"}這兩個標簽。在需要分別獲取 GET 和 POST 返回 200 的請求時,可分別使用上述兩種指標; 在需要獲取所有返回 200 的請求時,可以通過 http_request_total{status="200"}完成數據的聚合,非常便捷 和通用。
指標類型有四種:
l Counter(計數器):計數統計,累計多長或者累計多少次等。它的特點是只增不減,譬如 HTTP 訪問總 量
l Gauge(儀表盤):數據是一個瞬時值,如果當前內存用量,它隨着時間變化忽高忽低。
如果需要了解某個時間段內請求的響應時間,通常做法是使用平均響應時間,但這樣做無法體現數據的 長尾效應。例如,一個 HTTP 服務器的正常響應時間是 30ms,但有很少幾次請求耗時 3s,通過平均響應時 間很難甄別長尾效應,
l Histogram(直方圖):服務端分位,不同區間內樣本的個數,譬如班級成績,低於 60 分的 9 個,低於 70 分的 10 個,低於 80 分的 50 個
l Summary(摘要):客戶端分位,直接在客戶端通過分位情況,還是用班級成績舉例:0.8 分位的是 80 分,0.9 分為 85 分,0.99 分為的是 98 分
Prometheus 數據采集

Prometheus 通過 HTTP 接口的方式從各種客戶端獲取數據,這些客戶端必須符合 Prometheus 監控數 據格式,通常由兩種方式,一直是侵入式埋點監控,通過在客戶端集成如果 kubernetes API 直接通過引入 Prometheus go client,提供/metrics 接口查詢 kubernetes API 各種指標,另一種是通過 exporter 方式,在外 部將原來各種中間件的監控支持轉化為 Prometheus 的監控數據格式,如 redis exporter 將 reids 指標轉化為 Prometheus 能夠識別的 HTTP 請求。
Prometheus 並沒有采用 json 的數據格式,而是采用 text/plain 純文本的方式 ,這是它的特殊之處。 HTTP 返回 Header 和 Body 如上圖所示,指標前面兩行#是注釋,標識指標的含義和類型。指標和指標的值 通過空格分割,開發者通常不需要自己拼接這種個數的數據, Prometheus 提供了各種語言的 SDK 支持。

Prometheus 為了支持各種中間件以及第三方的監控提供了 exporter,大家可以把它理解成監控適配器, 將不同指標類型和格式的數據統一轉化為 Prometheus 能夠識別的指標類型。
譬如 Node exporter 主要通過讀取 linux 的/proc 以及/sys 目錄下的系統文件獲取操作系統運行狀態, reids exporter 通過 reids 命令行獲取指標,mysql exporter 通過讀取數據庫監控表獲取 mysql 的性能數據。 他們將這些異構的數據轉化為標准的 Prometheus 格式,並提供 HTTP 查詢接口。
Prometheus 數據存儲

Prometheus 提供了兩種數據持久化方式:一種是本地存儲,通過 Prometheus 自帶的 tsdb(時序數據 庫),將數據保存到本地磁盤,為了性能考慮,建議使用 SSD。但本地存儲的容量畢竟有限,建議不要保存 超過一個月的數據。Prometheus本地存儲經過多年改進,自Prometheus2.0 后提供的V3版本tsdb性能已 經非常高,可以支持單機每秒 1000w 個指標的收集。
Prometheus 本地數據存儲能力一直為大家詬病,但 Prometheus 本地存儲設計的初衷就是為了監控數 據的查詢,Facebook 發現 85%的查詢是針對 26 小時內的數據。所以 Prometheus 本地時序數據庫的設計 更多考慮的是高性能而非分布式大容量。
另一種是遠端存儲,適用於大量歷史監控數據的存儲和查詢。通過中間層的適配器的轉化,Prometheus 將數據保存到遠端存儲。適配器實現 Prometheus 存儲的 remote write 和 remote read 接口並把數據轉化為 遠端存儲支持的數據格式。目前,遠端存儲主要包括 OpenTSDB、InfluxDB、Elasticsearch、M3db 等,其中 M3db 是目前非常受歡迎的后端存儲。
prometheus查詢語言 PromQL

和關系型數據庫的 SQL 類型,Prometheus 也內置了數據查詢語言 PromQL,它提供對時間序列數據豐 富的查詢,聚合以及邏輯運算的能力。
數據運算包括了
+ (加法)
- (減法)
* (乘法)
/ (除法)
% (求余)
^ (冪運算)
聚合包括了
sum (求和)
min (最小值)
max (最大值)
avg (平均值)
stddev (標准差)
stdvar (標准差異)
count (計數)
count_values (對 value 進行計數)
bottomk (后 n 條)
topk (前 n 條)
quantile (分布統計)
如果需要獲取某個時刻的數據可以通過
curl 'http://Prometheus地址:9090/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z' 查詢監控數據,其中 query 參數就是一個 PromQL 表達式。
還支持范圍查詢 query_range,需要額外添加下面的參數:
start=: 起始時間。
end=: 結束時間。
step=: 查詢步長。
Prometheus 數據展現除了自帶的 webui 還可以通過 grafana,他們本質上都是通過 HTTP + PromQL 的 方式查詢 Prometheus 數據。

Prometheus 提供了 HTTP 查詢接口,當接收到請求參數后,通過 PromQL 引擎解析 PromQL,確定查 詢的數據序列和時間范圍,通過 tsdb 接口獲取對應數據塊(chunks),最后根據聚合函數處理監控數據並返回。
Prometheus 告警

如果監控數據達到告警閾值 Prometheus Server 會通過 HTTP 將告警發送到告警模塊 alertmanger。 Prometheus 告警配置也是通過 yaml 文件,核心是上面的 expr 表達式(告警規則)和查詢一樣也是一個 PromQL 表達式。 for 代表持續時間,如果在 for 時間內持續觸發 Prometheus 才發出告警
告警組件 alertmanger 地址是在 Prometheus 的配置文件中指定,告警經過 alertmanger 去重、抑制等 操作,最后執行告警動作,目前支持郵件、slack、微信和 webhook,如果是對接釘釘,便可以通過 webhook 方式觸發釘釘的客戶端發送告警
Prometheus 聯邦
為了擴展單個 Prometheus 的采集能力和存儲能力,Prometheus 引入了“聯邦”的概念。多個 Prometheus 節點組成兩層聯邦結構,如圖所示,上面一層是聯邦節點,負責定時從下面的 Prometheus 節點獲取數據並 匯總,部署多個聯邦節點是為了實現高可用以及數據匯聚存儲。下層的 Prometheus 節點又分別負責不同區 域的數據采集,在多機房的事件部署中,下層的每個 Prometheus 節點可以被部署到單獨的一個機房,充當 代理。

Prometheus 與 kubernetes
Prometheus 的流行和 kubernetes 是密不可分的,下面將介紹 Prometheus 和 kubernetes 結合的內容

Prometheus 配置告警對象有兩種方式,一種是通過靜態文件配置,另一種是動態發現機制,自動完成 數據采集。
Prometheus 動態發現目前已經支持 Kubernetes、etcd、Consul 等多種服務發現機制,動態發現機制可 以減少運維人員手動配置,在容器運行環境中尤為重要,容器集群通常在幾千甚至幾萬的規模,如果每個容 器都需要單獨配置監控項不僅需要大量工作量,而且容器經常變動,后續維護更是異常麻煩。
如果 kubernetes 環境的動態發現,Prometheus 通過 watch kubernetes api 動態獲取當前集群所有主機、 容器以及服務的變化情況。

通過自動發現機制,prometheus 可以動態獲取 Node 和 Pod 的變化,將 Node exporter 和 cAdvisor 加 入監控。
針對容器常用的監控指標包括:
CPU 利用率
rate(container_cpu_usage_seconds_total{
container_name="xxx" }[5m]
)
內存用量(使用內存減去緩存)
container_memory_usage_bytes{ container_name="xxx"
} -
container_memory_cache{ container_name="xxx"
}
網絡發送速率
rate(container_network_transmit_bytes_total{ pod_name="xxxx"
}[5m]
)
網絡接收速率
rate(container_network_receive_bytes_total{ pod_name="xxxx"
}[5m] )
prometheusOperator

和其他的 k8s 的 Operator 類似,Prometheus Operator 通過定義了下面四種 k8s 的 CRD 資源,從而
實現的操作 k8s 資源去管理 prometheus 的監控和告警的目標。
Prometheus:Prometheus Deployment 定義
ServiceMonitor:Prometheus 監控對象的定義
PrometheusRule:告警規則
Alertmanager:Alertmanager Deployment 定義
HPA

hpa 是 k8s 提供的水平伸縮服務,原生支持基於 CPU 利用率的擴縮容。如果用戶希望根據自定義指標 (如 QPS)擴容可以借助 k8s 的 custom metrics api。
k8s 資源擴展通常由兩種方式,一種是通過上面 Operator 使用的 CRD,另一種是通過 Aggregated API Server(未來可能會被 Kubebuilder 代替)。 custom-metrics-apiserver 便是通過 Aggregated API 擴展 k8s 的 custom metric 接口。
Hpa 查詢自定義監控數據的請求通過 kube-apiserver 代理到 custom-metrics-apiserver,並通過 prometheus-adapter 轉化為對 prometheus 數據查詢,從而實現自定義指標的擴縮容。
最后Prometheus 並非監控銀彈
首先,Prometheus 只針對性能和可用性監控,並不具備日志監控等功能,並不能通過 Prometheus 解 決所有監控問題。
其次,Prometheus 認為只有最近的監控數據才有查詢的需要,所有 Prometheus 本地存儲的設計初衷 只是保持短期(一個月)的數據,並非針對大量的歷史數據的存儲。如果需要報表之類的歷史數據,則建議 使用 Prometheus 的遠端存儲如 OpenTSDB、M3db 等。
Prometheus 還有一個小瑕疵是沒有定義單位,這里需要使用者自己去區分或者事先定義好所有監控數 據單位。
