全面学习Prometheus
Prometheus是繼Kubernetes后第2個正式加入CNCF基金會的項目,容器和云原生領域事實的監控標準解決方案。在這次分享將從Prometheus的基礎說起,學習和了解Prometheus強大的數據處理能力,了解如何使用Prometheus進行白盒和黑盒監控,以及Prometheus在規?;O控下的解決方案等。最后將從0開始構建完整的Kubernetes監控架構。
監控的目標
?
?
在《SRE:Google運維解密》一書中指出,監控系統需要能夠有效的支持白盒監控和黑盒監控。通過白盒能夠了解其內部的實際運行狀態,通過對監控指標的觀察能夠預判可能出現的問題,從而對潛在的不確定因素進行優化。而黑盒監控,常見的如HTTP探針,TCP探針等,可以在系統或者服務在發生故障時能夠快速通知相關的人員進行處理。通過建立完善的監控體系,從而達到以下目的:
?
-
長期趨勢分析:通過對監控樣本數據的持續收集和統計,對監控指標進行長期趨勢分析。例如,通過對磁盤空間增長率的判斷,我們可以提前預測在未來什么時間節點上需要對資源進行擴容。
-
對照分析:兩個版本的系統運行資源使用情況的差異如何?在不同容量情況下系統的并發和負載變化如何?通過監控能夠方便的對系統進行跟蹤和比較。
-
告警:當系統出現或者即將出現故障時,監控系統需要迅速反應并通知管理員,從而能夠對問題進行快速的處理或者提前預防問題的發生,避免出現對業務的影響。
-
故障分析與定位:當問題發生后,需要對問題進行調查和處理。通過對不同監控指標以及歷史數據的分析,能夠找到并解決根源問題。
-
數據可視化:通過可視化儀表盤能夠直接獲取系統的運行狀態、資源使用情況、以及服務運行狀態等直觀的信息。
而對于上一代監控系統而言,在使用過程中往往會面臨以下問題:
?
?
?
-
與業務脫離的監控:監控系統獲取到的監控指標與業務本身也是一種分離的關系。好比客戶可能關注的是服務的可用性、服務的SLA等級,而監控系統卻只能根據系統負載去產生告警;
-
運維管理難度大:Nagios這一類監控系統本身運維管理難度就比較大,需要有專業的人員進行安裝,配置和管理,而且過程并不簡單;
-
可擴展性低: 監控系統自身難以擴展,以適應監控規模的變化;
-
問題定位難度大:當問題產生之后(比如主機負載異常增加)對于用戶而言,他們看到的依然是一個黑盒,他們無法了解主機上服務真正的運行情況,因此當故障發生后,這些告警信息并不能有效的支持用戶對于故障根源問題的分析和定位。
在上述需求中,我們可以提取出以下對于一個完善的監控解決方案的幾個關鍵詞:數據分析、趨勢預測、告警、故障定位、可視化。
除此以外,當前越來越多的產品公司遷移到云或者容器的情況下,對于監控解決方案而言還需要另外一個關鍵詞:云原生。
?
?
主要內容
?
?
今天將從以下幾個方面來介紹下一代監控解決方案Prometheus是如何解決以上問題的:
?
-
初識Prometheus
-
讓數據會說話:PromQL與可視化
-
Alertmanager與告警處理;
-
白盒與黑盒監控
-
規?;O控解決方案
-
從0開始監控Kubernetes集群
?
初識Prometheus
?
?
Prometheus受啟發于Google的Brogmon監控系統(相似的Kubernetes是從Google的Brog系統演變而來),從2012年開始由前Google工程師在Soundcloud以開源軟件的形式進行研發,并且于2015年早期對外發布早期版本。2016年5月繼Kubernetes之后成為第二個正式加入CNCF基金會的項目,同年6月正式發布1.0版本。2017年底發布了基于全新存儲層的2.0版本,能更好地與容器平臺、云平臺配合。
從https://prometheus.io/download/獲取最新的node exporter版本的二進制包后直接運行即可:
$ node_exporter
INFO[0000] Starting node_exporter (version=0.15.2, branch=HEAD, revision=98bc64930d34878b84a0f87dfe6e1a6da61e532d) ?source="
node_exporter.go:43"
INFO[0000] Enabled collectors: ? ? ? ? ? ? ? ? ? ? ? ? ??source="node_exporter.go:50"
INFO[0000] ?- time ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??source="node_exporter.go:52"
INFO[0000] ?- meminfo ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?source="node_exporter.go:52"
INFO[0000] ?- textfile ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??source="node_exporter.go:52"
INFO[0000] ?- filesystem ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??source="node_exporter.go:52"
INFO[0000] ?- netdev ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??source="node_exporter.go:52"
INFO[0000] ?- cpu ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?source="node_exporter.go:52"
INFO[0000] ?- diskstats ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?source="node_exporter.go:52"
INFO[0000] ?- loadavg ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?source="node_exporter.go:52"
INFO[0000] Listening on :9100 ? ? ? ? ? ? ? ? ? ? ? ? ? ?source="node_exporter.go:76"
訪問http://localhost:9100/metrics,可以看到Node Exporter獲取到的當前主機的所有監控數據,如下所示:
?
?
每一個監控指標之前都會有一段類似于如下形式的信息:
?
?
# HELP node_cpu Seconds the cpus spent in each mode. # TYPE node_cpu counter node_cpu{cpu="cpu0",mode="idle"} 362812.7890625 # HELP node_load1 1m load average. # TYPE node_load1 gauge node_load1 3.0703125
Node Exporter通過指標名稱和標簽返回了當前主機的監控樣本數據。
從https://prometheus.io/download/找到最新版本的Prometheus Sevrer軟件包,目前這里采用最新的穩定版本2.x.x。
創建配置文件prometheus.yml,如下所示:
?
?
global: scrape_interval: ? ? 15s scrape_configs:- job_name: 'node'static_configs:- targets: ['localhost:9100']- job_name: 'prometheus'static_configs:- targets: ['localhost:9090']
并啟動Prometheus:
?
?
$ prometheus --config.file=prometheus.yml --storage.tsdb.path=/data/prometheus ...... level=info ts=2018-03-11T13:38:06.317645234Z caller=main.go:486 msg="Server is ready to receive web requests." level=info ts=2018-03-11T13:38:06.317679086Z caller=manager.go:59 component="scrape manager" msg="Starting scrape manager..."
訪問http://localhost:9090,進入到Prometheus Server。通過指標名稱node_load1,可以找到當前采集到的主機負載的樣本數據。
?
?
?
在上述的例子中,我們主要使用到了Node Exporter實例去獲取主機的監控數據,一個運行的Node Exporter實例稱為一個Target。Promthues周期性的從Node Exporter實例中獲取監控樣本,并保存到Promtheus基于本地磁盤實現的時間序列數據庫中。
?
?
?
在實際的應用場景中Exporter可以分為兩類:
?
?
-
獨立運行的:類似于Node Exporter這種,它并不直接產生數據,它只負責從數據源中獲取數據,并以Prometheus支持的格式返回監控數據即可。
-
集成到應用中的:為了能夠更好的監控系統的內部運行狀態,有些開源項目如Kubernetes,ETCD等直接在內部集成了對Prometheus的支持,通過內部埋點的形式,可以更好的監控服務的內部運行狀態。
?
讓數據說話:PromQL與數據可視化
?
理解時間序列
在Node Exporter的/metrics接口中返回的每一行監控數據,在Prometheus下稱為一個樣本。采集到的樣本由以下三部分組成:
?
-
指標(metric):指標和一組描述當前樣本特征的labelsets唯一標識;
-
時間戳(timestamp):一個精確到毫秒的時間戳,一般由采集時間決定;
-
樣本值(value): 一個folat64的浮點型數據表示當前樣本的值。
Prometheus會將所有采集到的樣本數據以時間序列(time-series)的方式保存在內存數據庫中,并且定時保存到硬盤上。每條time-series通過指標名稱(metrics name)和一組標簽集(labelset)命名。如下所示,可以將time-series理解為一個以時間為X軸的二維矩陣:
?
?
?
這種多維度的數據存儲方式,可以衍生出很多不同的玩法。 比如,如果數據來自不同的數據中心,那么我們可以在樣本中添加標簽來區分來自不同數據中心的監控樣本,例如:
?
?
node_cpu{cpu="cpu0",mode="idle", dc="dc0"}
從內部實現上來看Prometheus中所有存儲的監控樣本數據沒有任何差異,均是一組標簽,時間戳以及樣本值。
從存儲上來講所有的監控指標metric都是相同的,但是在不同的場景下這些metric又有一些細微的差異。 例如,在Node Exporter返回的樣本中指標node_load1反應的是當前系統的負載狀態,隨著時間的變化這個指標返回的樣本數據是在不斷變化的。而指標node_cpu所獲取到的樣本數據卻不同,它是一個持續增大的值,因為其反應的是CPU的累積使用時間,從理論上講只要系統不關機,這個值是會無限變大的。
為了能夠幫助用戶理解和區分這些不同監控指標之間的差異,Prometheus定義了4中不同的指標類型(metric type):Counter(計數器)、Gauge(儀表盤)、Histogram(直方圖)、Summary(摘要)。
Counter:只增不減的計數器
Counter是一個簡單但有強大的工具,例如我們可以在應用程序中記錄某些事件發生的次數,通過以時序的形式存儲這些數據,我們可以輕松的了解該事件產生速率的變化。PromQL內置的聚合操作和函數可以用戶對這些數據進行進一步的分析:
例如,通過rate()函數獲取HTTP請求量的增長率:
?
?
rate(http_requests_total[5m])?
Gauge:可增可減的儀表盤
與Counter不同,Gauge類型的指標側重于反應系統的當前狀態。因此這類指標的樣本數據可增可減。常見指標如:node_memory_MemFree(主機當前空閑的內容大小)、node_memory_MemAvailable(可用內存大小)都是Gauge類型的監控指標。
通過Gauge指標,用戶可以直接查看系統的當前狀態:
?
node_memory_MemFree
對于Gauge類型的監控指標,通過PromQL內置函數delta()可以獲取樣本在一段時間返回內的變化情況。例如,計算CPU溫度在兩個小時內的差異:
?
?
delta(cpu_temp_celsius{host="zeus"}[2h])
還可以使用deriv()計算樣本的線性回歸模型,甚至是直接使用predict_linear()對數據的變化趨勢進行預測。例如,預測系統磁盤空間在4個小時之后的剩余情況:
?
?
predict_linear(node_filesystem_free{job="node"}[1h], 4 * 3600)?
使用Histogram和Summary分析數據分布情況
在大多數情況下人們都傾向于使用某些量化指標的平均值,例如CPU的平均使用率、頁面的平均響應時間。這種方式的問題很明顯,以系統API調用的平均響應時間為例:如果大多數API請求都維持在100ms的響應時間范圍內,而個別請求的響應時間需要5s,那么就會導致某些WEB頁面的響應時間落到中位數的情況,而這種現象被稱為長尾問題。
為了區分是平均的慢還是長尾的慢,最簡單的方式就是按照請求延遲的范圍進行分組。例如,統計延遲在010ms之間的請求數有多少而1020ms之間的請求數又有多少。通過這種方式可以快速分析系統慢的原因。Histogram和Summary都是為了能夠解決這樣問題的存在,通過Histogram和Summary類型的監控指標,我們可以快速了解監控樣本的分布情況。
例如,指標prometheus_tsdb_wal_fsync_duration_seconds的指標類型為Summary。 它記錄了Prometheus Server中wal_fsync處理的處理時間,通過訪問Prometheus Server的/metrics地址,可以獲取到以下監控樣本數據:
?
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.5"} 0.012352463 prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.9"} 0.014458005 prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.99"} 0.017316173 prometheus_tsdb_wal_fsync_duration_seconds_sum 2.888716127000002 prometheus_tsdb_wal_fsync_duration_seconds_count 216
從上面的樣本中可以得知當前Promtheus Server進行wal_fsync操作的總次數為216次,耗時2.888716127000002s。其中中位數(quantile=0.5)的耗時為0.012352463,9分位數(quantile=0.9)的耗時為0.014458005s。
?
?
?
Prometheus對于數據的存儲方式就意味著,不同的標簽就代表著不同的特征維度。用戶可以通過這些特征維度對查詢,過濾和聚合樣本數據。
例如,通過node_load1,查詢出當前時間序列數據庫中所有名為node_load1的時間序列:
?
?
node_load1?
?
?
如果找到滿足某些特征維度的時間序列,則可以使用標簽進行過濾:
?
?
node_load1{instance="localhost:9100"}?
?
?
通過以標簽為核心的特征維度,用戶可以對時間序列進行有效的查詢和過濾,當然如果僅僅是這樣,顯然還不夠強大,Prometheus提供的豐富的聚合操作以及內置函數,可以通過PromQL輕松回答以下問題:
當前系統的CPU使用率?
?
?
avg(irate(node_cpu{mode!="idle"}[2m])) without (cpu, mode)?
?
?
CPU占用率前5位的主機有哪些?
?
?
topk(5, avg(irate(node_cpu{mode!="idle"}[2m])) without (cpu, mode))?
?
?
預測在4小時候后,磁盤空間占用大致會是什么情況?
?
?
predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600)?
?
?
其中avg(),topk()等都是PromQL內置的聚合操作,irate(),predict_linear()是PromQL內置的函數,irate()函數可以計算一段時間返回內時間序列中所有樣本的單位時間變化率。predict_linear函數內部則通過簡單線性回歸的方式預測數據的變化趨勢。
以Grafana為例,在Grafana中可以通過將Promtheus作為數據源添加到系統中,后再使用PromQL進行數據可視化。在Grafana v5.1中提供了對Promtheus 4種監控類型的完整支持,可以通過Graph Panel,Singlestat Panel,Heatmap Panel對監控指標數據進行可視化。
使用Graph Panel可視化主機CPU使用率變化情況:
?
?
?
使用Sigle Panel顯示當前狀態:
?
?
?
使用Heatmap Panel顯示數據分布情況:
?
?
?
Prometheus通過PromQL提供了強大的數據查詢和處理能力。對于外部系統而言可以通過Prometheus提供的API接口,使用PromQL查詢相關的樣本數據,從而實現如數據可視化等自定義需求,PromQL是Prometheus對內,對外功能實現的主要接口。
?
?
?
關于Grafana與Promthues的使用案例詳情可以參考:https://github.com/yunlzheng/prometheus-book/blob/master/grafana/README.md。
告警處理中心:Alertmanager
?
?
?
告警在Prometheus的架構中被劃分成兩個獨立的部分:告警產生和告警處理。
在Prometheus可以通過文件的形式定義告警規則,Promthues會周期性的計算告警規則中的PromQL表達式判斷是否達到告警觸發條件,如果滿足,則在Prometheus內部產生一條告警。
告警規則文件,通過YAML格式進行定義:
?
yaml groups: - name: hostStatsAlertrules:- alert: hostCpuUsageAlertexpr: sum(avg without (cpu)(irate(node_cpu{mode!='idle'}[5m]))) by (instance) > 0.85for: 1mlabels:severity: pageannotations:summary: "Instance {{ $labels.instance }} CPU usgae high"description: "{{ $labels.instance }} CPU usage above 85% (current value: {{ $value }})"
這里定義當主機的CPU使用率大于85%時,產生告警。告警狀態將在Promethues的UI中進行展示。
?
?
?
到目前為止Promethues通過周期性的校驗告警規則文件,從而在內部處罰告警。
?
?
?
而后續的告警處理則由Alertmanager進行統一處理。Alertmanager作為一個獨立的組件,負責接收并處理來自Prometheus Server(也可以是其它的客戶端程序)的告警信息。Alertmanager可以對這些告警信息進行進一步的處理,比如消除重復的告警信息,對告警信息進行分組并且路由到正確的接受方,Alertmanager內置了對郵件,Slack等通知方式的支持,同時還支持與Webhook的通知集成,以支持更多的可能性,例如可以通過Webhook與釘釘或者企業微信進行集成。同時AlertManager還提供了靜默和告警抑制機制來對告警通知行為進行優化。
?
?
?
關于Alertmanager的詳細內容可以參考:https://github.com/yunlzheng/prometheus-book/blob/master/alert/README.md。
Prometheus作為是一個開源的完整監控解決方案,其對傳統監控系統的check-alert模型進行了徹底的顛覆,形成了基于中央化的規則計算、統一分析和告警的新模型。
?
使用Blackbox進行黑盒監控
?
?
在前面的部分中,我們主要介紹了Node Exporter的使用,對于這類Exporter而言,它們主要監控服務或者基礎設施的內部使用狀態,即白盒監控。通過對監控指標的觀察能夠預判可能出現的問題,從而對潛在的不確定因素進行優化。
而從完整的監控邏輯的角度,除了大量的應用白盒監控以外,還應該添加適當的黑盒監控。黑盒監控即以用戶的身份測試服務的外部可見性,常見的黑盒監控包括HTTP探針、TCP探針等用于檢測站點或者服務的可訪問性,以及訪問效率等。
黑盒監控相較于白盒監控最大的不同在于黑盒監控是以故障為導向當故障發生時,黑盒監控能快速發現故障,而白盒監控則側重于主動發現或者預測潛在的問題。一個完善的監控目標是要能夠從白盒的角度發現潛在問題,能夠在黑盒的角度快速發現已經發生的問題。
?
這里類比敏捷中著名的敏捷測試金字塔,對于完整的監控而言,我們需要大量的白盒監控,用于監控服務的內部運行狀態,從而可以支持有效的故障分析。 同時也需要部分的黑盒監控,用于檢測主要服務是否發生故障。
Blackbox Exporter是Prometheus社區提供的官方黑盒監控解決方案,其允許用戶通過:HTTP、HTTPS、DNS、TCP以及ICMP的方式對網絡進行探測。用戶可以直接使用go get命令獲取Blackbox Exporter源碼并生成本地可執行文件。
Blackbox Exporter運行時,需要指定探針配置文件,例如blackbox.yml:
?
modules:http_2xx:prober: httphttp:method: GEThttp_post_2xx:prober: httphttp:method: POST
啟動blackbox_exporter即可啟動一個探針服務:
?
?
blackbox_exporter --config.file=/etc/prometheus/blackbox.yml
啟動后,通過訪問http://127.0.0.1:9115/probe?module=http_2xx&target=baidu.com可以獲得blackbox對baidu.com站點探測的結果。
?
?
probe_http_duration_seconds{phase="connect"} 0.055551141 probe_http_duration_seconds{phase="processing"} 0.049736019 probe_http_duration_seconds{phase="resolve"} 0.011633673 probe_http_duration_seconds{phase="tls"} 0 probe_http_duration_seconds{phase="transfer"} 3.8919e-05 # HELP probe_http_redirects The number of redirects # TYPE probe_http_redirects gauge probe_http_redirects 0 # HELP probe_http_ssl Indicates if SSL was used for the final redirect # TYPE probe_http_ssl gauge probe_http_ssl 0 # HELP probe_http_status_code Response HTTP status code # TYPE probe_http_status_code gauge probe_http_status_code 200 # HELP probe_http_version Returns the version of HTTP of the probe response # TYPE probe_http_version gauge probe_http_version 1.1 # HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6 # TYPE probe_ip_protocol gauge probe_ip_protocol 4 # HELP probe_success Displays whether or not the probe was a success # TYPE probe_success gauge probe_success 1
在Prometheus中可以通過添加響應的監控采集任務,即可獲取對相應站點的探測結構樣本數據:
?
?
?- job_name: 'blackbox'metrics_path: /probeparams:module: [http_2xx]static_configs:- targets:- http://prometheus.io ? ?# Target to probe with http.- https://prometheus.io ? # Target to probe with https.- http://example.com:8080 # Target to probe with http on port 8080.relabel_configs:- source_labels: [__address__]target_label: __param_target- source_labels: [__param_target]target_label: instance- target_label: __address__replacement: 127.0.0.1:9115?
規?;O控解決方案
?
?
到目前為止,我們了解了Prometheus的基礎架構和主要工作機制,如下所示:
?
?
Prometheus周期性的從Target中獲取監控數據并保存到本地的time-series中,并且通過PromQL對外暴露數據查詢接口。 內部周期性的檢查告警規則文件,產生告警并有Alertmanager對告警進行后續處理。
那么問題來了,這里Prometheus是單點,Alertmanager也是單點。 這樣的結構能否支持大規模的監控量?
對于Prometheus而言,要想完全理解其高可用部署模式,首先我們需要理解Prometheus的數據存儲機制。
?
?
?
如上所示,Prometheus 2.x采用自定義的存儲格式將樣本數據保存在本地磁盤當中。按照兩個小時為一個時間窗口,將兩小時內產生的數據存儲在一個塊(Block)中,每一個塊中包含該時間窗口內的所有樣本數據(chunks),元數據文件(meta.json)以及索引文件(index)。
當前時間窗口內正在收集的樣本數據,Prometheus則會直接將數據保存在內存當中。為了確保此期間如果Prometheus發生崩潰或者重啟時能夠恢復數據,Prometheus啟動時會從寫入日志(WAL)進行重播,從而恢復數據。此期間如果通過API刪除時間序列,刪除記錄也會保存在單獨的邏輯文件當中(tombstone)。
?
?
?
通過時間窗口的形式保存所有的樣本數據,可以明顯提高Prometheus的查詢效率,當查詢一段時間范圍內的所有樣本數據時,只需要簡單的從落在該范圍內的塊中查詢數據即可。而對于歷史數據的刪除,也變得非常簡單,只要刪除相應塊所在的目錄即可。
對于單節點的Prometheus而言,這種基于本地文件系統的存儲方式能夠讓其支持數以百萬的監控指標,每秒處理數十萬的數據點。為了保持自身管理和部署的簡單性,Prometheus放棄了管理HA的復雜度。
因此首先,對于這種存儲方式而言,我們需要明確的幾點:
?
?
Prometheus本身不適用于持久化存儲長期的歷史數據,默認情況下Prometheus只保留15天的數據。
本地存儲也意味著Prometheus自身無法進行有效的彈性伸縮。
而當監控規模變得巨大的時候,對于單臺Prometheus而言,其主要挑戰包括以下幾點:
?
?
服務的可用性,如何確保Prometheus不會發生單點故障;
監控規模變大的意味著,Prometheus的采集Job的數量也會變大(寫)操作會變得非常消耗資源;
同時也意味著大量的數據存儲的需求。
?
?
簡單HA:服務可用性
由于Prometheus的Pull機制的設計,為了確保Prometheus服務的可用性,用戶只需要部署多套Prometheus Server實例,并且采集相同的Exporter目標即可。
?
?
基本的HA模式只能確保Prometheus服務的可用性問題,但是不解決Prometheus Server之間的數據一致性問題以及持久化問題(數據丟失后無法恢復),也無法進行動態的擴展。因此這種部署方式適合監控規模不大,Promthues Server也不會頻繁發生遷移的情況,并且只需要保存短周期監控數據的場景。
基本HA + 遠程存儲
在基本HA模式的基礎上通過添加Remote Storage存儲支持,將監控數據保存在第三方存儲服務上。
?
?
?
當Prometheus在獲取監控樣本并保存到本地的同時,會將監控數據發送到Remote Storage Adaptor,由Adaptor完成對第三方存儲的格式轉換以及數據持久化。
當Prometheus查詢數據的時候,也會從Remote Storage Adaptor獲取數據,合并本地數據后進行數據查詢。
在解決了Prometheus服務可用性的基礎上,同時確保了數據的持久化,當Prometheus Server發生宕機或者數據丟失的情況下,可以快速的恢復。 同時Prometheus Server可能很好的進行遷移。因此,該方案適用于用戶監控規模不大,但是希望能夠將監控數據持久化,同時能夠確保Prometheus Server的可遷移性的場景。
基本HA + 遠程存儲 + 聯邦集群
當單臺Prometheus Server無法處理大量的采集任務時,用戶可以考慮基于Prometheus聯邦集群的方式將監控采集任務劃分到不同的Prometheus實例當中即在任務級別功能分區。
?
?
這種部署方式一般適用于兩種場景:
場景一:單數據中心 + 大量的采集任務
這種場景下Prometheus的性能瓶頸主要在于大量的采集任務,因此用戶需要利用Prometheus聯邦集群的特性,將不同類型的采集任務劃分到不同的Prometheus子服務中,從而實現功能分區。例如一個Prometheus Server負責采集基礎設施相關的監控指標,另外一個Prometheus Server負責采集應用監控指標。再有上層Prometheus Server實現對數據的匯聚。
場景二:多數據中心
這種模式也適合與多數據中心的情況,當Prometheus Server無法直接與數據中心中的Exporter進行通訊時,在每一個數據中部署一個單獨的Prometheus Server負責當前數據中心的采集任務是一個不錯的方式。這樣可以避免用戶進行大量的網絡配置,只需要確保主Prometheus Server實例能夠與當前數據中心的Prometheus Server通訊即可。 中心Prometheus Server負責實現對多數據中心數據的聚合。
高可用方案選擇
上面的部分,根據不同的場景演示了3種不同的高可用部署方案。當然對于Prometheus部署方案需要用戶根據監控規模以及自身的需求進行動態調整,下表展示了Prometheus和高可用有關3個選項各自解決的問題,用戶可以根據自己的需求靈活選擇。
?
| 選項/需求 | 服務可用性 | 數據持久化 | 水平擴展 |
| 主備HA | √ | × | × |
| 遠程存儲 | × | √ | × |
| 聯邦集群 | × | × | √ |
對于Alertmanager而言,Alertmanager集群之間使用Gossip協議相互傳遞狀態,因此對于Prometheus而言,只需要關聯多個Alertmanager實例即可,關于Alertmanager集群的詳細詳細可以參考:https://github.com/yunlzheng/prometheus-book/blob/master/ha/alertmanager-high-availability.md
?
?
?
?
服務發現與云原生:以Kubernetes為例
?
?
對于諸如Kubernetes這類容器或者云環境,對于Prometheus而言,需要解決的一個重要問題就是如何動態的發現部署在Kubernetes環境下的需要監控的所有目標。
?
?
對于Kubernetes而言,如上圖所示,我們可以把當中所有的資源分為幾類:
?
?
基礎設施層(Node):集群節點,為整個集群和應用提供運行時資源
容器基礎設施(Container):為應用提供運行時環境
用戶應用(Pod):Pod中會包含一組容器,它們一起工作,并且對外提供一個(或者一組)功能
內部服務負載均衡(Service):在集群內,通過Service在集群暴露應用功能,集群內應用和應用之間訪問時提供內部的負載均衡
外部訪問入口(Ingress):通過Ingress提供集群外的訪問入口,從而可以使外部客戶端能夠訪問到部署在Kubernetes集群內的服務
?
?
因此,在不考慮Kubernetes自身組件的情況下,如果要構建一個完整的監控體系,我們應該考慮,以下5個方面:
?
集群節點狀態監控:從集群中各節點的kubelet服務獲取節點的基本運行狀態;
集群節點資源用量監控:通過Daemonset的形式在集群中各個節點部署Node Exporter采集節點的資源使用情況;
節點中運行的容器監控:通過各個節點中kubelet內置的cAdvisor中獲取個節點中所有容器的運行狀態和資源使用情況;
從黑盒監控的角度在集群中部署Blackbox Exporter探針服務,檢測Service和Ingress的可用性;
如果在集群中部署的應用程序本身內置了對Prometheus的監控支持,那么我們還應該找到相應的Pod實例,并從該Pod實例中獲取其內部運行狀態的監控指標。
?
?
而對于Prometheus這一類基于Pull模式的監控系統,顯然也無法繼續使用的static_configs的方式靜態的定義監控目標。而對于Prometheus而言其解決方案就是引入一個中間的代理人(服務注冊中心),這個代理人掌握著當前所有監控目標的訪問信息,Prometheus只需要向這個代理人詢問有哪些監控目標控即可, 這種模式被稱為服務發現。
?
?
Prometheus提供了對Kubernetes的完整支持,通過與Kubernetes的API進行交互,Prometheus可以自動的發現Kubernetes中所有的Node、Service、Pod、Endpoints以及Ingress資源的相關信息。
通過服務發現找到所有的監控目標后,并通過Prometheus的Relabling機制對這些資源進行過濾,metrics地址替換等操作,從而實現對各類資源的全自動化監控。
例如,通過以下流程任務配置,可以自動從集群節點的kubelet服務中內置的cAdvisor中獲取容器的監控數據:
?
?
- job_name: 'kubernetes-cadvisor'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- action: labelmapregex: __meta_kubernetes_node_label_(.+)- target_label: __address__replacement: kubernetes.default.svc:443- source_labels: [__meta_kubernetes_node_name]regex: (.+)target_label: __metrics_path__replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
由或者是通過集群中部署的blackbox exporter對服務進行網絡探測:
?
?
- job_name: 'kubernetes-services'metrics_path: /probeparams:module: [http_2xx]kubernetes_sd_configs:- role: servicerelabel_configs:- source_labels: [__address__]target_label: __param_target- target_label: __address__replacement: blackbox-exporter.example.com:9115- source_labels: [__param_target]target_label: instance- action: labelmapregex: __meta_kubernetes_service_label_(.+)- source_labels: [__meta_kubernetes_namespace]target_label: kubernetes_namespace- source_labels: [__meta_kubernetes_service_name]target_label: kubernetes_name?
小結
?
?
由于線上分享的形式無法事無巨細的分享關于Prometheus的所有內容,但是希望大家能夠通過今天的分享能夠對Prometheus有更好的理解。
這里我也將關于Prometheus的相關實踐通過電子書的形式進行了整理:https://github.com/yunlzheng/prometheus-book,希望能對大家學習和使用Prometheus起到一定的幫助作用,當然關于Prometheus的相關問題,也可以通過Github Issue來相互交流。
Q&A
?
Q:Prometheus的數據能否自動同步到InfluxDB中?A:可以,通過remote_write可以實現,可以參考:https://github.com/prometheus/prometheus/tree/master/documentation/examples/remote_storage/remote_storage_adapter。Prometheus通過將采集到的數據發送到Adaptor,再由Adaptor完成對數據格式的轉換存儲到InfluxDB即可。
Q:Prometheus一個Server最多能運行多少個Job?A:這個沒有做具體的試驗,不過需要注意的是Job任務量(寫操作),會直接影響Prometheus的性能,最好使用federation實現讀寫分離。
Q:請問告警由Grafana實現比較好,還是Alertmanager,常用的metric列表有沒有匯總的清單鏈接分享下,歷史數據默認保留時間如何設置?A:Grafana自身是支持多數據源,Promethues只是其中之一。 如果只使用Promthues那用Alertmanager就好了,里面實現了很多告警去重和靜默的機制,不然收到郵件轟炸也不太好。 如果需要基于Grafana中用到的多種數據源做告警的話,那就用Grafana。
Q:Prometheus監控數據推薦存哪里是InfluxDB,或者ES里面,InfluxDB單節點免費,多節的似乎收費的?A:默認情況下,直接是保存到本地的。如果要把數據持久化到第三方存儲只要實現remote_write接口就可以。理論上可以對接任意的第三方存儲。 InfluxDB只是官方提供的一個示例之一。
Q:請問“再有上層Prometheus Server實現對數據的匯聚。”是表示該Prometheus會對下層Prometheus進行數據收集嗎?使用什么接口?A:請參考Prometheus Fedreation(https://prometheus.io/docs/prometheus/latest/federation/),這里主要是指由一部分Prometheus實例負責采集任務,然后Global的Prometheus匯集數據,并對外提供查詢接口。 減少Global Prometheus的壓力。
Q:兩臺Prometheus server 可否用Keepalived?A:直接負載均衡就可以了,對于Prometheus而言,實例之間本身并沒有任何的直接關系。
Q:用Prometheus監控業務的API接口,有什么好的方法嗎,能監控數據庫的慢查詢嗎?A:在系統中集成client_library,直接在代碼中埋點??梢詤⒖歼@個例子:https://github.com/yunlzheng/prometheus-book/blob/master/exporter/custom_app_support_prometheus.md。
總結
以上是生活随笔為你收集整理的全面学习Prometheus的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GO select用法详解
- 下一篇: Go语言入门——dep入门