轉載自:https://cloud.tencent.com/developer/article/1536967
1、Consul 介紹
Consul 是基於 GO 語言開發的開源工具,主要面向分布式,服務化的系統提供服務注冊、服務發現和配置管理的功能。Consul 提供服務注冊/發現、健康檢查、Key/Value存儲、多數據中心和分布式一致性保證等功能。之前我們通過 Prometheus 實現監控,當新增一個 Target 時,需要變更服務器上的配置文件,即使使用 file_sd_configs 配置,也需要登錄服務器修改對應 Json 文件,會非常麻煩。不過 Prometheus 官方支持多種自動服務發現的類型,其中就支持 Consul。
2、環境、軟件准備
本次演示環境,我是在虛擬機上安裝 Linux 系統來執行操作,以下是安裝的軟件及版本:
- Oracle VirtualBox: 5.1.20 r114628 (Qt5.6.2)
- System: CentOS Linux release 7.3.1611 (Core)
- Docker: 18.06.1-ce
- Prometheus: v2.11.1
- Consul: 1.6.1
注意:這里為了方便啟動 Prometheus、Consul服務,我使用 Docker 方式啟動,所以本機需要安裝好 Docker 環境,這里忽略 Docker 的安裝過程。其中 Prometheus 安裝配置,可以參照之前文章 Prometheus 監控報警系統 AlertManager 之郵件告警,這里着重介紹一下如何啟動並配置 Consul 並配置 Prometheus 基於 Consul 實現自動服務發現。
3、Consul 安裝配置
Consul 安裝很方便,官網 提供各個系統版本二進制安裝包,解壓安裝即可,同時也可以通過 Docker 來快速安裝。
3.1、源碼安裝
以 Linux 系統為例,源碼安裝並以開發模式啟動一個單節點,下載最新版二進制安裝包,解壓啟動即可。
$ wget https://releases.hashicorp.com/consul/1.6.1/consul_1.6.1_linux_amd64.zip
$ unzip consul_1.5.3_linux_amd64.zip
$ ./consul agent -dev
啟動完畢后,瀏覽器訪問 http://127.0.0.1:8500
地址,即可打開 Consul Web 管理頁面。可以看到默認只有 consul 一個 Service,后期我們注冊到 Consul 的 Service 都可以從頁面上看到,非常直觀。
3.2、Docker 安裝
使用 Docker 啟動 Consul 單節點服務,直接獲取最新版官方鏡像 consul:latest
命令如下:
$ docker run --name consul -d -p 8500:8500 consul
啟動完畢后,同上方法驗證是否啟動成功,這里為了方便演示,我采用 Docker 方式啟動 Consul,這里的訪問地址為:http://172.30.12.167:8500
。
4、API 注冊服務到 Consul
接下來,我們要注冊服務到 Consul 中,可以通過其提供的 API 標准接口來添加。那么先注冊一個測試服務,該測試數據為本機 node-exporter
服務信息,服務地址及端口為 node-exporter
默認提供指標數據的地址,執行如下命令:
$ curl -X PUT -d '{"id": "node-exporter","name": "node-exporter-172.30.12.167","address": "172.30.12.167","port": 9100,"tags": ["test"],"checks": [{"http": "http://172.30.12.167:9100/metrics", "interval": "5s"}]}' http://172.30.12.167:8500/v1/agent/service/register
執行完畢后,刷新一下 Consul Web 控制台頁面,可以看到成功注冊到 Consul 中。
提一下,如果要注銷掉某個服務,可以通過如下 API 命令操作,例如注銷上邊添加的 node-exporter
服務
$ curl -X PUT http://172.30.12.167:8500/v1/agent/service/deregister/node-exporter
5、配置 Prometheus 實現自動服務發現
現在 Consul 服務已經啟動完畢,並成功注冊了一個服務,接下來,我們需要配置 Prometheus 來使用 Consul 自動服務發現,目的就是能夠將上邊添加的服務自動發現到 Prometheus 的 Targets 中,增加 prometheus.yml
配置如下:
...
- job_name: 'consul-prometheus'
consul_sd_configs:
- server: '172.30.12.167:8500'
services: []
說明一下:這里需要使用 consul_sd_configs
來配置使用 Consul 服務發現類型,server
為 Consul 的服務地址,這里跟上邊要對應上。 配置完畢后,重啟 Prometheus 服務,此時可以通過 Prometheus UI 頁面的 Targets 下查看是否配置成功。
可以看到,在 Targets 中能夠成功的自動發現 Consul 中的 Services 信息,后期需要添加新的 Targets 時,只需要通過 API 往 Consul 中注冊服務即可,Prometheus 就能自動發現該服務,是不是很方便。
不過,我們會發現有如下幾個問題:
- 會發現 Prometheus 同時加載出來了默認服務 consul,這個是不需要的。
- 默認只顯示 job 及 instance 兩個標簽,其他標簽都默認屬於
before relabeling
下,有些必要的服務信息,也想要在標簽中展示,該如何操作呢? - 如果需要自定義一些標簽,例如 team、group、project 等關鍵分組信息,方便后邊 alertmanager 進行告警規則匹配,該如何處理呢?
- 所有 Consul 中注冊的 Service 都會默認加載到 Prometheus 下配置的
consul_prometheus
組,如果有多種類型的 exporter,如何在 Prometheus 中配置分配給指定類型的組,方便直觀的區別它們?
以上問題,我們可以通過 Prometheus 配置中的 relabel_configs
參數來解決。
6、配置 relabel_configs 實現自定義標簽及分類
我們先來普及一下 relabel_configs
的功能, Prometheus 允許用戶在采集任務設置中,通過 relabel_configs
來添加自定義的 Relabeling 的額過程,來對標簽進行指定規則的重寫。 Prometheus 加載 Targets 后,這些 Targets 會自動包含一些默認的標簽,Target 以 __
作為前置的標簽是在系統內部使用的,這些標簽不會被寫入到樣本數據中。眼尖的會發現,每次增加 Target 時會自動增加一個 instance 標簽,而 instance 標簽的內容剛好對應 Target 實例的 __address__
值,這是因為實際上 Prometheus 內部做了一次標簽重寫處理,默認 __address__
標簽設置為 <host>:<port>
地址,經過標簽重寫后,默認會自動將該值設置為 instance 標簽,所以我們能夠在頁面看到該標簽。
詳細 relabel_configs
配置及說明可以參考 relabel_config 官網說明,這里我簡單列舉一下里面每個 relabel_action
的作用,方便下邊演示。
- replace: 根據 regex 的配置匹配
source_labels
標簽的值(注意:多個source_label
的值會按照 separator 進行拼接),並且將匹配到的值寫入到target_label
當中,如果有多個匹配組,則可以使用 ${1}, ${2} 確定寫入的內容。如果沒匹配到任何內容則不對target_label
進行重新, 默認為 replace。 - keep: 丟棄
source_labels
的值中沒有匹配到 regex 正則表達式內容的 Target 實例 - drop: 丟棄
source_labels
的值中匹配到 regex 正則表達式內容的 Target 實例 - hashmod: 將
target_label
設置為關聯的source_label
的哈希模塊 - labelmap: 根據 regex 去匹配 Target 實例所有標簽的名稱(注意是名稱),並且將捕獲到的內容作為為新的標簽名稱,regex 匹配到標簽的的值作為新標簽的值
- labeldrop: 對 Target 標簽進行過濾,會移除匹配過濾條件的所有標簽
- labelkeep: 對 Target 標簽進行過濾,會移除不匹配過濾條件的所有標簽
接下來,我們來挨個處理上述問題。
問題一,我們可以配置 relabel_configs
來實現標簽過濾,只加載符合規則的服務。以上邊為例,可以通過過濾 __meta_consul_tags
標簽為 test
的服務,relabel_config
向 Consul 注冊服務的時候,只加載匹配 regex 表達式的標簽的服務到自己的配置文件。修改 prometheus.yml
配置如下:
...
- job_name: 'consul-prometheus'
consul_sd_configs:
- server: '172.30.12.167:8500'
services: []
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: .*test.*
action: keep
解釋下,這里的 relabel_configs
配置作用為丟棄源標簽中 __meta_consul_tags
不包含 test
標簽的服務,__meta_consul_tags
對應到 Consul 服務中的值為 "tags": ["test"]
,默認 consul 服務是不帶該標簽的,從而實現過濾。重啟 Prometheus 可以看到現在只獲取了 node-exporter-172.30.12.167
這個服務了。
問題二和問題三可以歸為一類,就是將系統默認標簽或者用戶自定義標簽轉換成可視化標簽,方便查看及后續 Alertmanager 進行告警規則匹配分組。不過要實現給服務添加自定義標簽,我們還得做一下修改,就是在注冊服務時,將自定義標簽信息添加到 Meta Data 數據中,具體可以參考 [這里](Consul Service - Agent HTTP API) 官網說明,下邊來演示一下如何操作。
新建 consul-0.json
如下:
$ vim consul-0.json
{
"ID": "node-exporter",
"Name": "node-exporter-172.30.12.167",
"Tags": [
"test"
],
"Address": "172.30.12.167",
"Port": 9100,
"Meta": {
"app": "spring-boot",
"team": "appgroup",
"project": "bigdata"
},
"EnableTagOverride": false,
"Check": {
"HTTP": "http://172.30.12.167:9100/metrics",
"Interval": "10s"
},
"Weights": {
"Passing": 10,
"Warning": 1
}
}
說明一下:該 Json 文件為要注冊的服務信息,同時往 Meta 信息中添加了 app=spring-boot
,team=appgroup
,project=bigdata
三組標簽,目的就是為了方便告警分組使用。執行如下命令進行注冊:
$ curl --request PUT --data @consul-0.json http://172.30.12.167:8500/v1/agent/service/register?replace-existing-checks=1
注冊完畢,通過 Consul Web 管理頁面可以查看到已注冊成功,並且包含了 Meta 信息。
然后修改 prometheus.yml
配置如下:
...
- job_name: 'consul-prometheus'
consul_sd_configs:
- server: '172.30.12.167:8500'
services: []
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: .*test.*
action: keep
- regex: __meta_consul_service_metadata_(.+)
action: labelmap
解釋一下,增加的配置作用為匹配 __meta_consul_service_metadata_
開頭的標簽,將捕獲到的內容作為新的標簽名稱,匹配到標簽的的值作為新標簽的值,而我們剛添加的三個自定義標簽,系統會自動添加 __meta_consul_service_metadata_app=spring-boot
、__meta_consul_service_metadata_team=appgroup
、__meta_consul_service_metadata_project=bigdata
三個標簽,經過 relabel 后,Prometheus 將會新增 app=spring-boot
、team=appgroup
、project=bigdata
三個標簽。重啟 Prometheus 服務,可以看到新增了對應了三個自定義標簽。
問題四,將自動發現的服務進行分類,本質上跟上邊的處理方式一致,可以添加自定義的標簽方式,通過標簽來區分,二可以通過服務 Tag 來進行匹配來創建不同的類型 exporter 分組。這里我以第二種為例,通過給每個服務標記不同的 Tag,然后通過 relabel_configs
來進行匹配區分。我們來更新一下原 node-exporter-172.30.12.167
服務標簽,同時注冊一個其他類型 exporter 的服務如下:
$ vim consul-1.json
{
"ID": "node-exporter",
"Name": "node-exporter-172.30.12.167",
"Tags": [
"node-exporter"
],
"Address": "172.30.12.167",
"Port": 9100,
"Meta": {
"app": "spring-boot",
"team": "appgroup",
"project": "bigdata"
},
"EnableTagOverride": false,
"Check": {
"HTTP": "http://172.30.12.167:9100/metrics",
"Interval": "10s"
},
"Weights": {
"Passing": 10,
"Warning": 1
}
}
# 更新注冊服務
$ curl --request PUT --data @consul-1.json http://172.30.12.167:8500/v1/agent/service/register?replace-existing-checks=1
$ vim consul-2.json
{
"ID": "cadvisor-exporter",
"Name": "cadvisor-exporter-172.30.12.167",
"Tags": [
"cadvisor-exporter"
],
"Address": "172.30.12.167",
"Port": 8080,
"Meta": {
"app": "docker",
"team": "cloudgroup",
"project": "docker-service"
},
"EnableTagOverride": false,
"Check": {
"HTTP": "http://172.30.12.167:8080/metrics",
"Interval": "10s"
},
"Weights": {
"Passing": 10,
"Warning": 1
}
}
# 注冊服務
$ curl --request PUT --data @consul-2.json http://172.30.12.167:8500/v1/agent/service/register?replace-existing-checks=1
說明一下,我們更新了原 node-exporter-172.30.12.167
服務的標簽為 node-exporter
,同時注冊一個新類型 cadvisor-exporter-172.30.12.167
服務,並設置標簽為 cadvisor-exporter
,以示區別。注冊完畢,通過 Consul Web 控制台可以看到成功注冊了這兩個服務。
最后,我們修改 prometheus.yml
配置如下:
...
- job_name: 'consul-node-exporter'
consul_sd_configs:
- server: '172.30.12.167:8500'
services: []
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: .*node-exporter.*
action: keep
- regex: __meta_consul_service_metadata_(.+)
action: labelmap
- job_name: 'consul-cadvisor-exproter'
consul_sd_configs:
- server: '172.30.12.167:8500'
services: []
relabel_configs:
- source_labels: [__meta_consul_tags]
regex: .*cadvisor-exporter.*
action: keep
- regex: __meta_consul_service_metadata_(.+)
action: labelmap
這里需要根據每種類型的 exporter 新增一個關聯 job,同時 relabel_configs
中配置以 Tag 來做匹配區分。重啟 Prometheus 服務,可以看到服務已經按照類型分類了,方便查看。
參考資料