本章節講解服務發現與Relabelling的機制與範例。
通過服務發現的方式,我們可以在不重啟Prometheus服務的情況下動態的發現需要監控的Target例項資訊。
如上圖所示,對於線上環境我們可能會劃分為:dev, stage, prod不同的叢集。每一個叢集執行多個主機節點,每個伺服器節點上執行一個Node Exporter例項。Node Exporter例項會自動註冊到Consul中,而Prometheus則根據Consul返回的Node Exporter例項資訊動態的維護Target列表,從而向這些Target輪詢監控資料。
然而,如果我們可能還需要:
- 按照不同的環境dev, stage, prod聚合監控資料?
- 對於研發團隊而言,我可能只關心dev環境的監控資料,如何處理?
- 如果為每一個團隊單獨搭建一個Prometheus Server。那麼如何讓不同團隊的Prometheus Server採集不同的環境監控資料?
面對以上這些場景下的需求時,我們實際上是希望Prometheus Server能夠按照某些規則(比如標籤)從服務發現註冊中心返回的Target例項中有選擇性的採集某些Exporter例項的監控資料。
接下來,我們實驗如何通過Prometheus強大的Relabel機制來實現以上這些具體的目標。
Prometheus的Relabeling機制
在Prometheus所有的Target例項中,都包含一些預設的Metadata標籤資訊。可以通過Prometheus UI的Targets頁面中檢視這些例項的Metadata標籤的內容:
預設情況下,當Prometheus載入Target例項完成後,這些Target時候都會包含一些預設的標籤:
__address__:當前Target例項的訪問地址<host>:<port>
__scheme__:採集目標服務訪問地址的HTTP Scheme,HTTP或者HTTPS
__metrics_path__:採集目標服務訪問地址的訪問路徑
__param_<name>:採集任務目標服務的中包含的請求引數
上面這些標籤將會告訴Prometheus如何從該Target例項中獲取監控資料。除了這些預設的標籤以外,我們還可以為Target新增自定義的標籤,例如,在“基於檔案的服務發現”小節中的示例中,我們通過JSON配置檔案,為Target例項新增了自定義標籤env,如下所示該標籤最終也會儲存到從該例項採集的樣本資料中:
node_cpu{cpu="cpu0",env="prod",instance="localhost:9100",job="node",mode="idle"}
一般來說,Target以__作為前置的標籤是在系統內部使用的,因此這些標籤不會被寫入到樣本資料中。不過這裡有一些例外,例如,我們會發現所有通過Prometheus採集的樣本資料中都會包含一個名為instance的標籤,該標籤的內容對應到Target例項的__address__。 這裡實際上是發生了一次標籤的重寫處理。
這種發生在採集樣本資料之前,對Target例項的標籤進行重寫的機制在Prometheus被稱為Relabeling。
Prometheus允許使用者在採集任務設定中通過relabel_configs來新增自定義的Relabeling過程。
使用replace/labelmap重寫標籤
Relabeling最基本的應用場景就是基於Target例項中包含的metadata標籤,動態的新增或者覆蓋標籤。例如,通過Consul動態發現的服務例項還會包含以下Metadata標籤資訊:
__meta_consul_address:consul地址
__meta_consul_dc:consul服務所在的資料中心
__meta_consulmetadata:服務的metadata
__meta_consul_node:consul服務node節點的資訊
__meta_consul_service_address:服務訪問地址
__meta_consul_service_id:服務ID
__meta_consul_service_port:服務埠
__meta_consul_service:服務名稱
__meta_consul_tags:服務包含的標籤資訊
在預設情況下,從Node Exporter例項採集上來的樣本資料如下所示:
node_cpu{cpu="cpu0",instance="localhost:9100",job="node",mode="idle"} 93970.8203125
我們希望能有一個額外的標籤dc可以表示該樣本所屬的資料中心:
node_cpu{cpu="cpu0",instance="localhost:9100",job="node",mode="idle", dc="dc1"} 93970.8203125
在每一個採集任務的配置中可以新增多個relabel_config配置,一個最簡單的relabel配置如下:
scrape_configs:
- job_name: node_exporter
consul_sd_configs:
- server: localhost:8500
services:
- node_exporter
relabel_configs:
- source_labels: ["__meta_consul_dc"]
target_label: "dc"
該採集任務通過Consul動態發現Node Exporter例項資訊作為監控採集目標。在上一小節中,我們知道通過Consul動態發現的監控Target都會包含一些額外的Metadata標籤,比如標籤__meta_consul_dc表明了當前例項所在的Consul資料中心,因此我們希望從這些例項中採集到的監控樣本中也可以包含這樣一個標籤,例如:
node_cpu{cpu="cpu0",dc="dc1",instance="172.21.0.6:9100",job="consul_sd",mode="guest"}
這樣可以方便的根據dc標籤的值,根據不同的資料中心聚合分析各自的資料。
在這個例子中,通過從Target例項中獲取__meta_consul_dc的值,並且重寫所有從該例項獲取的樣本中。
完整的relabel_config配置如下所示:
# The source labels select values from existing labels. Their content is concatenated
# using the configured separator and matched against the configured regular expression
# for the replace, keep, and drop actions.
[ source_labels: '[' <labelname> [, ...] ']' ]
# Separator placed between concatenated source label values.
[ separator: <string> | default = ; ]
# Label to which the resulting value is written in a replace action.
# It is mandatory for replace actions. Regex capture groups are available.
[ target_label: <labelname> ]
# Regular expression against which the extracted value is matched.
[ regex: <regex> | default = (.*) ]
# Modulus to take of the hash of the source label values.
[ modulus: <uint64> ]
# Replacement value against which a regex replace is performed if the
# regular expression matches. Regex capture groups are available.
[ replacement: <string> | default = $1 ]
# Action to perform based on regex matching.
[ action: <relabel_action> | default = replace ]
其中action定義了當前relabel_config對Metadata標籤的處理方式,預設的action行為為replace。 replace行為會根據regex的配置匹配source_labels標籤的值(多個source_label的值會按照separator進行拼接),並且將匹配到的值寫入到target_label當中,如果有多個匹配組,則可以使用${1}, ${2}確定寫入的內容。如果沒匹配到任何內容則不對target_label進行重新。
repalce操作允許使用者根據Target的Metadata標籤重寫或者寫入新的標籤鍵值對,在多環境的場景下,可以幫助使用者新增與環境相關的特徵維度,從而可以更好的對資料進行聚合。
除了使用replace以外,還可以定義action的配置為labelmap。與replace不同的是,labelmap會根據regex的定義去匹配Target例項所有標籤的名稱,並且以匹配到的內容為新的標籤名稱,其值作為新標籤的值。
例如,在監控Kubernetes下所有的主機節點時,為將這些節點上定義的標籤寫入到樣本中時,可以使用如下relabel_config配置:
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
而使用labelkeep或者labeldrop則可以對Target標籤進行過濾,僅保留符合過濾條件的標籤,例如:
relabel_configs:
- regex: label_should_drop_(.+)
action: labeldrop
該配置會使用regex匹配當前Target例項的所有標籤,並將符合regex規則的標籤從Target例項中移除。labelkeep正好相反,會移除那些不匹配regex定義的所有標籤。
使用keep/drop過濾Target例項
在上一部分中我們介紹了Prometheus的Relabeling機制,並且使用了replace/labelmap/labelkeep/labeldrop對標籤進行管理。而本節開頭還提到過第二個問題,使用中心化的服務發現註冊中心時,所有環境的Exporter例項都會註冊到該服務發現註冊中心中。而不同職能(開發、測試、運維)的人員可能只關心其中一部分的監控資料,他們可能各自部署的自己的Prometheus Server用於監控自己關心的指標資料,如果讓這些Prometheus Server採集所有環境中的所有Exporter資料顯然會存在大量的資源浪費。如何讓這些不同的Prometheus Server採集各自關心的內容?答案還是Relabeling,relabel_config的action除了預設的replace以外,還支援keep/drop行為。例如,如果我們只希望採集資料中心dc1中的Node Exporter例項的樣本資料,那麼可以使用如下配置:
scrape_configs:
- job_name: node_exporter
consul_sd_configs:
- server: localhost:8500
services:
- node_exporter
relabel_configs:
- source_labels: ["__meta_consul_dc"]
regex: "dc1"
action: keep
當action設定為keep時,Prometheus會丟棄source_labels的值中沒有匹配到regex正規表示式內容的Target例項,而當action設定為drop時,則會丟棄那些source_labels的值匹配到regex正規表示式內容的Target例項。可以簡單理解為keep用於選擇,而drop用於排除。
使用hashmod計算source_labels的Hash值
當relabel_config設定為hashmod時,Prometheus會根據modulus的值作為係數,計算source_labels值的hash值。例如:
scrape_configs
- job_name: 'file_ds'
relabel_configs:
- source_labels: [__address__]
modulus: 4
target_label: tmp_hash
action: hashmod
file_sd_configs:
- files:
- targets.json
根據當前Target例項__address__的值以4作為係數,這樣每個Target例項都會包含一個新的標籤tmp_hash,並且該值的範圍在1~4之間,檢視Target例項的標籤資訊,可以看到如下的結果,每一個Target例項都包含了一個新的tmp_hash值:
利用Hashmod的能力在Target例項級別實現對採集任務的功能分割槽的:
scrape_configs:
- job_name: some_job
relabel_configs:
- source_labels: [__address__]
modulus: 4
target_label: __tmp_hash
action: hashmod
- source_labels: [__tmp_hash]
regex: ^1$
action: keep
這裡需要注意的是,如果relabel的操作只是為了產生一個臨時變數,以作為下一個relabel操作的輸入,那麼我們可以使用 __tmp
作為標籤名的字首,通過該字首定義的標籤就不會寫入到Target或者採集到的樣本的標籤中。