Prometheus使用案例
1.計算CPU的使用率
1.顯示CPU使用率,按模式細分並按使用的時間進行顯示
node_cpu_seconds_total
2.首先計算每種CPU模式的每秒使用率。PromQL有一個irate函數,用於計算范圍向量中時間序列增加的每秒即時速率。
irate(node_cpu_seconds_total{job="node"}[5m])
這將在irate函數中使用node_cpu_seconds_total指標並查詢5分鍾范圍的數據。它將從node左火速返回每個CPU在每種模式下的列表,表示為5分鍾范圍內的每秒速率。
3.聚合不同CPU和模式間的指標
# node主機已經使用的CPU占比,
avg(irate(node_cpu_seconds_total{job="node"}[5m])) by (instance) * 100
結果:
{instance="192.168.1.121:9100"} 12.125000000006903
# node主機未使用的CPU占比
100 - avg(irate(node_cpu_seconds_total{job="node"}[5m])) by (instance) * 100
{instance="192.168.1.121:9100"} 87.8749999999931
現在將irate函數放在avg聚合中,並添加了一個由instance標簽聚合的by子句。
但上面的指標還不太准備,它仍然包含idle值,並且沒有表示成百分比的形式。
2.CPU飽和度
在主機上獲得CPU飽和的一種方法是跟蹤平均負載,實際上它是將主機上的CPU數量考慮在內的一段時間內的平均運行隊列長度。平均負載少於CPU的數量通常是正常的,長時間內超過該數字的平均值則表示CPU已經飽和。
要產看主機的平均負載,可以使用node_load指標,他們顯示了1分鍾、5分鍾和15分鍾的平均負載。比如使用1分鍾的平均負載:node_load1
1.計算主機上的CPU數量,可以使用count聚合實現
count by (instance)(node_cpu_seconds_total{mode="idle"})
結果:
{instance="192.168.1.121:9100"} 4
2.接下來將此計算與node_load1指標結合起來
# 過去一分鍾cpu負載大於cpu總數的兩倍
node_load1 > on (instance) 2 * count by (instance)(node_cpu_seconds_total{node="idle"})
這里我們查詢的是1分鍾的負載超過主機CPU數量的兩倍的結果。
3.內存使用率
Node Exporter的內存指標按內存的類型和使用率進行細分。可以在node_memory未前綴的指標列表找到它們。
# 查看主機上的總內存
node_memory_MenTotal_bytes
# 主機上的可用內存
node_memory_MemFree_bytes
# 緩沖緩存中的內存
node_memory_Buffers_bytes
# 頁面緩存中的內存
node_memory_Cached_bytes
因此,將node_memory_MemFree_bytes、node_memory_Cached_bytes、node_memory_Buffers_bytes 指標的值相加,代表主機上的可用內存。然后將使用這個值和node_memory_MemTotal_bytes 指標來計算可用內存的百分比。
(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Cached_bytes + node_memory_Buffers_bytes)) / node_memory_MemTotal_bytes *100
在上面,將三個內存相加,從總數中減去它們然后再除以總數,最后乘以100將其轉換為百分比。
4.內存飽和度
還可以通過檢查內存和磁盤的讀寫來監控內存飽和度。可以使用從/proc/vmstat收集的兩個Node Exporter指標。
node_vmstat_pswpin:系統每秒從磁盤讀到內存的字節數。
node_vmstat_pswpout:系統每秒從內存寫到磁盤的字節數。
兩者都是自上次啟動以來的字節數,以KB為單位。
為了獲得飽和度指標,對每個指標計算每一分鍾的速率,將兩個速率相加,然后乘以1024獲得字節數。
1024 * sum by (instance) ((rate(node_vmstat_pgpgin[1m]) + rate(node_vmstat_pgpgout[1m])))
然后,可以對此設置圖形化展示或者警報,以識別行為不當的應用程序主機。
5.磁盤使用率
對於磁盤,只測量磁盤使用情況而不是使用率、飽和充或錯誤。這是因為在大多數情況下,它是對可視化和警報最有用的數據。
node_filesystem_size_bytes
node_filesystem_size_bytes 指標顯示了被監控的每個文件系統掛載的大小。可以使用與內存指標類似的查詢來生成在主機上使用的磁盤空間百分比。
(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} *100
與內存指標不同,在每個主機上的每個掛載點都有文件系統指標。所以添加了mountpoint標簽,特別是根文件系統"/"掛載。這將在每台主機上返回該文件系統磁盤使用指標。
(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} *100
如果想要或需要監控特定掛載點,那么我們可以為其添加查詢。比如要監控/data掛載點,可以使用:
(node_filesystem_size_bytes{mountpoint="/data"} - node_filesystem_free_bytes{mountpoint="/data"}) / node_filesystem_size_bytes{mountpoint="/data"} *100
或者可以使用過正則表達式匹配多個掛載點:
(node_filesystem_size_bytes{mountpoint=~"/|/run"} - node_filesystem_free_bytes{mountpoint=~"/|/run"}) / node_filesystem_size_bytes{mountpoint=~"/|/run"} *100
可以使用predict_linear函數來構建在未來什么時間會耗盡磁盤空間。
predict_linear(node_filesystem_free_bytes{mountpoint="/"}[1h], 4*3600) < 0
上面是指定根文件系統,還可以通過指定作業名稱或使用正則表達式來選擇所有文件系統。
predict_linear(node_filesystem_free_bytes{job="node"}[1h], 4*3600) < 0
在上面中,我們選擇一小時的時間窗口,並將此時間序列快照放在predict_linear函數中。該函數使用簡單的線性回歸,根據以前的增長情況來確定文件系統何時會耗盡空間。該函數參數包括一個范圍向量,即一小時窗口,以及未來需要預測的時間點。這些都是以秒為單位的,因此這里使用4*3600秒,即四小時。最后<0,即文件系統空間不足。
因此,如果基於最后一小時的增長歷史記錄,文件系統將在接下來的四個小時內用完,那么查詢將返回一個負數,然后我們可以用它來觸發警報。
6.服務狀態
現在來看看來自systemd收集器的數據,他向我們展示了主機上的服務狀態和其它各種systemd配置。服務的狀態在node_systemd_unit_state(或者直接up,也能查出來指標狀態)指標中暴露出來。對於收集的每個服務和服務狀態都有一個指標。
1.查詢docker的服務
node_systemd_unit_state{name="docker.service"}
此查詢為每個潛在的服務和狀態(failed,inactive,active)的組合生成指標,其中表示當前服務狀態的指標的值為1.我們可以通過state標簽來進一步縮小搜索范圍。
node_systemd_unit_state{name="docker.service",state="active"}
或者可以搜索值為1的所有指標,這將返回當前服務的狀態:
node_systemd_unit_state{name="docker.service"} == 1
2.生產使用注意事項
# 1. 如果是使用的服務配置文件如下:那么無法收集服務狀態:
/usr/bin/node_exporter --collector.textfile.directory /var/lib/node_exporter/textfile_collector --collector.systemd --collector.systemd.unit-whitelist="(docker|sshd|rsyslog).service" --no-colletor.softnet
# 2. 如果使用上面的命令直接啟動的話,則沒有問題。
# 3. 如果沒有加--no-collector.softnet的話,則會報如下錯誤。
level=error ts=2020-03-27T06:22:07.283Z caller=collector.go:161 msg="collector failed" name=softnet duration_seconds=0.000685365 err="could not get sorfnet statistics: failed to parse /proc/net/softnet_stat: 10 columns were detected,but 11 were expected."
7.源數據及UP指標
1. UP指標
用於監控特定節點狀態的另一個有用指標:up指標。對於每個實例抓取,Prometheus都會在以下時間序列中存儲樣本。
up指標:
up{job="<job-name>",instance="<instance-id>"}
如果實例是健康的,則指標設置為1,即數據抓取成功返回。如果抓取失敗,則設置為0,指標使用作業名稱job和時間序列的實例instance來進行標記。

