文章來源:愛可生雲數據庫 :https://www.jianshu.com/p/af0f98fe7699
作者:張沈波
【1】本文主講

Prometheus+Grafana是監控告警解決方案里的后起之秀,比如大家熟悉的PMM,就是使用了這個方案;前不久羅老師在3306pi公眾號上就寫過完整的使用教程《構建狂拽炫酷屌的MySQL 監控平台》,所以我們在這里就不再贅述具體如何搭建使用。
今天我們聊一些Prometheus幾個有意思的特性,這些特性能幫助大家更深入的了解Prometheus的一條告警是怎么觸發的;本文提綱如下:
1.監控采集,計算和告警
2.告警分組,抑制和靜默
3.告警延時
【2】 監控采集、計算和告警
Prometheus以scrape_interval(默認為1m)規則周期,從監控目標上收集信息。其中scrape_interval可以基於全局或基於單個metric定義;然后將監控信息持久存儲在其本地存儲上。
Prometheus以evaluation_interval(默認為1m)另一個獨立的規則周期,對告警規則做定期計算。其中evaluation_interval只有全局值;然后更新告警狀態。
【2.1】告警的3種狀態
其中包含三種告警狀態:
inactive:沒有觸發閾值
pending:已觸發閾值但未滿足告警持續時間
firing:已觸發閾值且滿足告警持續時間
舉一個例子,閾值告警的配置如下:

· 收集到的mysql_uptime>=30,告警狀態為inactive
· 收集到的mysql_uptime<30,且持續時間小於10s,告警狀態為pending
· 收集到的mysql_uptime<30,且持續時間大於10s,告警狀態為firing
⚠ 注意:配置中的for語法就是用來設置告警持續時間的;如果配置中不設置for或者設置為0,那么pending狀態會被直接跳過。
【2.2】計算告警閥值持續時間
那么怎么來計算告警閾值持續時間呢,需要回到上文的scrape_interval和evaluation_interval,假設scrape_interval為5s采集一次信息;
evaluation_interval為10s;mysql_uptime告警閾值需要滿足10s持續時間。

如上圖所示:
1.Prometheus以5s(scrape_interval)一個采集周期采集狀態;
2.然后根據采集到狀態按照10s(evaluation_interval)一個計算周期,計算表達式;
3.表達式為真,告警狀態切換到pending;
4.下個計算周期,表達式仍為真,且符合for持續10s,告警狀態變更為active,並將告警從Prometheus發送給Altermanger;
5.下個計算周期,表達式仍為真,且符合for持續10s,持續告警給Altermanger;
6.直到某個計算周期,表達式為假,告警狀態變更為inactive,發送一個resolve給Altermanger,說明此告警已解決。
【3】 告警分組、抑制、靜默
【3.1】告警架構圖
第一節我們成功的把一條mysql_uptime的告警發送給了Altermanger;但是Altermanger並不是把一條從Prometheus接收到的告警簡簡單單的直接發送出去;直接發送出去會導致告警信息過多,運維人員會被告警淹沒;所以Altermanger需要對告警做合理的收斂。

如上圖,藍色框標柱的分別為告警的接收端和發送端;這張Altermanger的架構圖里,可以清晰的看到,中間還會有一系列復雜且重要的流程,等待着我們的mysql_uptime告警。
【4】告警收斂的3種手段
下面我們來講Altermanger非常重要的告警收斂手段。
· 分組:group
· 抑制:inhibitor
· 靜默:silencer

1.告警分組 group
告警分組的作用
·同類告警的聚合幫助運維排查問題
·通過告警郵件的合並,減少告警數量
舉例來說:我們按照mysql的實例id對告警分組;如下圖所示,告警信息會被拆分成兩組。
·mysql-A
mysql_cpu_high
·mysql-B
mysql_uptime
mysql_slave_sql_thread_down
mysql_slave_io_thread_down
實例A分組下的告警會合並成一個告警郵件發送;
實例B分組下的告警會合並成一個告警郵件發送;
通過分組合並,能幫助運維降低告警數量,同時能有效聚合告警信息,幫助問題分析。

2.告警抑制inhibitor
告警抑制的作用
·消除冗余的告警
舉例來說:同一台server-A的告警,如果有如下兩條告警,並且配置了抑制規則。
· mysql_uptime
· server_uptime
最后只會收到一條server_uptime的告警。
A機器掛了,勢必導致A服務器上的mysql也掛了;如配置了抑制規則,通過服務器down來抑制這台服務器上的其他告警;這樣就能消除冗余的告警,幫助運維第一時間掌握最核心的告警信息。

3.告警靜默silencer
告警靜默的作用
·阻止發送可預期的告警
舉例來說:夜間跑批時間,批量任務會導致實例A壓力升高;我們配置了對實例A的靜默規則。
·mysql-A
qps_more_than_3000
tps_more_than_2000
thread_running_over_200
·mysql-B
thread_running_over_200
最后我們只會收到一條實例B的告警。
A壓力高是可預期的,周期性的告警會影響運維判斷;這種場景下,運維需要聚焦處理實例B的問題即可。

4.收斂小結
這一節,我們mysql_uptime同學從Prometheus被出發后,進入了Altermanger的內部流程,並沒有如預期的被順利告出警來;它會先被分組,被抑制掉,被靜默掉;之所以這么做,是因為我們的運維同學很忙很忙,精力非常有限;只有mysql_uptime同學證明自己是非常重要的,我們才安排它和運維同學會面。
【5】告警延時
第二節我們提到了分組的概念,分組勢必會帶來延時;合理的配置延時,才能避免告警不及時的問題,同時幫助我們避免告警轟炸的問題。
我們先來看告警延時的幾個重要參數:
告警延時的核心參數
group_by:分組參數,第二節已經介紹,比如按照[mysql-id]分組
group_wait:分組等待時間,比如:5s
group_interval:分組嘗試再次發送告警的時間間隔,比如:5m
Repeat_interval: 分組內發送相同告警的時間間隔,比如:60m
延時參數主要作用在Altermanger的Dedup階段,如圖:

1.延時的三個參數
我們還是舉例來說,假設如下:
·配置了延時參數:
group_wait:5s
group_interval:5m
repeat_interval: 60m
·有同組告警集A,如下:
a1
a2
a3
·有同組告警集B,如下:
b1
b2
場景一:
a1先到達告警系統,此時在group_wait:5s的作用下,a1不會立刻告出來,a1等待5s,下一刻a2在5s內也觸發,a1,a2會在5s后合並為一個分組,通過一個告警消息發出來;
a1,a2持續未解決,它們會在repeat_interval: 60m的作用下,每隔一小時發送告警消息。

場景二:
a1,a2持續未解決,中間又有新的同組告警a3出現,此時在group_interval:5m的作用下,由於同組的狀態發生變化,a1,a2,a3會在5min中內快速的告知運維,不會被收斂60min(repeat_interval)的時間;
a1,a2,a3如持續無變化,它們會在repeat_interval: 60m的作用下,再次每隔一小時發送告警消息。

場景三:
a1,a2發生的過程中,發生了b1的告警,由於b1分組規則不在集合A中,所以b1遵循集合B的時間線;
b1發生后發生了b2,b1,b2按照類似集合A的延時規則收斂,但是時間線獨立。
原文:

2.延時小結
通過三個延時參數,告警實現了分組等待的合並發送(group_wait),未解決告警的重復提醒(repeat_interval),分組變化后快速提醒(group_interval)。
總結
本文通過監控信息的周期性采集、告警公式的周期性計算、合並同類告警的分組、減少冗余告警的抑制、降低可預期告警的靜默、同時配合三個延時參數,講解了Prometheus的一條告警是怎么觸發的;當然對於Prometheus,還有很多特性可以實踐;如您有興趣,歡迎聯系我們,我們是愛可生。
作者:愛可生開源社區
鏈接:https://www.jianshu.com/p/af0f98fe7699
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。