基于Alertmanager設(shè)計(jì)告警降噪系統(tǒng),成本低可落地
一、背景
轉(zhuǎn)轉(zhuǎn)基于Prometheus落地了一體化監(jiān)控系統(tǒng),并自研了告警系統(tǒng),但研發(fā)同學(xué)每人每天都會(huì)接收到很多告警,導(dǎo)致重要的告警被淹沒,部分同學(xué)會(huì)選擇直接屏蔽掉所有告警,進(jìn)一步加重問題。告警過多等同于沒有告警。
另外,多個(gè)告警之間通常具有一定的關(guān)聯(lián)性,如:SQL執(zhí)行錯(cuò)誤告警導(dǎo)致異常日志過多告警。而面對(duì)雜亂無章的告警,很難快速分析出告警的根本原因。
告警降噪治理十分重要,在此背景下,我們基于Alertmanager擴(kuò)展研發(fā)了轉(zhuǎn)轉(zhuǎn)告警中心。
二、規(guī)范與SDK
2.1 發(fā)送告警
Alertmanager提供了告警發(fā)送的OpenAPI,其中,告警的labels用于識(shí)別同一條告警并對(duì)告警去重、降噪,相同labels的告警的annotations會(huì)被覆蓋。startsAt與endsAt分別為告警發(fā)生時(shí)間與結(jié)束時(shí)間。
一條告警從提交到發(fā)送再到接收人的流程大致如下圖所示,其中,Alertmanager需要集群部署來保證高可用性,需要注意的是,發(fā)送告警時(shí)不能對(duì)集群做負(fù)載均衡,必須要對(duì)集群內(nèi)所有的Alertmanager發(fā)送告警才能保證高可用性。
2.2 常用標(biāo)簽
Alertmanager為基于標(biāo)簽的告警降噪,需提前規(guī)范告警常見標(biāo)簽。
- ENV:環(huán)境,如:線上環(huán)境、測(cè)試環(huán)境
- APP:服務(wù)名
- SOURCE:告警來源,如:日志告警、JVM告警
- NAME:告警名稱
- LEVEL:告警等級(jí),如:P0告警、P5告警
- INSTANCE:告警實(shí)例IP
- RECEIVER_TYPE:告警接受者類型
- RECEIVER:告警接受者,與RECEIVER_TYPE配合使用,如RECEIVER_TYPE=郵件,RECEIVER即為郵箱地址。
Alertmanager標(biāo)簽名的正則規(guī)則為??[a-zA-Z_][a-zA-Z0-9_]*?
?,在真正發(fā)送通知時(shí),最好將標(biāo)簽名做一次中文映射轉(zhuǎn)換。
2.3 SDK
我們針對(duì)Alertmanager開發(fā)了發(fā)送告警的SDK,如下所示,發(fā)送告警非常簡(jiǎn)單,SDK默認(rèn)會(huì)為每條告警自動(dòng)增加服務(wù)名、環(huán)境、IP、告警等級(jí),并按照接收方拆開為多條告警發(fā)送。每一項(xiàng)內(nèi)容都是標(biāo)簽,其中value較為特殊,放在了annotations內(nèi),其他均放在了labels內(nèi)用于唯一識(shí)別一條告警。
三、告警降噪
3.1 分組去重
分組機(jī)制可以將多條告警信息合并成一個(gè)通知。例如,當(dāng)集群中有數(shù)百個(gè)正在運(yùn)行的服務(wù)實(shí)例,假如此時(shí)發(fā)生了網(wǎng)絡(luò)故障,結(jié)果就會(huì)有數(shù)百個(gè)告警被發(fā)送到Alertmanager。
而作為用戶,可能只希望能夠在一個(gè)通知中就能查看哪些服務(wù)實(shí)例受到影響。這時(shí)可以按照服務(wù)所在集群或者告警名稱對(duì)告警進(jìn)行分組,將這些告警聚合在一起成為一個(gè)通知。
Alertmanager可以將收到的告警按照特定的標(biāo)簽分組、去重,并基于以下參數(shù)決定何時(shí)發(fā)送組內(nèi)的告警通知,Alertmanager的每一次通知都會(huì)包含當(dāng)前組內(nèi)的所有告警。
- 初始等待時(shí)間(group_wait):一組告警第一次發(fā)送之前等待的時(shí)間,用于等待同一組的更多告警合并發(fā)送。
- 變化等待時(shí)間(group_interval):一組已發(fā)送初始通知的告警在接收到新告警或有告警恢復(fù)后,再次發(fā)送通知前等待的時(shí)間。
- 重復(fù)等待時(shí)間(repeat_interval):一組已發(fā)送初始通知的告警,組內(nèi)告警均沒有恢復(fù)且沒有新增告警,再次發(fā)送通知前等待的時(shí)間。
下面以一張圖,來展示從告警產(chǎn)生到合并到某個(gè)集合中,到發(fā)送通知的整個(gè)過程。三角形和圓形表示不斷產(chǎn)生的告警,矩形代表實(shí)際的通知時(shí)間以及告警內(nèi)容。
3.2 恢復(fù)通知
Alertmanager自帶恢復(fù)通知,默認(rèn)5m沒有收到告警后,告警將被認(rèn)為恢復(fù),然后會(huì)等待group_interval后通知給用戶。發(fā)送告警時(shí)也可以指定告警恢復(fù)時(shí)間,如下所示:
需要注意的是,endTime如果小于當(dāng)前時(shí)間,會(huì)認(rèn)為告警在發(fā)出時(shí)就已經(jīng)恢復(fù),這條告警不會(huì)通知。
3.3 告警分級(jí)
我們將告警分為P0~P5六個(gè)等級(jí),告警等級(jí)默認(rèn)取決于服務(wù)重要性,轉(zhuǎn)轉(zhuǎn)服務(wù)按照重要性分了A、B、C、D、E五個(gè)等級(jí),服務(wù)重要性與告警等級(jí)的對(duì)應(yīng)關(guān)系:A → P1,B → P2,C → P3,D → P4,E → P5。發(fā)送告警時(shí)也可以指定告警等級(jí),如下:
告警分級(jí)的目的是盡量讓高等級(jí)的告警及時(shí)發(fā)出,低等級(jí)的告警減少用戶打擾次數(shù)。不同等級(jí)告警的分組、去重時(shí)間均不相同。
如:P4/P5的告警初始時(shí)會(huì)等待3m收集告警,并將當(dāng)前告警接收者的所有告警匯總到一條通知內(nèi);
P0的告警只會(huì)等待15s收集告警,并按照告警接收者、環(huán)境、服務(wù)名、告警來源、告警名稱為維度拆分成多個(gè)通知。
告警等級(jí) | 分組標(biāo)簽 | group_wait | group_interval | repeat_interval |
P0 | 告警接收者、環(huán)境、服務(wù)名、告警來源、告警名稱 | 15s | 1m | 30m |
P1 | 告警接收者、環(huán)境、服務(wù)名、告警來源 | 30s | 5m | 1h |
P2 | 告警接收者、環(huán)境、服務(wù)名 | 1m | 5m | 1h |
P3 | 告警接收者、環(huán)境 | 2m | 10m | 2h |
P4/P5 | 告警接收者 | 3m | 10m | 4h |
3.4 通知合并
統(tǒng)一使用Alertmanager webhook通知,一次通知內(nèi)容會(huì)包含分組內(nèi)的多個(gè)報(bào)警,我們會(huì)按照告警相似度對(duì)告警做合并,如下為6條報(bào)警合并成一條通知,其中,告警值與服務(wù)實(shí)例一一對(duì)應(yīng)。
定義相似度:對(duì)于多個(gè)報(bào)警的labels,只有一個(gè)label value不一樣,剩余的label key與label value均相同,則認(rèn)為相似并合并;一次Alertmanager webhook通知可按照相似度拆分成多種告警,不同的告警提取公共標(biāo)簽,最終推送到一條通知內(nèi)。
如下,為4條告警合并到一條通知,可清晰的看到兩臺(tái)機(jī)器的異常日志報(bào)警的原因是由于Druid執(zhí)行SQL錯(cuò)誤導(dǎo)致。
3.5 告警抑制
抑制是指當(dāng)某一告警發(fā)出后,可以停止重復(fù)發(fā)送由此告警引發(fā)的其它告警的機(jī)制。
當(dāng)同一個(gè)服務(wù)、環(huán)境、告警來源、IP、接受者、告警名稱,同時(shí)出現(xiàn)多個(gè)等級(jí)的告警時(shí),高等級(jí)的告警會(huì)抑制低等級(jí)告警的通知。
如:告警名稱為FGC次數(shù),P1告警閾值為20次,P2告警為10次,當(dāng)某個(gè)實(shí)例的FGC次數(shù)達(dá)到20次以上時(shí),只會(huì)發(fā)送P1告警,不會(huì)發(fā)送P2告警。
四、多通知機(jī)制
支持企業(yè)微信、企業(yè)微信群、短信、郵件、電話、WebHook,可在一個(gè)告警內(nèi)同時(shí)指定多種接收方式,我們會(huì)自動(dòng)按照接收人拆分成多條告警。
- 企業(yè)微信、企業(yè)微信群、郵件、WebHook:最詳細(xì),發(fā)送告警與恢復(fù)通知。
- 短信:相對(duì)以上,只是不會(huì)發(fā)送恢復(fù)通知。
- 電話:不會(huì)發(fā)送恢復(fù)通知,并且只會(huì)播報(bào)報(bào)警標(biāo)題與告警服務(wù)名。
五、未恢復(fù)告警
為了防止告警過多時(shí)淹沒了重要告警,在每條告警的最后,都提供了一個(gè)未恢復(fù)告警鏈接,用于實(shí)時(shí)查詢當(dāng)前未恢復(fù)的告警。
未恢復(fù)告警擁有三種狀態(tài):活躍、靜默、抑制。其中,活躍狀態(tài)可以設(shè)置靜默,靜默狀態(tài)可以查看被誰靜默。
六、靜默告警
基于Alertmanager OpenAPI,支持基于標(biāo)簽的靜默告警,每條告警通知內(nèi)都提供了一個(gè)鏈接用于快速靜默,也可以在未恢復(fù)告警內(nèi)靜默告警。
點(diǎn)擊新增靜默后,會(huì)自動(dòng)補(bǔ)充靜默匹配的標(biāo)簽項(xiàng),也可以增減標(biāo)簽項(xiàng),如:去掉INSTANCE標(biāo)簽維度以便匹配所有的機(jī)器,修改_RECEIVER為其他人等。需要注意的是,添加靜默時(shí)RECEIVER必須要指定。
添加完成后,會(huì)自動(dòng)跳轉(zhuǎn)到靜默列表,并展示剛剛添加的靜默項(xiàng)。
在靜默列表內(nèi)可查詢所有的活躍、過期的靜默項(xiàng),可編輯、刪除、查看影響的告警。
查看受影響的告警為實(shí)時(shí)查詢,如果當(dāng)前靜默沒有匹配到任何告警,查詢結(jié)果會(huì)為空。
七、告警歷史
告警通知給用戶后,我們會(huì)保留三個(gè)月的歷史告警記錄列表。
八、總結(jié)
Alertmanager提供了告警降噪的策略,我們?cè)贏lertmanager的基礎(chǔ)上制定了標(biāo)簽規(guī)范、告警分級(jí)降噪、分級(jí)抑制、告警合并,并基于Alertmanager OpenAPI擴(kuò)展了未恢復(fù)告警、靜默告警、告警歷史。Alertmanager雖然不是告警降噪的銀彈,但也可以解決大部分問題,如果你也面臨著告警轟炸的問題,可以嘗試一下。
關(guān)于作者
苑沖,轉(zhuǎn)轉(zhuǎn)架構(gòu)部存儲(chǔ)服務(wù)負(fù)責(zé)人,主要負(fù)責(zé)MQ、監(jiān)控系統(tǒng)、Redis、KV存儲(chǔ)等。愛學(xué)習(xí),喜歡以辯證思維與變化思維思考。