背景
Prometheus有兩個最基本的組件:一個是Prometheus程序呀打,一個是Alertmanager程序旱易。
它們的職責(zé)分工很明確:
- Prometheus程序負(fù)責(zé):定時拉取監(jiān)控指標(biāo)數(shù)據(jù)饲做、存儲指標(biāo)數(shù)據(jù)主胧、根據(jù)告警規(guī)則發(fā)起告警通知迄委;
- Alertmanager程序負(fù)責(zé):負(fù)責(zé)告警通知的路由蚌吸,即當(dāng)接收到Prometheus程序的通知后,該將通知以何種方式通知給誰龄坪。
Prometheus程序的配置最核心的配置是:
# ...
# 當(dāng)指標(biāo)數(shù)據(jù)符合什么規(guī)則進行告警通知昭雌。
# 在其它文件定義,這里只是引用該文件的路徑健田。
rule_files:
[ - <filepath_glob> ... ]
# 從哪里烛卧,該如何拉取指標(biāo)
scrape_configs:
[ - <scrape_config> ... ]
# ...
Alertmanager程序的配置最核心的配置是:
# ...
# 告警通知路由規(guī)則
route:
[- <route_config>-]
# 告警通知的接收者列表,部分監(jiān)控告警平臺也稱之為channel
receivers:
[- <receivers>-]
# ...
在實際工作中妓局,Prometheus和Alertmanager的配置會非常大总放。
嚴(yán)謹(jǐn)?shù)能浖こ桃笪覀冊谡嬲渴疬@些配置前,對其進行有效性和正確性的檢查好爬。否則SRE/DevOps的工程效率就會很低局雄,因為你需要手工調(diào)試龐大的配置。
所以存炮,我們需要有一種高效率的方式來保證配置的有效性和正確性炬搭。
保證Prometheus程序配置的有效性和正確性
promtool
Prometheus程序提供了一個叫promtool的命令行程序。解壓Prometheus的程序包后穆桂,你會發(fā)現(xiàn)它和Prometheus程序放在一個文件夾中宫盔。
promtool提供了一些子命令來保證Prometheus程序配置的有效性和正確性:
# 校驗Prometheus配置的有效性,它支持--lint="duplicate-rules"參數(shù)享完,用于檢查重復(fù)的rule配置
check config [<flags>] <config-files>...
# 校驗rule配置的有效性
check rules [<flags>] <rule-files>...
# 執(zhí)行rules單元測試用例
test rules <test-rule-file>...
至于有效性檢查灼芭,只需要執(zhí)行check子命令即可,不需要過多說明般又。
promtool的test rules
子命令可以實現(xiàn)rule配置的單元測試彼绷,具體命令如下:
./promtool test rules test.yml
test.yaml是單元測試描述文件。promtool是支持同時指定多個單元測試文件的倒源,如:./promtool test rules test.yml test1.yml test2.yml
單元測試描述文件內(nèi)容的格式如下:
# Prometheus的rule配置文件路徑
rule_files:
- rule1.yml
# 評估的間隔時長
evaluation_interval: 1m
# 單元測試列表
tests:
- interval: 1m
input_series:
alert_rule_test:
promql_expr_test:
tests
下的每個用例由4個字段組成:
- input_series:測試用例的測試數(shù)據(jù)苛预,即指標(biāo)的時序數(shù)據(jù)句狼;
- interval:代表每個時序數(shù)據(jù)之間的間隔時長笋熬;
- alert_rule_test:告警規(guī)則的測試用例;
- promql_expr_test:promql表達(dá)式的測試用例腻菇。我們可以使用它進行調(diào)試我們的promsql胳螟。
接下來將詳細(xì)介紹它們昔馋。
測試用例數(shù)據(jù)
測試用例數(shù)據(jù)的定義格式如下:
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'
- series: 'go_goroutines{job="prometheus", instance="localhost:9090"}'
values: '10+10x2 30+20x5'
- series: 'go_goroutines{job="node_exporter", instance="localhost:9100"}'
values: '10+10x7 10+30x4'
每一條input_serie由兩個字段組成:
- series:指標(biāo)時序數(shù)據(jù)的key
- values:指標(biāo)的value。其中的每一個值之間的間隔時長是
interval
的值
為了簡化values的值的定義糖耸,你可以一種擴展符號來定義其值秘遏。語法如下:
-
a+bxc
代表:a a+b a+(2*b) a+(3*b) … a+(c*b)
;這一個a值是起始值的序列嘉竟,然后a以b的(0..c)的倍數(shù)進行遞增邦危; -
a-bxc
表示:這一個a值是起始值的序列,然后a以b的(0..c)的倍數(shù)進行遞減舍扰; -
_
下劃線表示:序列中的某次指標(biāo)值沒有被抓取到倦蚪; -
stale
表示:過期的樣本數(shù)據(jù)。
以下是一些來自官方文檔的例子: -
-2+4x3
表示:-2 2 6 10
-
1-2x4
表示:1 -1 -3 -5 -7
-
1x4
表示:1 1 1 1 1
-
1 _x3 stale
表示:1 _ _ _ stale
-
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
-
10+10x2 30+20x5
表示:10 20 30 30 50 70 90 110 130
測試Promsql表達(dá)式
在寫Prometheus告警規(guī)則時边苹,一個很大的痛點就是無法簡單的驗證自己寫的promsql的正確性陵且。我們在告警規(guī)則的單元測試中驗證后,再配置到真正的rule文件中个束。
promsql的測試用例的寫法如下:
promql_expr_test:
- expr: go_goroutines > 5
# 要測試的promsql表達(dá)式慕购,它將會從測試數(shù)據(jù)中查詢數(shù)據(jù)
eval_time: 4m
# 評估時長。從測試數(shù)據(jù)的第0秒開始算茬底。
# 如果interval是1m沪悲,那么4m代表的是測試數(shù)據(jù)的第4個數(shù)值
exp_samples: # 執(zhí)行promsql表達(dá)式后,預(yù)期得到的數(shù)據(jù)結(jié)果
- labels: 'go_goroutines{job="prometheus",instance="localhost:9090"}'
value: 50
- labels: 'go_goroutines{job="node_exporter",instance="localhost:9100"}'
value: 50
告警規(guī)則的單元測試
在單元測試描述文件中桩警,添加Promsql表達(dá)式的測試用例的同時可训,我們還可以添加告警規(guī)則的測試用例,代碼樣例如下:
alert_rule_test:
- eval_time: 10m
alertname: InstanceDown
exp_alerts:
- 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."
- eval_time:規(guī)則評估時長捶枢;
- alertname:告警名握截,要求與Prometheus的告警規(guī)則中的alertname一致;
- exp_labels:預(yù)期收到的告警通知中的label值烂叔;
- exp_annotations:預(yù)期收到的告警通知中的annotation值谨胞。
保證Alertmanager程序配置的有效性和正確性
amtool
與Prometheus程序類似,Alertmanager程序提供了一個叫amtool的命令行程序蒜鸡。
我們關(guān)注它的兩個子命令:
-
config routes test
:驗證配置的正確性 -
check-config <config.yaml>
:驗證配置的有效性
config routes test子命令介紹
amtool不像promtool那樣支持在YAML文件中定義測試用例胯努,以下是它的命令樣例:
amtool config routes test --config.file=config.yaml --verify.receivers=team-X-pager service=database owner=team-X
--config.file
參數(shù)指定了配置文件的路徑。
除了支持指定配置的路徑逢防,還可以通過參數(shù)--alertmanager.url
指定使用某個運行中的Alertmanager的配置叶沛。
--verify.receivers
指定期望返回的receiver列表,使用逗號分隔忘朝。
該子命令的最后是標(biāo)簽集灰署,由key=value的格式組成,并使用空格分隔。例子中service=database owner=team-X
溉箕,代表的是{service="database",owner="team-X"}
為了更好的可視化晦墙,還可以加一個--tree
的參數(shù),效果如下:
% amtool config routes test --config.file=config.yaml --tree --verify.receivers=team-X-pager service=database owner=team-X
Matching routes:
.
└── default-route
└── {service="database"}
└── {owner="team-X"} receiver: team-X-pager
如果驗證失敗肴茄,該命令返回非0結(jié)果晌畅。
check-config子命令介紹
它的運行效果如下:
% amtool check-config config.yaml
Checking 'config.yaml' SUCCESS
Found:
- global config
- route
- 1 inhibit rules
- 5 receivers
- 1 templates
SUCCESS
如果驗證失敗,該命令返回非0結(jié)果寡痰。
可視化告警通知路由
Prometheus官網(wǎng)提供了一個告警通知路由的在線可視化編輯器抗楔。
將配置粘貼至編輯框中,然后在“Match Label Set”中輸入告警的標(biāo)簽拦坠,最后下方會顯示通知的路由路徑谓谦。如下圖,實心紅點即是匹配了該label的receiver:
可視化工具在路由配置調(diào)試階段非常有用贪婉。減小了路由配置的難度反粥。但是,需要注意:不要將任何敏感配置上傳到公網(wǎng)疲迂。
如何集成到CI/CD Pipeline中
以上介紹的是兩個命令最原始的使用方法才顿,即手工運行。我們需要將其集成到CI/CD pipeline中尤蒿,以實現(xiàn)工程化郑气。
集成方式一般有兩:
- 在Pipeline中增加一個執(zhí)行promtool和amtool的階段
- 集成構(gòu)建工具中,比如集成到Bazel中腰池。
當(dāng)然有一些DevOps平臺如果需要深度集成尾组,可以將promtool的amtool的實現(xiàn)代碼引入到自己的DevOps平臺的代碼中。
工程化的挑戰(zhàn)
另一個工程化的挑戰(zhàn)示弓,就是以上的配置文件之間存在引用讳侨,如下prometheus的rule文件中的expr字段的值,實際上是被prometheus-unitesting.yml文件引用奏属。
如果不對這個引用關(guān)系進行治理跨跨,這些配置的維護成本將會非常高。
由于YAML文件天生不具備變量定義的功能囱皿∮掠ぃ可以采用類似Jsonnet、CUE這樣的支持編程的配置語言代替YAML嘱腥。
這個話題比較大耕渴,不在本文討論范圍。