本章節主要講自動發現使用場景介紹與Prometheus基於文件、DNS的自動發現配置
當我們使用各類exporter分別對系統、數據庫和HTTP服務進行監控指標采集,對於所有監控指標對應的Target的運行狀態和資源使用情況,都是用Prometheus的靜態配置功能 static_configs
來
手動添加主機IP和端口,然后重載服務讓Prometheus發現。
對於一組比較少的服務器的測試環境中,這種手動方式添加配置信息是最簡單的方法。但是實際生產環境中,對於成百上千的節點組成的大型集群又或者Kubernetes這樣的大型集群,很明顯,手動方式捉襟見肘了。
為此,Prometheus提前已經設計了一套服務發現功能。
Prometheus 服務發現能夠自動檢測分類,並且能夠識別新節點和變更節點。也就是說,可以在容器或者雲平台中,自動發現並監控節點或更新節點,動態的進行數據采集和處理。
目前 Prometheus 已經支持了很多常見的自動發現服務,比如 consul
ec2
gce
serverset_sd_config
openStack
kubernetes
等等。
我們常用的就是sd_config、DNS、kubernetes、consul這些足夠了。如果有需要其他配置的探討,可以與我交流,我可以補上來。
本章節中會對Prometheus自動發現中的基於文件、DNS進行發現講解,consul
在后面會單獨展開來講,如何可以使其完美的解決當前場景下常見的各類服務發現監控。
為什么要用自動發現?
在基於雲(IaaS或者CaaS)的基礎設施環境中用戶可以像使用水、電一樣按需使用各種資源(計算、網絡、存儲)。按需使用就意味着資源的動態性,這些資源可以隨着需求規模的變化而變化。例如在AWS中就提供了專門的AutoScall服務,可以根據用戶定義的規則動態地創建或者銷毀EC2實例,從而使用戶部署在AWS上的應用可以自動的適應訪問規模的變化。
這種按需的資源使用方式對於監控系統而言就意味着沒有了一個固定的監控目標,所有的監控對象(基礎設施、應用、服務)都在動態的變化。對於Nagias這類基於Push模式傳統監控軟件就意味着必須在每一個節點上安裝相應的Agent程序,並且通過配置指向中心的Nagias服務,受監控的資源與中心監控服務器之間是一個強耦合的關系,要么直接將Agent構建到基礎設施鏡像當中,要么使用一些自動化配置管理工具(如Ansible、Chef)動態的配置這些節點。當然實際場景下除了基礎設施的監控需求以外,我們還需要監控在雲上部署的應用,中間件等等各種各樣的服務。要搭建起這樣一套中心化的監控系統實施成本和難度是顯而易見的。
而對於Prometheus這一類基於Pull模式的監控系統,顯然也無法繼續使用的static_configs的方式靜態的定義監控目標。而對於Prometheus而言其解決方案就是引入一個中間的代理人(服務注冊中心),這個代理人掌握着當前所有監控目標的訪問信息,Prometheus只需要向這個代理人詢問有哪些監控目標控即可, 這種模式被稱為服務發現。
在不同的場景下,會有不同的東西扮演者代理人(服務發現與注冊中心)這一角色。比如在AWS公有雲平台或者OpenStack的私有雲平台中,由於這些平台自身掌握着所有資源的信息,此時這些雲平台自身就扮演了代理人的角色。Prometheus通過使用平台提供的API就可以找到所有需要監控的雲主機。在Kubernetes這類容器管理平台中,Kubernetes掌握並管理着所有的容器以及服務信息,那此時Prometheus只需要與Kubernetes打交道就可以找到所有需要監控的容器以及服務對象。Prometheus還可以直接與一些開源的服務發現工具進行集成,例如在微服務架構的應用程序中,經常會使用到例如Consul這樣的服務發現注冊軟件,Promethues也可以與其集成從而動態的發現需要監控的應用服務實例。除了與這些平台級的公有雲、私有雲、容器雲以及專門的服務發現注冊中心集成以外,Prometheus還支持基於DNS以及文件的方式動態發現監控目標,從而大大的減少了在雲原生,微服務以及雲模式下監控實施難度。
如上所示,展示了Push系統和Pull系統的核心差異。相較於Push模式,Pull模式的優點可以簡單總結為以下幾點:
-
只要Exporter在運行,你可以在任何地方(比如在本地),搭建你的監控系統;
-
你可以更容易的查看監控目標實例的健康狀態,並且可以快速定位故障;
-
更利於構建DevOps文化的團隊;
-
松耦合的架構模式更適合於雲原生的部署環境。
基於文件的服務發現
在Prometheus支持的眾多服務發現的實現方式中,基於文件的服務發現是最通用的方式。這種方式不需要依賴於任何的平台或者第三方服務。對於Prometheus而言也不可能支持所有的平台或者環境。通過基於文件的服務發現方式下,Prometheus會定時從文件中讀取最新的Target信息,因此,你可以通過任意的方式將監控Target的信息寫入即可。
用戶可以通過JSON或者YAML格式的文件,定義所有的監控目標。例如,在下面的yaml文件中分別定義了2個采集任務,以及每個任務對應的Target列表:
yaml格式
- targets: ['192.168.1.220:9100']
labels:
app: 'app1'
env: 'game1'
region: 'us-west-2'
- targets: ['192.168.1.221:9100']
labels:
app: 'app2'
env: 'game2'
region: 'ap-southeast-1'
json格式
[
{
"targets": [ "192.168.1.221:29090"],
"labels": {
"app": "app1",
"env": "game1",
"region": "us-west-2"
}
},
{
"targets": [ "192.168.1.222:29090" ],
"labels": {
"app": "app2",
"env": "game2",
"region": "ap-southeast-1"
}
}
]
同時還可以通過為這些實例添加一些額外的標簽信息,例如使用env標簽標示當前節點所在的環境,這樣從這些實例中采集到的樣本信息將包含這些標簽信息,從而可以通過該標簽按照環境對數據進行統計。
創建Prometheus配置文件/data/prometheus/conf/prometheus-file-sd.yml,並添加以下內容:
- job_name: 'file_sd_test'
scrape_interval: 10s
file_sd_configs:
- files:
- /data/prometheus/static_conf/*.yml
- /data/prometheus/static_conf/*.json
這里定義了一個基於file_sd_configs的監控采集test任務,其中模式的任務名稱為file_sd_test。在yml文件中可以使用yaml標簽覆蓋默認的job名稱,然后重載Prometheus服務。
service prometheus restat
在Prometheus UI的Targets下就可以看到當前從targets.json文件中動態獲取到的Target實例信息以及監控任務的采集狀態,同時在Labels列下會包含用戶添加的自定義標簽:
Prometheus默認每5m重新讀取一次文件內容,當需要修改時,可以通過refresh_interval進行設置,例如:
- job_name: 'file_sd_test'
scrape_interval: 10s
file_sd_configs:
- refresh_interval: 30s # 30s重載配置文件
files:
- /data/prometheus/static_conf/*.yml
- /data/prometheus/static_conf/*.json
通過這種方式,Prometheus會自動的周期性讀取文件中的內容。當文件中定義的內容發生變化時,不需要對Prometheus進行任何的重啟操作。
這種通用的方式可以衍生了很多不同的玩法,比如與自動化配置管理工具(Ansible)結合、與Cron Job結合等等。 對於一些Prometheus還不支持的雲環境,比如國內的阿里雲、騰訊雲等也可以使用這種方式通過一些自定義程序與平台進行交互自動生成監控Target文件,從而實現對這些雲環境中基礎設施的自動化監控支持。
基於DNS的發現
對於一些環境,可能基於文件與consul服務發現已經無法滿足的時候,我們可能就需要DNS來做服務發現了。在互聯網架構中,我們使用主機節點或者Kubernetes集群通常是不對外暴露IP的,這就要求我們在一個內部局域網或者專用的網絡中部署DNS服務器,使用DNS服務來完成內部網絡中的域名解析工作。
這個時候我們就可以使用Prometheus的DNS服務發現,Prometheus的DNS服務發現有倆種方法,第一種是使用DNA A記錄來做自動發現,第二種方法是DNS SRV,第一種顯然沒有沒有SRV資源記錄更為便捷,在這里就把倆種配置全部做一遍,對於取決用什么,根據你自己的環境來抉擇。
DNA A記錄發現配置,首先你內網需要有一個DNS服務器,或者直接自行配置解析記錄即可,我這里使用的dnsmasq服務在內網測試
# 驗證 test1 DNS記錄
nslookup test1.example.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: test1.example.com
Address: 192.168.1.221
# 驗證 test2 DNS記錄
nslookup test2.example.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: test2.example.com
Address: 192.168.1.222
Prometheus配置
# 基於DNS A記錄發現
- job_name: 'DNS-A' # job 名稱
metrics_path: "/metrics" # 路徑
dns_sd_configs:
- names: ["test1.example.com", "test2.example.com"] # A記錄
type: A # 解析類型
port: 29100 # 端口
重啟Prometheus 在targets中可以看到dns-a記錄
DNS SRV是DNS資源記錄中的一種記錄類型,用來指定服務器地址與端口,並且可以設置每個服務器的優先級和權重。訪問到服務的時候,本地的DNS resolver 從DNS服務器獲取一個地址列表,然后根據優先級和權重來選擇一個地址作為本次請求的目標地址。
SRV的記錄格式:
_service._proto.name. TTL class SRV priority weight port target
參數 | 說明 |
---|---|
_service |
服務名稱,前綴 _ 是為了防止與DNS 標簽(域名)沖突 |
proto |
服務使用的通訊協議 通常是 tcp udp |
name |
此記錄有效域名 |
TTL |
標准DNS class 字段 如 IN |
priority |
記錄優先級,數值越小,優先級越高。 [0-65535] |
weight |
記錄權重,數值越大,權重越高。[0-65535] |
port |
服務使用端口 |
target |
使用服務的主機地址名稱 |
這里沒有使用named,而是使用的dnsmasq來做的測試,添加SRV記錄完成后,需要重啟dnsmasq服務使其生效。
# 配置dns解析
cat /etc/dnsmasq.d/localdomain.conf
address=/test1.example.com/192.168.1.221
address=/test2.example.com/192.168.1.222
# 添加 SRV 記錄
cat /etc/dnsmasq.conf
srv-host =_prometheus._tcp.example.com,test1.example.com,29100
srv-host =_prometheus._tcp.example.com,test2.example.com,29100
# 驗證srv服務是否正確,192.168.1.123 是內部DNS服務器,
dig @192.168.1.123 +noall +answer SRV _prometheus._tcp.example.com
output...
_prometheus._tcp.example.com. 0 IN SRV 0 0 9100 test1.example.com.
_prometheus._tcp.example.com. 0 IN SRV 0 0 9100 test2.example.com.
Prometheus配置完成以后,重載Prometheus服務。
- job_name: 'DNS-SRV' # 名稱
metrics_path: "/metrics" # 獲取數據的路徑
dns_sd_configs: # 配置使用DNS解析
- names: ['_prometheus._tcp.example.com'] # 配置SRV對應的解析地址
這個時候在targets中可以看到DNS自動發現的記錄了。
這個時候,我們在新加一個記錄,用來做自動發現。
# 添加test0解析
cat /etc/dnsmasq.d/localdomain.conf
address=/test1.example.com/192.168.1.221
address=/test2.example.com/192.168.1.222
address=/test0.example.com/192.168.1.220
# 添加 test0 SRV 記錄
cat /etc/dnsmasq.conf
srv-host =_prometheus._tcp.example.com,test1.example.com,29100
srv-host =_prometheus._tcp.example.com,test2.example.com,29100
srv-host =_prometheus._tcp.example.com,test0.example.com,19100
# 驗證dns SRV記錄是否成功
dig @192.168.1.123 +noall +answer SRV _prometheus._tcp.example.com
_prometheus._tcp.example.com. 0 IN SRV 0 0 19100 test0.example.com.
_prometheus._tcp.example.com. 0 IN SRV 0 0 29100 test2.example.com.
_prometheus._tcp.example.com. 0 IN SRV 0 0 29100 test1.example.com.
這個時候在去觀察targets就發現已經可以自動發現test0了。