2.metadata指標
最后,使用Node Exporter的textfile收集器來查看我們創建的metadata指標。
metadata{role="docker_server",datacenter="SH"} 1
因此,如果我們想要查詢哪些主機不在上海的,就可以直接用下列語句查詢。
metadata{datacenter != "NJ"}
3.向量匹配
我們還可以使用metadata指標來進行向量匹配,向量匹配可以使用任何的PromQL二次運算符。向量匹配嘗試針對左側向量中的每個元素在右側向量中查找對應的匹配元素。
目前有兩種向量匹配:一對一和多對一,或一對多
3.1一對一匹配
一對一匹配從每一側找到唯一匹配的條目對。如果兩個條目具有完全相同的標簽和值,則它們是一對一匹配的。你可以考慮使用ignoring修飾符忽略掉特定標簽,或者使用on修飾符來減少顯示的標簽列表。我們來看一個例子
node_systemd_unit_state{name="docker.service"} ==1 and on (instance ,job) metadata{datacenter="SH"}
這將選擇所有node_systemd_unit_state指標中name標簽為docker.service並且值為1的指標。然后使用On修飾符將返回的標簽列表減少到metadata指標的instance和job標簽,並且datacenter標簽的值為SH。
3.2 多對一和一對多皮皮額
多對一和一對多匹配是其中一側向量中的元素與另一側向量中的多個元素相匹配。這些匹配使用group_right修飾符顯示指定,其中left或right是為了確定哪個向量具有更高的基數。但它們通常不會被使用。大多數情況下,一對一匹配就足夠了。
8.查詢的持久化
可以通過以下三種方式使查詢持久化:
1)記錄規則:根據查詢創建新指標。
2)警報規則:從查詢生成警報。
3)可視化規則:使用Grafana等儀表板可視化查詢。
之前的查詢都可以交替應用這三種機制,因為所有這些機制都能理解和執行PromQL查詢。
1.記錄規則
記錄規則是一種根據已有時間序列計算新時間序列(特別是聚合時間序列)的方法,我們這樣做是為了:
1)跨多個時間序列生成聚合。
2)預先計算消耗大的查詢。
3)產生可用於生成警報的時間序列。
2.配置記錄規則
記錄規則存儲在Prometheus服務器上,位於Prometheus服務器加載的文件中。規則是自動計算的,頻率則由Prometheus.yml配置文件中的evaluation_interval參數控制。
global:
scrape_interval: 15s
evaluation_interval: 15s
在Prometheus.yaml文件的同一文件夾中創建一個名為rules的子文件夾,用於保存記錄規則。在這里為節點創建一個名為node_rules.yml的文件。Prometheus規則與Prometheus配置一樣是通過YAML編寫的。
cd /etc/prometheus/
mkdir -p rules
cd rules/
touch node_rules.yml
編輯Prometheus.yml文件,添加內容如下:
rule_files:
- "rules/node_rules.yml"
2.1添加記錄規則
1.一個記錄CPU 5分鍾速率的案例
groups:
- name: node_rules
rules:
- record: instance:node_cpu:avg_rate5m
expr: 100 - avg(irate(node_cpu_seconds_total{job="node",mode="ide"}[5m])) by (instance) * 100
記錄規則在規則組中定義,這里的規則組叫作node_rules。規則組名稱在服務器中必須是唯一的。規則組內的規則以固定間隔順序執行。默認情況下,這是通過全局evaluate_interval來控制的,但你可以使用interval子句在規則組中覆蓋。
規則組內規則執行的順序性質意味着你可以在后續規則中使用之前創建的規則。這允許你根據規則創建指標,然后再之后的規則中重用這些指標。這僅在規則組內適用,規則組是並行運行的,因此不建議跨組適用規則。
這意味着可以將記錄規則用作參數,例如,可能希望創建一個帶有閾值的規則。然后,可以在規則中設置一次閾值並重復使用多次。如果你需要更改閾值,則只需要更改一處即可。
groups:
- name: node_rules
interval: 10s
rules:
接下來,我們有一個名為rules的YAML塊,它包含該組的記錄規則。每條規則都包含一條記錄,告訴Prometheus將新的時間序列命名為什么。你應該仔細命名規則,以便快速識別它們代表的內容。
一般推薦的格式是:
level:metirc:operations
其中level表示聚合級別,以及規則輸出的標簽。metric是指標名稱,除了使用rate()或irate()函數玻璃_total計數器之外,應該保持不變。這樣的命名可以幫助你更輕松地找到新指標。最后,operations是應用於指標的操作列表,一般最新的操作放在前面。
所以我們的CPU查詢命名為:
instance:node_cpu:avg_rate5m
然后使用一個expr字段來保存生成新時間序列的查詢。
我們還可以添加labels塊以向新時間序列添加新標簽。根據規則創建的時間序列會繼承用於創建它們的時間序列的相關標簽,但你也可以添加或覆蓋標簽。例如:
groups:
- name: node_rules
rules:
- record: instance:node_cpu:avg_rate5m
expr: 100 - avg(irate(node_cpu_seconds_total{job="node",mode="ide"}[5m])) by (instance) * 100
labels:
metric_type: aggregation
接下來,再創建一些查詢:
groups:
- name: node_rules
rules:
- record: instance:node_cpu:avg_rate5m
expr: 100 - avg(irate(node_cpu_seconds_total{job="node",mode="ide"}[5m])) by (instance) * 100
- record: instance:node_memory_usage:percentage
expr: (node_memory_MemTotal_bytes-(node_memory_MemFree_bytes + node_memory_Cached_bytes + node_memory_Buffers_bytes)) / node_memory_MemTotal_bytes *100
- record: instance:root:node_filesystem_usage:percentage
expr: (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} * 100
在重啟Prometheus服務器或進行SIGHUP以激活新規則。這將為每個規則創建一個新的時間序列。一小段時間后,應該能在服務器上找到新的時間序列。
[info]通過將SIGHUP信號發送到Prometheus進程上或在Microsoft Windows上重啟,可以在運行時重新加載規則文件,重新加載僅在規則文件格式良好時才有效。Prometheus服務器附帶一個名為Prometheus的使用程序,可以幫助檢測文件規則文件。
隨后可以在web界面的rules中查看定義的規則:

