導航:這里主要是列出一個prometheus一些系統的學習過程,最后按照章節順序查看,由於寫作該文檔經歷了不同時期,所以在文中有時出現 的雲環境不統一,但是學習具體使用方法即可,在最后的篇章,有一個完整的騰訊雲的實戰案例。 8.kube-state-metrics 和 metrics-server 13.Grafana簡單用法 參考: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config https://www.bookstack.cn/read/prometheus_practice/introduction-README.md |
本章我們將探索Prometheus的告警處理機制,告警能力在Prometheus的架構中被划分為兩個部分,在Prometheus Server中定義告警規則以及產生告警,Alertmanager組件則用於處理這些由Prometheus產生的告警。Alertmanager即Prometheus體系中告警的統一處理中心。Alertmanager提供了多種內置第三方告警通知方式,同時還提供了對Webhook通知的支持,通過Webhook用戶可以完成對告警更多個性化的擴展。
本章主要內容:
- 在Prometheus中自定義告警規則
- 理解Alertmanager特性
- 基於標簽的動態告警處理
- 將告警通知發送到第三方服務
- 如何使用Webhook擴展Alertmanager
- 以及一些其他的性能優化模式
1.Prometheus告警簡介
告警能力在Prometheus的架構中被划分成兩個獨立的部分。如下所示,通過在Prometheus中定義AlertRule(告警規則),Prometheus會周期性的對告警規則進行計算,如果滿足告警觸發條件就會向Alertmanager發送告警信息。
Prometheus告警處理
在Prometheus中一條告警規則主要由以下幾部分組成:
- 告警名稱:用戶需要為告警規則命名,當然對於命名而言,需要能夠直接表達出該告警的主要內容
- 告警規則:告警規則實際上主要由PromQL進行定義,其實際意義是當表達式(PromQL)查詢結果持續多長時間(During)后出發告警
在Prometheus中,還可以通過Group(告警組)對一組相關的告警進行統一定義。當然這些定義都是通過YAML文件來統一管理的。
Alertmanager作為一個獨立的組件,負責接收並處理來自Prometheus Server(也可以是其它的客戶端程序)的告警信息。Alertmanager可以對這些告警信息進行進一步的處理,比如當接收到大量重復告警時能夠消除重復的告警信息,同時對告警信息進行分組並且路由到正確的通知方,Prometheus內置了對郵件,Slack等多種通知方式的支持,同時還支持與Webhook的集成,以支持更多定制化的場景。例如,目前Alertmanager還不支持釘釘,那用戶完全可以通過Webhook與釘釘機器人進行集成,從而通過釘釘接收告警信息。同時AlertManager還提供了靜默和告警抑制機制來對告警通知行為進行優化。
2.Alertmanager特性
Alertmanager除了提供基本的告警通知能力以外,還主要提供了如:分組、抑制以及靜默等告警特性:
2.1 分組
分組機制可以將詳細的告警信息合並成一個通知。在某些情況下,比如由於系統宕機導致大量的告警被同時觸發,在這種情況下分組機制可以將這些被觸發的告警合並為一個告警通知,避免一次性接受大量的告警通知,而無法對問題進行快速定位。
例如,當集群中有數百個正在運行的服務實例,並且為每一個實例設置了告警規則。假如此時發生了網絡故障,可能導致大量的服務實例無法連接到數據庫,結果就會有數百個告警被發送到Alertmanager。
而作為用戶,可能只希望能夠在一個通知中中就能查看哪些服務實例收到影響。這時可以按照服務所在集群或者告警名稱對告警進行分組,而將這些告警內聚在一起成為一個通知。
告警分組,告警時間,以及告警的接受方式可以通過Alertmanager的配置文件進行配置。
2.2 抑制
抑制是指當某一告警發出后,可以停止重復發送由此告警引發的其它告警的機制。
例如,當集群不可訪問時觸發了一次告警,通過配置Alertmanager可以忽略與該集群有關的其它所有告警。這樣可以避免接收到大量與實際問題無關的告警通知。
抑制機制同樣通過Alertmanager的配置文件進行設置。
2.3 靜默
靜默提供了一個簡單的機制可以快速根據標簽對告警進行靜默處理。如果接收到的告警符合靜默的配置,Alertmanager則不會發送告警通知。
靜默設置需要在Alertmanager的Werb頁面上進行設置。
3.自定義Prometheus告警規則
Prometheus中的告警規則允許你基於PromQL表達式定義告警觸發條件,Prometheus后端對這些觸發規則進行周期性計算,當滿足觸發條件后則會觸發告警通知。默認情況下,用戶可以通過Prometheus的Web界面查看這些告警規則以及告警的觸發狀態。當Promthues與Alertmanager關聯之后,可以將告警發送到外部服務如Alertmanager中並通過Alertmanager可以對這些告警進行進一步的處理。
3.1定義告警規則
一條典型的告警規則如下所示:
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 description: description info
在告警規則文件中,我們可以將一組相關的規則設置定義在一個group下。在每一個group中我們可以定義多個告警規則(rule)。一條告警規則主要由以下幾部分組成:
- alert:告警規則的名稱。
- expr:基於PromQL表達式告警觸發條件,用於計算是否有時間序列滿足該條件。
- for:評估等待時間,可選參數。用於表示只有當觸發條件持續一段時間后才發送告警。在等待期間新產生告警的狀態為pending。
- labels:自定義標簽,允許用戶指定要附加到告警上的一組附加標簽。
- annotations:用於指定一組附加信息,比如用於描述告警詳細信息的文字等,annotations的內容在告警產生時會一同作為參數發送到Alertmanager。
為了能夠讓Prometheus能夠啟用定義的告警規則,我們需要在Prometheus全局配置文件中通過rule_files指定一組告警規則文件的訪問路徑,Prometheus啟動后會自動掃描這些路徑下規則文件中定義的內容,並且根據這些規則計算是否向外部發送通知:
rule_files:
[ - <filepath_glob> ... ]
默認情況下Prometheus會每分鍾對這些告警規則進行計算,如果用戶想定義自己的告警計算周期,則可以通過evaluation_interval來覆蓋默認的計算周期:
global: [ evaluation_interval: <duration> | default = 1m ]
3.2 模板化
一般來說,在告警規則文件的annotations中使用summary描述告警的概要信息,description用於描述告警的詳細信息。同時Alertmanager的UI也會根據這兩個標簽值,顯示告警信息。為了讓告警信息具有更好的可讀性,Prometheus支持模板化label和annotations的中標簽的值。
通過$labels.<labelname>變量可以訪問當前告警實例中指定標簽的值。$value則可以獲取當前PromQL表達式計算的樣本值。
# To insert a firing element's label values: {{ $labels.<labelname> }} # To insert the numeric expression value of the firing element: {{ $value }}
例如,可以通過模板化優化summary以及description的內容的可讀性:
groups: - name: example rules: # Alert for any instance that is unreachable for >5 minutes. - 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 for any instance that has a median request latency >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)"
3.3查看告警狀態
如下所示,用戶可以通過Prometheus WEB界面中的Alerts菜單查看當前Prometheus下的所有告警規則,以及其當前所處的活動狀態。
告警活動狀態
同時對於已經pending或者firing的告警,Prometheus也會將它們存儲到時間序列ALERTS{}中。
可以通過表達式,查詢告警實例:
ALERTS{alertname="<alert name>", alertstate="pending|firing", <additional alert labels>}
樣本值為1表示當前告警處於活動狀態(pending或者firing),當告警從活動狀態轉換為非活動狀態時,樣本值則為0。
3.4 實例:定義主機監控告警
修改Prometheus配置文件prometheus.yml,添加以下配置:
rule_files:
- /etc/prometheus/rules/*.rules
在目錄/etc/prometheus/rules/下創建告警文件hoststats-alert.rules內容如下:
groups: - name: hostStatsAlert rules: - alert: hostCpuUsageAlert expr: sum(avg without (cpu)(irate(node_cpu{mode!='idle'}[5m]))) by (instance) > 0.85 for: 1m labels: severity: page annotations: summary: "Instance {{ $labels.instance }} CPU usgae high" description: "{{ $labels.instance }} CPU usage above 85% (current value: {{ $value }})" - alert: hostMemUsageAlert expr: (node_memory_MemTotal - node_memory_MemAvailable)/node_memory_MemTotal > 0.85 for: 1m labels: severity: page annotations: summary: "Instance {{ $labels.instance }} MEM usgae high" description: "{{ $labels.instance }} MEM usage above 85% (current value: {{ $value }})"
重啟Prometheus后訪問Prometheus UIhttp://127.0.0.1:9090/rules可以查看當前以加載的規則文件。
告警規則
切換到Alerts標簽http://127.0.0.1:9090/alerts可以查看當前告警的活動狀態。
告警活動狀態
此時,我們可以手動拉高系統的CPU使用率,驗證Prometheus的告警流程,在主機上運行以下命令:
cat /dev/zero>/dev/null
運行命令后查看CPU使用率情況,如下圖所示:
Prometheus首次檢測到滿足觸發條件后,hostCpuUsageAlert顯示由一條告警處於活動狀態。由於告警規則中設置了1m的等待時間,當前告警狀態為PENDING,如下圖所示:
如果1分鍾后告警條件持續滿足,則會實際觸發告警並且告警狀態為FIRING,如下圖所示:
在這一小節中介紹了如何配置和使用Prometheus提供的告警能力,並且嘗試實現了對主機CPU以及內存的告警規則設置。目前為止,我們只能通過Prometheus UI查看當前告警的活動狀態。接下來,接下來我們將嘗試利用Prometheus體系中的另一個組件Alertmanager對這些觸發的告警進行處理,實現告警通知。
4.部署AlertManager
Alertmanager和Prometheus Server一樣均采用Golang實現,並且沒有第三方依賴。一般來說我們可以通過以下幾種方式來部署Alertmanager:二進制包、容器以及源碼方式安裝。
4.1 使用二進制包部署AlertManager
獲取並安裝軟件包
Alertmanager最新版本的下載地址可以從Prometheus官方網站https://prometheus.io/download/獲取。
export VERSION=0.15.2 curl -LO https://github.com/prometheus/alertmanager/releases/download/v$VERSION/alertmanager-$VERSION.darwin-amd64.tar.gz tar xvf alertmanager-$VERSION.darwin-amd64.tar.gz
創建alertmanager配置文件
Alertmanager解壓后會包含一個默認的alertmanager.yml配置文件,內容如下所示:
global: resolve_timeout: 5m route: group_by: ['alertname'] group_wait: 10s group_interval: 10s repeat_interval: 1h receiver: 'web.hook' receivers: - name: 'web.hook' webhook_configs: - url: 'http://127.0.0.1:5001/' inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['alertname', 'dev', 'instance']
Alertmanager的配置主要包含兩個部分:路由(route)以及接收器(receivers)。所有的告警信息都會從配置中的頂級路由(route)進入路由樹,根據路由規則將告警信息發送給相應的接收器。
在Alertmanager中可以定義一組接收器,比如可以按照角色(比如系統運維,數據庫管理員)來划分多個接收器。接收器可以關聯郵件,Slack以及其它方式接收告警信息。
當前配置文件中定義了一個默認的接收者default-receiver由於這里沒有設置接收方式,目前只相當於一個占位符。關於接收器的詳細介紹會在后續章節介紹。
在配置文件中使用route定義了頂級的路由,路由是一個基於標簽匹配規則的樹狀結構。所有的告警信息從頂級路由開始,根據標簽匹配規則進入到不同的子路由,並且根據子路由設置的接收器發送告警。目前配置文件中只設置了一個頂級路由route並且定義的接收器為default-receiver。因此,所有的告警都會發送給default-receiver。關於路由的詳細內容會在后續進行詳細介紹。
啟動Alertmanager
Alermanager會將數據保存到本地中,默認的存儲路徑為data/。因此,在啟動Alertmanager之前需要創建相應的目錄:
./alertmanager
用戶也在啟動Alertmanager時使用參數修改相關配置。--config.file用於指定alertmanager配置文件路徑,--storage.path用於指定數據存儲路徑。
查看運行狀態
Alertmanager啟動后可以通過9093端口訪問,http://192.168.33.10:9093
Alertmanager頁面
Alert菜單下可以查看Alertmanager接收到的告警內容。Silences菜單下則可以通過UI創建靜默規則,這部分我們會在后續部分介紹。進入Status菜單,可以看到當前系統的運行狀態以及配置信息。
4.2 關聯Prometheus與Alertmanager
在Prometheus的架構中被划分成兩個獨立的部分。Prometheus負責產生告警,而Alertmanager負責告警產生后的后續處理。因此Alertmanager部署完成后,需要在Prometheus中設置Alertmanager相關的信息。
編輯Prometheus配置文件prometheus.yml,並添加以下內容
alerting: alertmanagers: - static_configs: - targets: ['localhost:9093']
重啟Prometheus服務,成功后,可以從http://192.168.33.10:9090/config查看alerting配置是否生效。
此時,再次嘗試手動拉高系統CPU使用率:
cat /dev/zero>/dev/null
等待Prometheus告警進行觸發狀態:
查看Alertmanager UI此時可以看到Alertmanager接收到的告警信息。
目前為止,已經成功安裝部署了Alertmanager並且與Prometheus關聯,能夠正常接收來自Prometheus的告警信息。接下來將詳細介紹Alertmanager是如何處理這些接收到的告警信息的。
5.Alertmanager配置概述
在上面的部分中已經簡單介紹過,在Alertmanager中通過路由(Route)來定義告警的處理方式。路由是一個基於標簽匹配的樹狀匹配結構。根據接收到告警的標簽匹配相應的處理方式。這里將詳細介紹路由相關的內容。
Alertmanager主要負責對Prometheus產生的告警進行統一處理,因此在Alertmanager配置中一般會包含以下幾個主要部分:
- 全局配置(global):用於定義一些全局的公共參數,如全局的SMTP配置,Slack配置等內容;
- 模板(templates):用於定義告警通知時的模板,如HTML模板,郵件模板等;
- 告警路由(route):根據標簽匹配,確定當前告警應該如何處理;
- 接收人(receivers):接收人是一個抽象的概念,它可以是一個郵箱也可以是微信,Slack或者Webhook等,接收人一般配合告警路由使用;
- 抑制規則(inhibit_rules):合理設置抑制規則可以減少垃圾告警的產生
其完整配置格式如下:
global: [ resolve_timeout: <duration> | default = 5m ] [ smtp_from: <tmpl_string> ] [ smtp_smarthost: <string> ] [ smtp_hello: <string> | default = "localhost" ] [ smtp_auth_username: <string> ] [ smtp_auth_password: <secret> ] [ smtp_auth_identity: <string> ] [ smtp_auth_secret: <secret> ] [ smtp_require_tls: <bool> | default = true ] [ slack_api_url: <secret> ] [ victorops_api_key: <secret> ] [ victorops_api_url: <string> | default = "https://alert.victorops.com/integrations/generic/20131114/alert/" ] [ pagerduty_url: <string> | default = "https://events.pagerduty.com/v2/enqueue" ] [ opsgenie_api_key: <secret> ] [ opsgenie_api_url: <string> | default = "https://api.opsgenie.com/" ] [ hipchat_api_url: <string> | default = "https://api.hipchat.com/" ] [ hipchat_auth_token: <secret> ] [ wechat_api_url: <string> | default = "https://qyapi.weixin.qq.com/cgi-bin/" ] [ wechat_api_secret: <secret> ] [ wechat_api_corp_id: <string> ] [ http_config: <http_config> ] templates: [ - <filepath> ... ] route: <route> receivers: - <receiver> ... inhibit_rules: [ - <inhibit_rule> ... ]
在全局配置中需要注意的是resolve_timeout,該參數定義了當Alertmanager持續多長時間未接收到告警后標記告警狀態為resolved(已解決)。該參數的定義可能會影響到告警恢復通知的接收時間,讀者可根據自己的實際場景進行定義,其默認值為5分鍾。在接下來的部分,將已一些實際的例子解釋Alertmanager的其它配置內容。
6.基於標簽的告警處理路由
在Alertmanager的配置中會定義一個基於標簽匹配規則的告警路由樹,以確定在接收到告警后Alertmanager需要如何對其進行處理:
route: <route>
其中route中則主要定義了告警的路由匹配規則,以及Alertmanager需要將匹配到的告警發送給哪一個receiver,一個最簡單的route定義如下所示:
route: group_by: ['alertname'] receiver: 'web.hook' receivers: - name: 'web.hook' webhook_configs: - url: 'http://127.0.0.1:5001/'
如上所示:在Alertmanager配置文件中,我們只定義了一個路由,那就意味着所有由Prometheus產生的告警在發送到Alertmanager之后都會通過名為web.hook的receiver接收。這里的web.hook定義為一個webhook地址。當然實際場景下,告警處理可不是這么簡單的一件事情,對於不同級別的告警,我們可能會有完全不同的處理方式,因此在route中,我們還可以定義更多的子Route,這些Route通過標簽匹配告警的處理方式,route的完整定義如下:
[ receiver: <string> ] [ group_by: '[' <labelname>, ... ']' ] [ continue: <boolean> | default = false ] match: [ <labelname>: <labelvalue>, ... ] match_re: [ <labelname>: <regex>, ... ] [ group_wait: <duration> | default = 30s ] [ group_interval: <duration> | default = 5m ] [ repeat_interval: <duration> | default = 4h ] routes: [ - <route> ... ]
6.1 路由匹配
每一個告警都會從配置文件中頂級的route進入路由樹,需要注意的是頂級的route必須匹配所有告警(即不能有任何的匹配設置match和match_re),每一個路由都可以定義自己的接受人以及匹配規則。默認情況下,告警進入到頂級route后會遍歷所有的子節點,直到找到最深的匹配route,並將告警發送到該route定義的receiver中。但如果route中設置continue的值為false,那么告警在匹配到第一個子節點之后就直接停止。如果continue為true,報警則會繼續進行后續子節點的匹配。如果當前告警匹配不到任何的子節點,那該告警將會基於當前路由節點的接收器配置方式進行處理。
其中告警的匹配有兩種方式可以選擇。一種方式基於字符串驗證,通過設置match規則判斷當前告警中是否存在標簽labelname並且其值等於labelvalue。第二種方式則基於正則表達式,通過設置match_re驗證當前告警標簽的值是否滿足正則表達式的內容。
如果警報已經成功發送通知, 如果想設置發送告警通知之前要等待時間,則可以通過repeat_interval參數進行設置。
6.2 告警分組
在之前的部分有講過,Alertmanager可以對告警通知進行分組,將多條告警合合並為一個通知。這里我們可以使用group_by來定義分組規則。基於告警中包含的標簽,如果滿足group_by中定義標簽名稱,那么這些告警將會合並為一個通知發送給接收器。
有的時候為了能夠一次性收集和發送更多的相關信息時,可以通過group_wait參數設置等待時間,如果在等待時間內當前group接收到了新的告警,這些告警將會合並為一個通知向receiver發送。
而group_interval配置,則用於定義相同的Group之間發送告警通知的時間間隔。
例如,當使用Prometheus監控多個集群以及部署在集群中的應用和數據庫服務,並且定義以下的告警處理路由規則來對集群中的異常進行通知。
route: receiver: 'default-receiver' group_wait: 30s group_interval: 5m repeat_interval: 4h group_by: [cluster, alertname] routes: - receiver: 'database-pager' group_wait: 10s match_re: service: mysql|cassandra - receiver: 'frontend-pager' group_by: [product, environment] match: team: frontend
默認情況下所有的告警都會發送給集群管理員default-receiver,因此在Alertmanager的配置文件的根路由中,對告警信息按照集群以及告警的名稱對告警進行分組。
如果告警時來源於數據庫服務如MySQL或者Cassandra,此時則需要將告警發送給相應的數據庫管理員(database-pager)。這里定義了一個單獨子路由,如果告警中包含service標簽,並且service為MySQL或者Cassandra,則向database-pager發送告警通知,由於這里沒有定義group_by等屬性,這些屬性的配置信息將從上級路由繼承,database-pager將會接收到按cluster和alertname進行分組的告警通知。
而某些告警規則來源可能來源於開發團隊的定義,這些告警中通過添加標簽team來標示這些告警的創建者。在Alertmanager配置文件的告警路由下,定義單獨子路由用於處理這一類的告警通知,如果匹配到告警中包含標簽team,並且team的值為frontend,Alertmanager將會按照標簽product和environment對告警進行分組。此時如果應用出現異常,開發團隊就能清楚的知道哪一個環境(environment)中的哪一個應用程序出現了問題,可以快速對應用進行問題定位。
7.使用Receiver接收告警信息
前上一小節已經講過,在Alertmanager中路由負責對告警信息進行分組匹配,並將像告警接收器發送通知。告警接收器可以通過以下形式進行配置:
receivers:
- <receiver> ...
每一個receiver具有一個全局唯一的名稱,並且對應一個或者多個通知方式:
name: <string> email_configs: [ - <email_config>, ... ] hipchat_configs: [ - <hipchat_config>, ... ] pagerduty_configs: [ - <pagerduty_config>, ... ] pushover_configs: [ - <pushover_config>, ... ] slack_configs: [ - <slack_config>, ... ] opsgenie_configs: [ - <opsgenie_config>, ... ] webhook_configs: [ - <webhook_config>, ... ] victorops_configs: [ - <victorops_config>, ... ]
目前官方內置的第三方通知集成包括:郵件、 即時通訊軟件(如Slack、Hipchat)、移動應用消息推送(如Pushover)和自動化運維工具(例如:Pagerduty、Opsgenie、Victorops)。Alertmanager的通知方式中還可以支持Webhook,通過這種方式開發者可以實現更多個性化的擴展支持。
7.1 集成郵件系統
郵箱應該是目前企業最常用的告警通知方式,Alertmanager內置了對SMTP協議的支持,因此對於企業用戶而言,只需要一些基本的配置即可實現通過郵件的通知。
在Alertmanager使用郵箱通知,用戶只需要定義好SMTP相關的配置,並且在receiver中定義接收方的郵件地址即可。在Alertmanager中我們可以直接在配置文件的global中定義全局的SMTP配置:
global: [ smtp_from: <tmpl_string> ] [ smtp_smarthost: <string> ] [ smtp_hello: <string> | default = "localhost" ] [ smtp_auth_username: <string> ] [ smtp_auth_password: <secret> ] [ smtp_auth_identity: <string> ] [ smtp_auth_secret: <secret> ] [ smtp_require_tls: <bool> | default = true ]
完成全局SMTP之后,我們只需要為receiver配置email_configs用於定義一組接收告警的郵箱地址即可,如下所示:
name: <string>
email_configs:
[ - <email_config>, ... ]
每個email_config中定義相應的接收人郵箱地址,郵件通知模板等信息即可,當然如果當前接收人需要單獨的SMTP配置,那直接在email_config中覆蓋即可:
[ send_resolved: <boolean> | default = false ] to: <tmpl_string> [ html: <tmpl_string> | default = '{{ template "email.default.html" . }}' ] [ headers: { <string>: <tmpl_string>, ... } ]
如果當前收件人需要接受告警恢復的通知的話,在email_config中定義send_resolved為true即可。
如果所有的郵件配置使用了相同的SMTP配置,則可以直接定義全局的SMTP配置。
這里,以Gmail郵箱為例,我們定義了一個全局的SMTP配置,並且通過route將所有告警信息發送到default-receiver中:
global: smtp_smarthost: smtp.gmail.com:587 smtp_from: <smtp mail from> smtp_auth_username: <usernae> smtp_auth_identity: <username> smtp_auth_password: <password> route: group_by: ['alertname'] receiver: 'default-receiver' receivers: - name: default-receiver email_configs: - to: <mail to address> send_resolved: true
注意:新的Google賬號安全規則需要使用”應用專有密碼“作為郵箱登錄密碼
這時如果手動拉高主機CPU使用率,使得監控樣本數據滿足告警觸發條件。在SMTP配置正確的情況下,可以接收到如下的告警內容:
7.2 集成Slack
Slack是非常流行的團隊溝通應用,提供群組聊天和直接消息發送功能,支持移動端,Web 和桌面平台。在國外有大量的IT團隊使用Slack作為團隊協作平台。同時其提供了強大的集成能力,在Slack的基礎上也衍生出了大量的ChatOps相關的技術實踐。這部分將介紹如何將Slack集成到Alertmanager中。
7.2.1 認識Slack
Slack作為一款即時通訊工具,協作溝通主要通過Channel(平台)來完成,用戶可以在企業中根據用途添加多個Channel,並且通過Channel來集成各種第三方工具。
例如,我們可以為監控建立一個單獨的Channel用於接收各種監控信息:
創建Channel
通過一個獨立的Channle可以減少信息對用戶工作的干擾,並且將相關信息聚合在一起:
Monitoring
Slack的強大之處在於在Channel中添加各種第三方服務的集成,用戶也可以基於Slack開發自己的聊天機器人來實現一些更高級的能力,例如自動化運維,提高開發效率等。
7.2.2 添加應用:Incomming Webhooks
為了能夠在Monitoring中接收來自Alertmanager的消息,我們需要在Channel的設置選項中使用"Add an App"為Monitoring channel添加一個名為Incoming WebHooks的應用:
添加Incomming Webhooks
添加成功后Slack會顯示Incoming WebHooks配置和使用方式:
Incomming Webhhook配置
Incomming Webhook的工作方式很簡單,Slack為當前Channel創建了一個用於接收消息的API地址:
https://hooks.slack.com/services/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
用戶只需要使用Post方式向Channel發送需要通知的消息即可,例如,我們可以在命令行中通過curl模擬一次消息通知:
curl -d "payload={'text': 'This is a line of text in a channel.\nAnd this is another line of text.'}" https://hooks.slack.com/services/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
在網絡正常的情況下,在Channel中會顯示新的通知信息,如下所示:
測試消息
除了發送純文本以外,slack還支持在文本內容中添加鏈接,例如:
payload={"text": "A very important thing has occurred! <https://alert-system.com/alerts/1234|Click here> for details!"}
此時接收到的消息中建輝包含一個可點擊的超鏈接地址。除了payload以外,Incomming Webhhook還支持一些其他的參數:
參數 | 作用 | 示例 |
username | 設置當前聊天機器人的名稱 | webhookbot |
icon_url | 當前聊天機器人的頭像地址 | https://slack.com/img/icons/app-57.png |
icon_emoji | 使用emoji作為聊天機器人的頭像 | :ghost: |
channel | 消息發送的目標channel, 需要直接發給特定用戶時使用@username即可 | #monitoring 或者 @username |
例如,使用以上參數發送一條更有趣的消息:
curl -X POST --data-urlencode "payload={'channel': '#monitoring', 'username': 'webhookbot', 'text': 'This is posted to #monitoring and comes from a bot named webhookbot.', 'icon_emoji': ':ghost:'}" https://hooks.slack.com/services/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
自定義消息
7.2.3 在Alertmanager中使用Slack
在了解了Slack以及Incomming Webhhook的基本使用方式后,在Alertmanager中添加Slack支持就非常簡單了。
在Alertmanager的全局配置中,將Incomming Webhhook地址作為slack_api_url添加到全局配置中即可:
global: slack_api_url: https://hooks.slack.com/services/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
當然,也可以在每個receiver中單獨定義自己的slack_configs即可:
receivers: - name: slack slack_configs: - channel: '#monitoring' send_resolved: true
這里如果我們手動拉高當前主機的CPU利用率,在#Monitoring平台中,我們會接收到一條告警信息如下所示:
告警信息
而當告警項恢復正常后,則可以接收到如下通知:
告警恢復信息
對於Incomming Webhhook支持的其它自定義參數,也可以在slack_config中進行定義,slack_config的主要配置如下:
channel: <tmpl_string> [ send_resolved: <boolean> | default = false ] [ api_url: <secret> | default = global.slack_api_url ] [ icon_emoji: <tmpl_string> ] [ icon_url: <tmpl_string> ] [ link_names: <boolean> | default = false ] [ username: <tmpl_string> | default = '{{ template "slack.default.username" . }}' ] [ color: <tmpl_string> | default = '{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}' ] [ footer: <tmpl_string> | default = '{{ template "slack.default.footer" . }}' ] [ pretext: <tmpl_string> | default = '{{ template "slack.default.pretext" . }}' ] [ text: <tmpl_string> | default = '{{ template "slack.default.text" . }}' ] [ title: <tmpl_string> | default = '{{ template "slack.default.title" . }}' ] [ title_link: <tmpl_string> | default = '{{ template "slack.default.titlelink" . }}' ] [ image_url: <tmpl_string> ] [ thumb_url: <tmpl_string> ]
如果要覆蓋默認的告警內容,直接使用Go Template即可。例如:
color: '{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}'
7.3 集成企業微信
Alertmanager已經內置了對企業微信的支持,我們可以通過企業微信來管理報警,更進一步可以通過企業微信和微信的互通來直接將告警消息轉發到個人微信上。
prometheus官網中給出了企業微信的相關配置說明
# Whether or not to notify about resolved alerts. [ send_resolved: <boolean> | default = false ] # The API key to use when talking to the WeChat API. [ api_secret: <secret> | default = global.wechat_api_secret ] # The WeChat API URL. [ api_url: <string> | default = global.wechat_api_url ] # The corp id for authentication. [ corp_id: <string> | default = global.wechat_api_corp_id ] # API request data as defined by the WeChat API. [ message: <tmpl_string> | default = '{{ template "wechat.default.message" . }}' ] [ agent_id: <string> | default = '{{ template "wechat.default.agent_id" . }}' ] [ to_user: <string> | default = '{{ template "wechat.default.to_user" . }}' ] [ to_party: <string> | default = '{{ template "wechat.default.to_party" . }}' ] [ to_tag: <string> | default = '{{ template "wechat.default.to_tag" . }}' ]
企業微信相關概念說明請參考企業微信API說明,可以在企業微信的后台中建立多個應用,每個應用對應不同的報警分組,由企業微信來做接收成員的划分。具體配置參考如下:
global: resolve_timeout: 10m wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/' wechat_api_secret: '應用的secret,在應用的配置頁面可以看到' wechat_api_corp_id: '企業id,在企業的配置頁面可以看到' templates: - '/etc/alertmanager/config/*.tmpl' route: group_by: ['alertname'] group_wait: 30s group_interval: 5m repeat_interval: 12h routes: - receiver: 'wechat' continue: true inhibit_rules: - source_match: receivers: - name: 'wechat' wechat_configs: - send_resolved: false corp_id: '企業id,在企業的配置頁面可以看到' to_user: '@all' to_party: ' PartyID1 | PartyID2 ' message: '{{ template "wechat.default.message" . }}' agent_id: '應用的AgentId,在應用的配置頁面可以看到' api_secret: '應用的secret,在應用的配置頁面可以看到'
配置模板示例如下:
{{ define "wechat.default.message" }} {{- if gt (len .Alerts.Firing) 0 -}} {{- range $index, $alert := .Alerts -}} {{- if eq $index 0 -}} 告警類型: {{ $alert.Labels.alertname }} 告警級別: {{ $alert.Labels.severity }} ===================== {{- end }} ===告警詳情=== 告警詳情: {{ $alert.Annotations.message }} 故障時間: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }} ===參考信息=== {{ if gt (len $alert.Labels.instance) 0 -}}故障實例ip: {{ $alert.Labels.instance }};{{- end -}} {{- if gt (len $alert.Labels.namespace) 0 -}}故障實例所在namespace: {{ $alert.Labels.namespace }};{{- end -}} {{- if gt (len $alert.Labels.node) 0 -}}故障物理機ip: {{ $alert.Labels.node }};{{- end -}} {{- if gt (len $alert.Labels.pod_name) 0 -}}故障pod名稱: {{ $alert.Labels.pod_name }}{{- end }} ===================== {{- end }} {{- end }} {{- if gt (len .Alerts.Resolved) 0 -}} {{- range $index, $alert := .Alerts -}} {{- if eq $index 0 -}} 告警類型: {{ $alert.Labels.alertname }} 告警級別: {{ $alert.Labels.severity }} ===================== {{- end }} ===告警詳情=== 告警詳情: {{ $alert.Annotations.message }} 故障時間: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }} 恢復時間: {{ $alert.EndsAt.Format "2006-01-02 15:04:05" }} ===參考信息=== {{ if gt (len $alert.Labels.instance) 0 -}}故障實例ip: {{ $alert.Labels.instance }};{{- end -}} {{- if gt (len $alert.Labels.namespace) 0 -}}故障實例所在namespace: {{ $alert.Labels.namespace }};{{- end -}} {{- if gt (len $alert.Labels.node) 0 -}}故障物理機ip: {{ $alert.Labels.node }};{{- end -}} {{- if gt (len $alert.Labels.pod_name) 0 -}}故障pod名稱: {{ $alert.Labels.pod_name }};{{- end }} ===================== {{- end }} {{- end }} {{- end }}
這時如果某一容器頻繁重啟,可以接收到如下的告警內容:
告警
7.3.1 集成企業微信案例
1.企業ID獲取
首先訪問企業微信官網:https://work.weixin.qq.com/
注冊完成之后,登錄后台管理,在【我的企業】這里,先拿到后面用到的第一個配置:企業ID
2.部門ID獲取
在通訊錄中,添加一個子部門,用於接收告警信息,后面把人加到該部門,這個人就能接收到告警信息了。
可以看到部門id為2
3.告警AgentId和Secret獲取
告警AgentId和Secret獲取是需要在企業微信后台,【應用管理】中,自建應用才能夠獲得的。這里網上介紹的非常多,都只是說了這一步驟,而忽略了其他幾個重要的步驟。
點擊這個應用,可以看到我們想要的AgentId和Secret
以上步驟完成后,我們就得到了配置Alertmanager的所有信息,包括:企業ID,AgentId,Secret和接收告警的部門id
4.配置Alertmanager服務
主配置文件
global: resolve_timeout: 5m wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/' wechat_api_corp_id: 'wwd30f74a2a3aca657' # 企業微信中企業ID wechat_api_secret: 'yIyc9g_2S0kxOTe2kwgZ0gWG6RVZ7AGB0m2qhUFgD34' # 企業微信中,應用的Secret templates: - "/opt/alertmanager/templates/*.tmpl" route: group_by: ['alertname'] group_wait: 10s group_interval: 10s repeat_interval: 1m receiver: 'cn-web-prod' receivers: - name: 'cn-web-prod' wechat_configs: - send_resolved: true #message: '{{ template "wechat.default.message" . }}' to_party: '2' # 企業微信中創建的接收告警的部門【告警機器人】的部門ID to_user: 'tc' #這里有2點需要注意。1.用戶不能在默認的最大部門下。2.無法配置多用戶同時發送告警,所以多用戶需要使用部門 agent_id: '1000003' # 企業微信中創建的應用的ID api_secret: 'yIyc9g_2S0kxOTe2kwgZ0gWG6RVZ7AGB0m2qhUFgD34' #企業微信中,應用的Secret
5.微信告警模版(可選)
對應配置文件中message字段引用。
# cat /opt/alertmanager/template/wechat.tmpl {{ define "wechat.default.message" }} {{- if gt (len .Alerts.Firing) 0 -}} {{- range $index, $alert := .Alerts -}} {{- if eq $index 0 }} ========= 監控報警 ========= 告警狀態:{{ .Status }} 告警級別:{{ .Labels.severity }} 告警類型:{{ $alert.Labels.alertname }} 故障主機: {{ $alert.Labels.instance }} 告警主題: {{ $alert.Annotations.summary }} 告警詳情: {{ $alert.Annotations.message }}{{ $alert.Annotations.description}}; 觸發閥值:{{ .Annotations.value }} 故障時間: {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} ========= = end = ========= {{- end }} {{- end }} {{- end }} {{- if gt (len .Alerts.Resolved) 0 -}} {{- range $index, $alert := .Alerts -}} {{- if eq $index 0 }} ========= 異常恢復 ========= 告警類型:{{ .Labels.alertname }} 告警狀態:{{ .Status }} 告警主題: {{ $alert.Annotations.summary }} 告警詳情: {{ $alert.Annotations.message }}{{ $alert.Annotations.description}}; 故障時間: {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} 恢復時間: {{ ($alert.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} {{- if gt (len $alert.Labels.instance) 0 }} 實例信息: {{ $alert.Labels.instance }} {{- end }} ========= = end = ========= {{- end }} {{- end }} {{- end }} {{- end }}
更多微信告警配置參考: https://prometheus.io/docs/alerting/latest/configuration/#wechat_config
7.4 集成釘釘:基於Webhook的擴展
7.4.1 自定義webhook群機器人
通過釘釘客戶端(如:桌面或者手機)進入到群設置后選擇“群機器人”。將顯示如下界面:
群機器人
選擇“自定義機器人”,並且按照提示填寫機器人名稱,獲取機器人webhook地址,如下所示:
獲取webhook地址
webhook機器人創建成功后,用戶就可以使用任何方式向該地址發起HTTP POST請求,即可實現向該群主發送消息。目前自定義機器人支持文本(text),連接(link),markdown三種消息類型。
但是由於使用釘釘的方式是使用基於webhook的方式來擴展的,所以直接把告警消息發送到釘釘告警機器人做不到,所以需要一個轉換器.
首先有兩種轉換器,第一種,別人開發好的,但是消息不好自定義,另一種是自己寫的,告警格式可以自定義.
7.4.2 現成轉換器
首先講解github上面的項目,優點是拿過來就可以用,缺點是消息無法自定義.
集成了這個項目,用於釘釘機器人推送告警信息https://github.com/timonwong/prometheus-webhook-dingtalk
二進制部署
# 二進制包下載 https://github.com/timonwong/prometheus-webhook-dingtalk/releases wget https://github.com/timonwong/prometheus-webhook-dingtalk/releases/download/v0.3.0/prometheus-webhook-dingtalk-0.3.0.linux-amd64.tar.gz # 啟動服務 ./prometheus-webhook-dingtalk --ding.profile="webhook1=https://oapi.dingtalk.com/robot/send?access_token={替換成自己的dingding token}"
docker部署
docker pull timonwong/prometheus-webhook-dingtalk # 啟動容器 docker run -d -p 8060:8060 --name webhook timonwong/prometheus-webhook --ding.profile="webhook1=https://oapi.dingtalk.com/robot/send?access_token={替換成自己的dingding token}
alert配置
receivers: - name: webhook webhook_configs: #主要主要就是發送的時候不是配置釘釘機器人的地址,而是轉換器的地址 - url: http://localhost:8060/dingtalk/webhook1/send send_resolved: true
7.4.3 自定義
自定義是本人使用python的flask框架自己寫的,可以自定義告警格式,以下就貼出代碼

[root@prometheus01 infra]# cat /opt/dingding.py #!/usr/bin import os import json import requests import arrow from flask import Flask from flask import request app = Flask(__name__) @app.route('/', methods=['POST', 'GET']) def send(): if request.method == 'POST': post_data = request.get_data() send_alert(bytes2json(post_data)) return 'success' else: return 'weclome to use prometheus alertmanager dingtalk webhook server!' def bytes2json(data_bytes): data = data_bytes.decode('utf8').replace("'", '"') return json.loads(data) def send_alert(data): #token = os.getenv('ROBOT_TOKEN') #if not token: #print('you must set ROBOT_TOKEN env') #return import time now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) url = 'https://oapi.dingtalk.com/robot/send?access_token=e58d04a7b02ef382e5d0112ad99b413ef60774b136a2aec3fac8397b7130828a' tmp_data={} for output in data['alerts'][:]: #print ('----------------------------',data['alerts']) alert_num = int(len(data['alerts'])) try: pod_name = output['labels']['pod'] except KeyError: try: pod_name = output['labels']['pod_name'] except KeyError: pod_name = 'null' try: namespace = output['labels']['namespace'] except KeyError: namespace = 'null' try: container_name = output['labels']['container_name'] except KeyError: container_name = 'null' try: message = output['annotations']['message'] except KeyError: try: message = output['annotations']['description'] except KeyError: message = 'null' try: hostname = output['labels']['hostname'] except KeyError: hostname = 'null' try: instance = output['labels']['instance'] except KeyError: instance = 'null' if not tmp_data: if pod_name != 'null': tmp_data = "## 告警標題: %s (總共 %d 個告警)\n" %(output['annotations']['summary'],alert_num) + \ "**任務歸屬**: %s \n\n" % output['labels']['job'] + \ "**告警類型**: %s \n\n" % output['labels']['alertname'] + \ "**告警級別**: %s \n\n" % output['labels']['severity'] + \ "<font color=#FF0000 >**容器名**: %s \n\n</font>" % container_name + \ "<font color=#FF0000 >**pod名**: %s \n\n</font>" % pod_name + \ "<font color=#FF0000 >**namespace**: %s \n\n</font>" % namespace + \ "**告警詳情**: <font color=#FF0000 >%s \n\n</font>" % message + \ "**告警狀態**: %s \n\n" % output['status'] + \ "**觸發開始時間**: %s \n\n" % arrow.get(output['startsAt']).to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss ZZ') + "\n" \ "**告警發送時間**: %s \n\n" % now_time + "\n" \ "............................................................................................................" + "\n" else: tmp_data = "## 告警標題: %s (總共 %d 個告警)\n" %(output['annotations']['summary'],alert_num) + \ "**任務歸屬**: %s \n\n" % output['labels']['job'] + \ "**告警類型**: %s \n\n" % output['labels']['alertname'] + \ "**告警級別**: %s \n\n" % output['labels']['severity'] + \ "<font color=#FF0000 >**主機名**: %s \n\n</font>" % hostname + \ "<font color=#FF0000 >**Instance**: %s</font> \n\n" % instance + \ "**告警詳情**: <font color=#FF0000 >%s \n\n</font>" % message + \ "**告警狀態**: %s \n\n" % output['status'] + \ "**觸發時間**: %s \n\n" % arrow.get(output['startsAt']).to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss ZZ') + "\n" \ "**告警發送時間**: %s \n\n" % now_time + "\n" \ "............................................................................................................" + "\n" else: if pod_name != 'null': tmp_data = tmp_data + "**任務歸屬**: %s \n\n" % output['labels']['job'] + \ "**告警類型**: %s \n\n" % output['labels']['alertname'] + \ "**告警級別**: %s \n\n" % output['labels']['severity'] + \ "<font color=#FF0000 >**容器名**: %s \n\n</font>" % container_name + \ "<font color=#FF0000 >**pod名**: %s \n\n</font>" % pod_name + \ "<font color=#FF0000 >**namespace**: %s\n\n </font>" % namespace + \ "**告警詳情**: <font color=#FF0000 >%s \n\n</font>" % message + \ "**告警狀態**: %s \n\n" % output['status'] + \ "**觸發開始時間**: %s \n\n" % arrow.get(output['startsAt']).to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss ZZ') + "\n" \ "**告警發送時間**: %s \n\n" % now_time + "\n" \ "............................................................................................................" + "\n" else: tmp_data = tmp_data + "**任務歸屬**: %s \n\n" % output['labels']['job'] + \ "**告警類型**: %s \n\n" % output['labels']['alertname'] + \ "**告警級別**: %s \n\n" % output['labels']['severity'] + \ "<font color=#FF0000 >**主機名**: %s \n\n</font>" % hostname + \ "<font color=#FF0000 >**Instance**: %s \n\n</font>" % instance + \ "**告警詳情**: <font color=#FF0000 >%s \n\n</font>" % message + \ "**告警狀態**: %s \n\n" % output['status'] + \ "**觸發時間**: %s \n\n" % arrow.get(output['startsAt']).to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss ZZ') + "\n" \ "**告警發送時間**: %s \n\n" % now_time + "\n" \ "............................................................................................................" + "\n" tmp_data = tmp_data + "prometheus:[http://prometheus.mobage.cn:9090](http://prometheus.mobage.cn:9090)\n\n" + \ "alertmanager:[http://alertmanager.mobage.cn:9093](http://alertmanager.mobage.cn:9093)\n\n" send_data = { "msgtype": "markdown", "markdown": { "title": "sb", "text": tmp_data } } req = requests.post(url, json=send_data) result = req.json() if result['errcode'] != 0: print('notify dingtalk error: %s' % result['errcode']) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
alert配置
receivers: - name: webhook webhook_configs: #主要就是發送的時候不是配置釘釘機器人的地址,而是轉換器的地址 - url: http://localhost:5000 send_resolved: true
8.告警模版詳解
默認情況下Alertmanager使用了系統自帶的默認通知模板,模板源碼可以從https://github.com/prometheus/alertmanager/blob/master/template/default.tmpl獲得。Alertmanager的通知模板基於Go的模板系統。Alertmanager也支持用戶定義和使用自己的模板,一般來說有兩種方式可以選擇。
第一種,基於模板字符串。用戶可以直接在Alertmanager的配置文件中使用模板字符串,例如:
receivers: - name: 'slack-notifications' slack_configs: - channel: '#alerts' text: 'https://internal.myorg.net/wiki/alerts/{{ .GroupLabels.app }}/{{ .GroupLabels.alertname }}'
第二種方式,自定義可復用的模板文件。例如,可以創建自定義模板文件custom-template.tmpl,如下所示:
{{ define "slack.myorg.text" }}https://internal.myorg.net/wiki/alerts/{{ .GroupLabels.app }}/{{ .GroupLabels.alertname }}{{ end}}
通過在Alertmanager的全局設置中定義templates配置來指定自定義模板的訪問路徑:
# Files from which custom notification template definitions are read. # The last component may use a wildcard matcher, e.g. 'templates/*.tmpl'. templates: [ - <filepath> ... ]
在設置了自定義模板的訪問路徑后,用戶則可以直接在配置中使用該模板:
receivers: - name: 'slack-notifications' slack_configs: - channel: '#alerts' text: '{{ template "slack.myorg.text" . }}' templates: - '/etc/alertmanager/templates/myorg.tmpl'
9.屏蔽告警通知
Alertmanager提供了方式可以幫助用戶控制告警通知的行為,包括預先定義的抑制機制和臨時定義的靜默規則。
9.1 抑制機制
Alertmanager的抑制機制可以避免當某種問題告警產生之后用戶接收到大量由此問題導致的一系列的其它告警通知。例如當集群不可用時,用戶可能只希望接收到一條告警,告訴他這時候集群出現了問題,而不是大量的如集群中的應用異常、中間件服務異常的告警通知。
在Alertmanager配置文件中,使用inhibit_rules定義一組告警的抑制規則:
inhibit_rules:
[ - <inhibit_rule> ... ]
每一條抑制規則的具體配置如下:
target_match: [ <labelname>: <labelvalue>, ... ] target_match_re: [ <labelname>: <regex>, ... ] source_match: [ <labelname>: <labelvalue>, ... ] source_match_re: [ <labelname>: <regex>, ... ] [ equal: '[' <labelname>, ... ']' ]
當已經發送的告警通知匹配到target_match和target_match_re規則,當有新的告警規則如果滿足source_match或者定義的匹配規則,並且已發送的告警與新產生的告警中equal定義的標簽完全相同,則啟動抑制機制,新的告警不會發送。
例如,定義如下抑制規則:
- source_match:
alertname: NodeDown
severity: critical
target_match:
severity: critical
equal:
- node
例如當集群中的某一個主機節點異常宕機導致告警NodeDown被觸發,同時在告警規則中定義了告警級別severity=critical。由於主機異常宕機,該主機上部署的所有服務,中間件會不可用並觸發報警。根據抑制規則的定義,如果有新的告警級別為severity=critical,並且告警中標簽node的值與NodeDown告警的相同,則說明新的告警是由NodeDown導致的,則啟動抑制機制停止向接收器發送通知。
9.2 臨時靜默
除了基於抑制機制可以控制告警通知的行為以外,用戶或者管理員還可以直接通過Alertmanager的UI臨時屏蔽特定的告警通知。通過定義標簽的匹配規則(字符串或者正則表達式),如果新的告警通知滿足靜默規則的設置,則停止向receiver發送通知。
進入Alertmanager UI,點擊"New Silence"顯示如下內容:
創建靜默規則
用戶可以通過該UI定義新的靜默規則的開始時間以及持續時間,通過Matchers部分可以設置多條匹配規則(字符串匹配或者正則匹配)。填寫當前靜默規則的創建者以及創建原因后,點擊"Create"按鈕即可。
通過"Preview Alerts"可以查看預覽當前匹配規則匹配到的告警信息。靜默規則創建成功后,Alertmanager會開始加載該規則並且設置狀態為Pending,當規則生效后則進行到Active狀態。
活動的靜默規則
當靜默規則生效以后,從Alertmanager的Alerts頁面下用戶將不會看到該規則匹配到的告警信息。
告警信息
對於已經生效的規則,用戶可以通過手動點擊”Expire“按鈕使當前規則過期。
10.使用Recoding Rules優化性能
通過PromQL可以實時對Prometheus中采集到的樣本數據進行查詢,聚合以及其它各種運算操作。而在某些PromQL較為復雜且計算量較大時,直接使用PromQL可能會導致Prometheus響應超時的情況。這時需要一種能夠類似於后台批處理的機制能夠在后台完成這些復雜運算的計算,對於使用者而言只需要查詢這些運算結果即可。Prometheus通過Recoding Rule規則支持這種后台計算的方式,可以實現對復雜查詢的性能優化,提高查詢效率。
10.1 定義Recoding rules
在Prometheus配置文件中,通過rule_files定義recoding rule規則文件的訪問路徑。
rule_files:
[ - <filepath_glob> ... ]
每一個規則文件通過以下格式進行定義:
groups:
[ - <rule_group> ]
一個簡單的規則文件可能是這個樣子的:
groups: - name: example rules: - record: job:http_inprogress_requests:sum expr: sum(http_inprogress_requests) by (job)
rule_group的具體配置項如下所示:
# The name of the group. Must be unique within a file. name: <string> # How often rules in the group are evaluated. [ interval: <duration> | default = global.evaluation_interval ] rules: [ - <rule> ... ]
與告警規則一致,一個group下可以包含多條規則rule。
# The name of the time series to output to. Must be a valid metric name. record: <string> # The PromQL expression to evaluate. Every evaluation cycle this is # evaluated at the current time, and the result recorded as a new set of # time series with the metric name as given by 'record'. expr: <string> # Labels to add or overwrite before storing the result. labels: [ <labelname>: <labelvalue> ]
根據規則中的定義,Prometheus會在后台完成expr中定義的PromQL表達式計算,並且將計算結果保存到新的時間序列record中。同時還可以通過labels為這些樣本添加額外的標簽。
這些規則文件的計算頻率與告警規則計算頻率一致,都通過global.evaluation_interval定義:
global: [ evaluation_interval: <duration> | default = 1m ]