前言
本文來自Prometheus官網手冊1、2、3、4和 Prometheus簡介1、2、3、4
記錄規則
一、配置規則
Prometheus支持兩種類型的規則,這些規則可以定期配置,然后定期評估:記錄規則和警報規則。 要在Prometheus中包含規則,請創建包含必要規則語句的文件,並讓Prometheus通過Prometheus配置中的rule_files
字段加載文件, 規則文件使用YAML。
通過將SIGHUP
發送到Prometheus進程,可以在運行時重新加載規則文件。 僅當所有規則文件格式正確時才會應用更改。
二、語法檢查規則
要在不啟動Prometheus服務器的情況下快速檢查規則文件在語法上是否正確,請安裝並運行Prometheus的promtool
命令行實用工具:一般下載來整個Prometheus已經包含了promtool工具。
go get github.com/prometheus/prometheus/cmd/promtool promtool check rules /path/to/example.rules.yml
當文件在語法上有效時,檢查器將已解析規則的文本表示打印到標准輸出,然后以0
返回狀態退出。如果存在任何語法錯誤或無效的輸入參數,則會向標准錯誤輸出錯誤消息,並以1
返回狀態退出。
三、錄制規則
錄制規則允許預先計算經常需要或計算上昂貴的表達式,並將其結果保存為一組新的時間序列。 因此,查詢預先計算的結果通常比每次需要時執行原始表達式快得多。 這對於儀表板尤其有用,儀表板需要在每次刷新時重復查詢相同的表達式。記錄和警報規則存在於規則組中,組內的規則以固定間隔順序運行。
規則文件的語法是:
groups:
[ - <rule_group> ]
一個簡單的示例規則文件將是:
groups: - name: example rules: - record: job:http_inprogress_requests:sum expr: sum(http_inprogress_requests) by (job)
3.1 <rule_group>
# 組的名稱。 在文件中必須是唯一的。 name: <string> # 評估組中的規則的頻率。 [ interval: <duration> | default = global.evaluation_interval ] rules: [ - <rule> ... ]
3.2 <rule>
記錄規則的語法是:
# 要輸出的時間序列的名稱。 必須是有效的度量標准名稱。 record: <string> # 要評估的PromQL表達式。 每個評估周期都會在當前時間進行評估,並將結果記錄為一組新的時間序列,其中度量標准名稱由“記錄”給出。 expr: <string> # 在存儲結果之前添加或覆蓋的標簽。 labels: [ <labelname>: <labelvalue> ]
警報規則的語法是:
# 警報的名稱。 必須是有效的度量標准名稱。 alert: <string> # 要評估的PromQL表達式。 每個評估周期都會在當前時間進行評估,並且所有結果時間序列都會成為待處理/觸發警報。 expr: <string> # 警報一旦被退回這段時間就會被視為開啟。 # 尚未解雇的警報被認為是未決的。 [ for: <duration> | default = 0s ] # 為每個警報添加或覆蓋的標簽。 labels: [ <labelname>: <tmpl_string> ] # 要添加到每個警報的注釋。 annotations: [ <labelname>: <tmpl_string> ]
比如按照規則的語法來創建一個新的metric,prometheus.rules.yml:
groups: - name: example rules: - record: Cpu_Usage expr: clamp_max(((avg by (mode) ( (clamp_max(rate(node_cpu_seconds_total{mode!="idle"}[10s]),1)) or (clamp_max(irate(node_cpu_seconds_total{mode!="idle"}[10s]),1)) ))*100 ),100)
再去Prometheus上進行配置,prometheus.yml:
rule_files: - "prometheus.rules.yml"
預警規則
警報規則基於Prometheus表達式定義警報條件,並將有關觸發警報的通知發送到外部服務。 每當警報表達式在給定時間點生成一個或多個向量元素時,警報將視為這些元素的標簽集的活動狀態。
一、定義報警規則
警報規則在Prometheus中與記錄規則相同的方式配置。帶警報的示例規則文件將是:
groups: - name: example rules: - alert: HighErrorRate expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5 for: 10m labels: severity: page annotations: summary: High request latency
for
子句:使Prometheus在第一次遇到新的表達式輸出向量元素和將此警告作為此元素的觸發計數之間等待一段時間。 在這種情況下,Prometheus將在每次評估期間檢查警報是否繼續處於活動狀態10分鍾,然后再觸發警報。 處於活動狀態但尚未觸發的元素處於pending狀態。labels
子句:允許指定要附加到警報的一組附加標簽。 任何現有的沖突標簽都將被覆蓋。 標簽值可以是模板化的。annotations
子句:指定一組信息標簽,可用於存儲更長的附加信息,例如警報描述或Runbook鏈接。 注釋值可以是模板化的。
二、模板
可以使用控制台模板化標簽和注釋值。 $labels
變量保存警報實例的標簽鍵/值對,$value
保存警報實例的評估值。
# 要插入觸發元素的標簽值: {{ $labels.<labelname> }} # 要插入觸發元素的數值表達式值: {{ $value }}
例子:
groups: - name: example rules: # 對於任何無法訪問> 5分鍾的實例的警報。 - alert: InstanceDown expr: up == 0 for: 5m labels: severity: page annotations: summary: "Instance {{ $labels.instance }} down" description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes." # 對中值請求延遲> 1s的任何實例發出警報。 - alert: APIHighRequestLatency expr: api_http_request_latencies_second{quantile="0.5"} > 1 for: 10m annotations: summary: "High request latency on {{ $labels.instance }}" description: "{{ $labels.instance }} has a median request latency above 1s (current value: {{ $value }}s)"
三、在運行時檢查警報
要手動檢查哪些警報處於活動狀態(待處理或觸發),請導航至Prometheus實例的"Alerts"選項卡。 這將顯示每個定義的警報當前處於活動狀態的確切標簽集。
對於待處理和觸發警報,Prometheus還存儲ALERTS{alertname="<alert name>",alertstate ="pending|firing",<additional alert labels>}
形式的合成時間序列。 只要警報處於指示的活動(掛起或觸發)狀態,樣本值就會設置為1
,並且當不再是這種情況時,系列會標記為過時。
四、發送提醒通知
Prometheus的警報規則很好地解決了現在的問題,但並不是一個完全成熟的通知解決方案。 需要另一層來在簡單警報定義之上添加摘要,通知速率限制。 其中Alertmanager承擔了這一角色,可以被配置為周期性地向Alertmanager實例發送關於警報狀態的信息,然后該實例負責調度正確的通知。另外Prometheus可以配置為通過其服務發現集成自動發現可用的Alertmanager實例。
模板例子
Prometheus支持在警報的注釋和標簽以及服務的控制台頁面中進行模板化。 模板能夠針對本地數據庫運行查詢,迭代數據,使用條件,格式化數據等.Prometheus模板語言基於Go模板系統。
一、簡單的警報字段模板
alert: InstanceDown expr: up == 0 for: 5m labels: severity: page annotations: summary: "Instance {{$labels.instance}} down" description: "{{$labels.instance}} of job {{$labels.job}} has been down for more than 5 minutes."
對於每個觸發的警報,將在每次規則迭代期間執行警報字段模板,因此請保持所有查詢和模板的輕量級。 如果您需要更復雜的警報模板,建議您改為鏈接到控制台。
二、簡單的迭代
這將顯示實例列表以及它們是否已啟動:
{{ range query "up" }} {{ .Labels.instance }} {{ .Value }} {{ end }}
特別的.
變量包含每個循環迭代的當前樣本的值。
三、展示一個值
{{ with query "some_metric{instance='someinstance'}" }} {{ . | first | value | humanize }} {{ end }}
Go和Go的模板語言都是強類型的,因此必須檢查是否返回了樣本以避免執行錯誤。 例如,如果抓取或規則評估尚未運行,或者主機已關閉,則可能會發生這種情況。包含的prom_query_drilldown
模板處理此問題,允許格式化結果,並鏈接到表達式瀏覽器。
四、使用命令行URL參數
{{ with printf "node_memory_MemTotal{job='node',instance='%s'}" .Params.instance | query }} {{ . | first | value | humanize1024}}B {{ end }}
如果以console.html?instance = hostname
的身份訪問,.Params.instance
將評估為hostname
。
五、高級迭代
<table> {{ range printf "node_network_receive_bytes{job='node',instance='%s',device!='lo'}" .Params.instance | query | sortByLabel "device"}} <tr><th colspan=2>{{ .Labels.device }}</th></tr> <tr> <td>Received</td> <td>{{ with printf "rate(node_network_receive_bytes{job='node',instance='%s',device='%s'}[5m])" .Labels.instance .Labels.device | query }}{{ . | first | value | humanize }}B/s{{end}}</td> </tr> <tr> <td>Transmitted</td> <td>{{ with printf "rate(node_network_transmit_bytes{job='node',instance='%s',device='%s'}[5m])" .Labels.instance .Labels.device | query }}{{ . | first | value | humanize }}B/s{{end}}</td> </tr>{{ end }} <table>
在這里,我們遍歷所有網絡設備並顯示每個網絡設備的網絡流量。由於range
操作未指定變量,因此循環內部.Params.instance
不可用,現在是循環變量。
六、定義可重用模板
Prometheus支持定義可重用的模板。 當與控制台庫支持結合使用時,這一功能特別強大,允許跨控制台共享模板。
{{/* Define the template */}} {{define "myTemplate"}} do something {{end}} {{/* Use the template */}} {{template "myTemplate"}}
模板僅限於一個參數。 args
函數可用於包裝多個參數。
{{define "myMultiArgTemplate"}} First argument: {{.arg0}} Second argument: {{.arg1}} {{end}} {{template "myMultiArgTemplate" (args 1 2)}}
模板參考
規則的單元測試
使用promtool
來測試規則:
# 單個測試文件 ./promtool test rules test.yml # 多個測試文件 ./promtool test rules test1.yml test2.yml test3.yml
一、測試文件格式
# 這是要考慮進行測試的規則文件列表。 rule_files: [ - <file_name> ] # 可選的, 默認 = 1m evaluation_interval: <duration> # 下面列出組名稱的順序將是規則組的評估順序(在給定的評估時間)。 訂單僅適用於下面提到的組。 # 下面不需要提到所有組。 group_eval_order: [ - <group_name> ] # 所有測試都列在這里。 tests: [ - <test_group> ]
1.1 <test_group>
# 系列數據 interval: <duration> input_series: [ - <series> ] # 上述數據的單元測試 # 警報規則的單元測試。 我們從輸入文件中考慮警報規則。 alert_rule_test: [ - <alert_test_case> ] # 單元測試PromQL表達式。 promql_expr_test: [ - <promql_test_case> ]
1.2 <series>
# 這遵循通常的系列符號 '<metric name>{<label name>=<label value>, ...}' # 例子: # series_name{label1="value1", label2="value2"} # go_goroutines{job="prometheus", instance="localhost:9090"} series: <string> # 這使用擴展表示法。 # 擴展符號: # 'a+bxc' becomes 'a a+b a+(2*b) a+(3*b) … a+(c*b)' # 'a-bxc' becomes 'a a-b a-(2*b) a-(3*b) … a-(c*b)' # 例子: # 1. '-2+4x3' becomes '-2 2 6 10' # 2. ' 1-2x4' becomes '1 -1 -3 -5 -7' values: <string>
1.3 <alert_test_case>
Prometheus允許為不同的警報規則使用相同的警報名稱。 因此,在此單元測試中,必須在單個<alert_test_case>
下列出alertname
的所有觸發警報的並集。
# 這是從必須檢查警報的時間= 0開始經過的時間。 eval_time: <duration> # 要測試的警報的名稱。 alertname: <string> # 在給定評估時間在給定警報名稱下觸發的預期警報列表。 如果您想測試是否不應該觸發警報規則,那么您可以提及上述字段並將“exp_alerts”留空。 exp_alerts: [ - <alert> ]
1.4 <alert>
# 這些是預期警報的擴展標簽和注釋。 # 注意:標簽還包括與警報關聯的樣本標簽(與您在`/alerts`中看到的標簽相同,沒有系列`__name__`和`alertname`) exp_labels: [ <labelname>: <string> ] exp_annotations: [ <labelname>: <string> ]
1.5 <promql_test_case>
# 表達評估 expr: <string> # 這是從必須檢查警報的時間= 0開始經過的時間。 eval_time: <duration> # 在給定評估時間的預期樣品。 exp_samples: [ - <sample> ]
1.6 <sample>
# 通常系列表示法中的樣本標簽 '<metric name>{<label name>=<label value>, ...}' # 例子: # series_name{label1="value1", label2="value2"} # go_goroutines{job="prometheus", instance="localhost:9090"} labels: <string> # promql表達式的期望值。 value: <number>
二、例子
這是用於通過測試的單元測試的示例輸入文件。 test.yml
是遵循上述語法的測試文件,alerts.yml
包含警報規則。將alerts.yml
放在同一目錄中,運行./promtool test rules test.ym
l。
2.1 <test.yml>
# This is the main input for unit testing. # Only this file is passed as command line argument. rule_files: - alerts.yml evaluation_interval: 1m tests: # Test 1. - interval: 1m # Series data. input_series: - series: 'up{job="prometheus", instance="localhost:9090"}' values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' - series: 'up{job="node_exporter", instance="localhost:9100"}' values: '1+0x6 0 0 0 0 0 0 0 0' # 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 - series: 'go_goroutines{job="prometheus", instance="localhost:9090"}' values: '10+10x2 30+20x5' # 10 20 30 30 50 70 90 110 130 - series: 'go_goroutines{job="node_exporter", instance="localhost:9100"}' values: '10+10x7 10+30x4' # 10 20 30 40 50 60 70 80 10 40 70 100 130 # Unit test for alerting rules. alert_rule_test: # Unit test 1. - eval_time: 10m alertname: InstanceDown exp_alerts: # Alert 1. - exp_labels: severity: page instance: localhost:9090 job: prometheus exp_annotations: summary: "Instance localhost:9090 down" description: "localhost:9090 of job prometheus has been down for more than 5 minutes." # Unit tests for promql expressions. promql_expr_test: # Unit test 1. - expr: go_goroutines > 5 eval_time: 4m exp_samples: # Sample 1. - labels: 'go_goroutines{job="prometheus",instance="localhost:9090"}' value: 50 # Sample 2. - labels: 'go_goroutines{job="node_exporter",instance="localhost:9100"}' value: 50
2.2 <alerts.yml>
# This is the rules file. groups: - name: example rules: - alert: InstanceDown expr: up == 0 for: 5m labels: severity: page annotations: summary: "Instance {{ $labels.instance }} down" description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes." - alert: AnotherInstanceDown expr: up == 0 for: 10m labels: severity: page annotations: summary: "Instance {{ $labels.instance }} down" description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes."