一、配置概述
1. 配置簡介
Alertmanager主要負責對Prometheus産生的告警進行統一處理,在Alertmanager配置中一般會包含以下幾個主要部分:
- 全局配置(global):用于定義一些全局的公共參數,如全局的SMTP配置,Slack配置等内容;
- 模闆(templates):用于定義告警通知時的模闆,如HTML模闆,郵件模闆等;
- 告警路由(route):根據标簽比對,确定目前告警應該如何處理;
- 接收人(receivers):接收人是一個抽象的概念,它可以是一個郵箱也可以是微信,Slack或者Webhook等,接收人一般配合告警路由使用;
- 抑制規則(inhibit_rules):合理設定抑制規則可以減少垃圾告警的産生
2.global配置
global:
[ resolve_timeout: <duration> | default = 5m ] # 當Alertmanager持續多長時間未接收到告警後标記告警狀态為resolved(已解決)
[ 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> ... ]
global配置中主要關注resolve_timeout的配置。其他配置為SMTP配置,Slack配置等告警媒介的相關配置,在後續章節配置不同的告警媒介時會具體講到。也可參考官方文檔:https://prometheus.io/docs/alerting/latest/configuration/
二、告警路由
1. 配置詳解
告警路由可以使我們的告警根據不同的标簽告警比對到不同的管道發送處理。配置檔案解析如下:
route: #配置路由樹
receiver: # 接收組名,對于不同級别的告警,我們可能多個完全不同的接收組進行處理。
group_by: []# 根據label标簽的key進行比對,如果是多個,就要多個都比對
continue: false # 告警是否去繼續路由子節點
match: [labelname:labelvalue,labelname1,labelvalue1] # 通過标簽去比對這次告警是否符合這個路由節點。
match_re: [labelname:regex] # 通過正則表達是比對标簽,意義同上
group_wait: 30s # 組内等待時間,同一分組内收到第一個告警等待多久開始發送,目标是為了同組消息同時發送,不占用告警資訊,預設30s
group_interval: 5m # 當組内已經發送過一個告警,組内若有新增告警需要等待的時間,預設為5m,這條要确定組内資訊是影響同一業務才能設定,若分組不合理,可能導緻告警延遲,造成影響
repeat_inteval: 4h # 告警已經發送,且無新增告警,若重複告警需要間隔多久 預設4h 屬于重複告警,時間間隔應根據告警的嚴重程度來設定
routes:
- route: #路由子節點 配置資訊跟主節點的路由資訊一緻
2. 路由比對
每一個告警都會從配置檔案中頂級的route進入路由樹,需要注意的是頂級的route必須比對所有告警(即不能有任何的比對設定match和match_re),每一個路由都可以定義自己的接受人以及比對規則。預設情況下,告警進入到頂級route後會周遊所有的子節點,直到找到最深的比對route,并将告警發送到該route定義的receiver中。但如果route中設定continue的值為false,那麼告警在比對到第一個子節點之後就直接停止。如果continue為true,報警則會繼續進行後續子節點的比對。如果目前告警比對不到任何的子節點,那該告警将會基于目前路由節點的接收器配置方式進行處理。
其中告警的比對有兩種方式可以選擇。一種方式基于字元串驗證,通過設定match規則判斷目前告警中是否存在标簽labelname并且其值等于labelvalue。第二種方式則基于正規表達式,通過設定match_re驗證目前告警标簽的值是否滿足正規表達式的内容。
如果警報已經成功發送通知, 如果想設定發送告警通知之前要等待時間,則可以通過repeat_interval參數進行設定。
3. 告警分組
Alertmanager可以對告警通知進行分組,将多條告警合合并為一個通知,避免短期内頻繁收到多條相關告警。這裡我們可以使用group_by來定義分組規則。基于告警中包含的标簽,如果滿足group_by中定義标簽名稱,那麼這些告警将會合并為一個通知發送給接收器。
有的時候為了能夠一次性收集和發送更多的相關資訊時,可以通過group_wait參數設定等待時間,如果在等待時間内目前group接收到了新的告警,這些告警将會合并為一個通知向receiver發送。
而group_interval配置,則用于定義相同的Group之間發送告警通知的時間間隔。
4. 配置舉例:告警分組功能的實作
一個完善的告警系統,告警路由通常是非常複雜的,為了便于運維人員配置,prometheus官方開發了一個路由配置樹工具。https://www.prometheus.io/webtools/alerting/routing-tree-editor/
- 預設情況下所有的告警都會發送給管理者default-receiver,是以在Alertmanager的配置檔案的根路由中,對告警資訊按照叢集以及告警的名稱對告警進行分組。
- 如果告警是來源于資料庫服務如MySQL或者pgsql,此時則需要将告警發送給相應的資料庫管理者(dba)。這裡定義了一個單獨子路由,如果告警中包含service标簽,并且service為mysql或者pgsql,則向dba-pager發送告警通知,由于這裡沒有定義group_by等屬性,這些屬性的配置資訊将從上級路由繼承,dba-pager将會接收到按cluser和alertname進行分組的告警通知。
- 而某些告警規則來源可能來源于開發團隊,這些告警中通過添加标簽team來标示這些告警的建立者。在Alertmanager配置檔案的告警路由下,定義單獨子路由用于處理這一類的告警通知,如果比對到告警中包含标簽team,并且team的值為dev,Alertmanager将會按照标簽product和environment對告警進行分組。此時如果應用出現異常,開發團隊就能清楚的知道哪一個環境(environment)中的哪一個應用程式出現了問題,可以快速對應用進行問題定位。
route:
receiver: 'default-receiver'
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
group_by: [cluster, alertname]
routes:
- receiver: 'dba-pager'
group_wait: 10s
match_re:
service: mysql|pgsql
- receiver: 'dev-pager'
group_by: [product, environment]
match:
team: dev
5. 配置舉例:告警分級功能的實作
- 在每條告警配置的标簽中添加severity配置,有三種等級,分别為warning、critical和emergency。嚴重等級依次遞增。
- 不論收到那種等級的告警,都會郵件通知給預設的管理者default-receiver
- 當告警等級為critical時,比較嚴重的告警,發送短信通知,每2h重複發送一次,直到問題解決
- 當告警等級為emergency時,特别嚴重的告警,打電話通知,每1h重複發送一次,直到問題解決
route:
receiver: 'default-receiver'
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
group_by: [cluster, alertname]
routes:
- receiver: 'SMS-pager'
repeat_inteval: 2h
group_wait: 10s
match:
severity: critical
- receiver: 'phone-pager'
repeat_inteval: 1h
group_wait: 10s
match:
severity: emergency
三、告警接收
1. receiver配置介紹
在Alertmanager中路由負責對告警資訊進行分組比對,并向告警接收器發送通知。每一個receiver具有一個全局唯一的名稱,并且對應一個或者多個通知方式,告警接收配置如下:
receivers:
- name: # 接收器名稱,全局唯一
# Configurations for several notification integrations.
email_configs:
[ - <email_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>, ... ]
wechat_configs:
[ - <wechat_config>, ... ]
- name: # 另一個接收器名稱,全局唯一
………………
目前官方内置的第三方通知內建包括:郵件、 即時通訊軟體(如Slack、Hipchat)、移動應用消息推送(如Pushover)和自動化運維工具(例如:Pagerduty、Opsgenie、Victorops)。Alertmanager的通知方式中還可以支援Webhook,通過這種方式開發者可以實作更多個性化的擴充支援。
更多告警媒介配置請參考官方文檔:https://prometheus.io/docs/alerting/latest/configuration/#receiver
2. 郵件告警配置
Alertmanager使用郵箱通知,使用者隻需要全局配置中定義好SMTP相關的配置,并且在receiver中定義接收方的郵件位址即可,此處以qq郵箱為例:
- 需要先登入QQ郵箱,開通smtp功能,并擷取授權碼。smtp_auth_password填寫的資訊,就是授權碼,而非QQ郵箱的登入密碼!
image.png
- Alertmanager配置
apiVersion: v1
kind: ConfigMap
metadata:
name: alertmanager-conf
namespace: monitoring
data:
config.yaml: |-
global:
smtp_smarthost: 'smtp.qq.com:465'
smtp_from: '[email protected]'
smtp_auth_username: '[email protected]'
smtp_auth_password: 'XXXX'
smtp_require_tls: false
route:
receiver: email
group_by:
- alertname
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receivers:
- name: 'email'
email_configs:
- to: '[email protected]'
send_resolved: false #告警解除發送恢複通知
- 告警測試
image.png
image.png
image.png
四、告警模闆
Alertmanager提供了一套基于Go的預設模闆系統。Alertmanager也支援使用者定義和使用自己的模闆。
1. 模闆字元串
和prometheus配置模闆字元串一樣。具體參考官方文檔https://prometheus.io/blog/2016/03/03/custom-alertmanager-templates/#customize,實際生産環境使用較少,此處不再介紹。
2. 模闆檔案
官方文法介紹:https://prometheus.io/docs/alerting/latest/notifications/
官方模闆連結:https://github.com/prometheus/alertmanager/blob/master/template/default.tmpl
郵件模闆連結:https://github.com/mailgun/transactional-email-templates
- 首先定義模闆檔案configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: alertmanager-email-tmpl
namespace: monitoring
data:
email-monitor.tmpl: |-
{{ define "email-monitor.html" }}
{{- if gt (len .Alerts.Firing) 0 -}}
<h1>告警</h1>
<table border="5">
<tr>
<td>報警項</td>
<td>執行個體</td>
<td>報警詳情</td>
<td>報警閥值</td>
<td>開始時間</td>
</tr>
{{ range $i, $alert := .Alerts }}
<tr><td>{{ index $alert.Labels "alertname" }}</td>
<td>{{ index $alert.Labels "instance" }}</td>
<td>{{ index $alert.Annotations "description" }}</td>
<td>{{ index $alert.Annotations "value" }}</td>
<td>{{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}</td>
</tr>
{{ end }}
</table>
{{ end }}
{{- if gt (len .Alerts.Resolved) 0 -}}
<h1>恢複</h1>
<table border="5">
<tr>
<td>報警項</td>
<td>執行個體</td>
<td>報警詳情</td>
<td>報警閥值</td>
<td>開始時間</td>
</tr>
{{ range $i, $alert := .Alerts }}
<tr>
<td>{{ index $alert.Labels "alertname" }}</td>
<td>{{ index $alert.Labels "instance" }}</td>
<td>{{ index $alert.Annotations "description" }}</td>
<td>{{ index $alert.Annotations "value" }}</td>
<td>{{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}</td>
</tr>
{{ end }}
</table>
{{ end }}{{- end }}
- 然後修改Alertmanager-config,指定模闆檔案
apiVersion: v1
kind: ConfigMap
metadata:
name: alertmanager-conf
namespace: monitoring
data:
config.yaml: |-
global:
smtp_smarthost: 'smtp.qq.com:465'
smtp_from: '[email protected]'
smtp_auth_username: '[email protected]'
smtp_auth_password: 'XXXXXX'
smtp_require_tls: false
templates:
- '/etc/alertmanager/tmpl/*.tmpl' # 指定自定義告警模闆位置
route:
receiver: email
group_by:
- alertname
group_wait: 10s
group_interval: 10m
repeat_interval: 1h
receivers:
- name: 'email'
email_configs:
- to: '[email protected]'
send_resolved: false # 告警解除發送恢複通知
html: '{{ template "email-monitor.html" . }}' # 指定告警模闆
headers: { Subject: "告警郵件" } # 郵件主題 如果不寫也可以在模闆中定義預設值
- 最後修改Alertmanager資源清單,将模闆配置檔案挂載
apiVersion: apps/v1
kind: Deployment
metadata:
name: alertmanager
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: alertmanager
template:
metadata:
name: alertmanager
labels:
app: alertmanager
spec:
containers:
- name: alertmanager
image: prom/alertmanager:v0.23.0
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "4Gi"
cpu: "4"
requests:
memory: "128Mi"
cpu: "500m"
args:
- '--config.file=/etc/alertmanager/config/config.yaml'
- '--storage.path=/alertmanager'
- '--log.level=debug'
ports:
- name: alertmanager
containerPort: 9093
volumeMounts:
- name: alertmanager-conf
mountPath: /etc/alertmanager/config
- name: alertmanager-email-tmpl
mountPath: /etc/alertmanager/tmpl
- name: alertmanager
mountPath: /alertmanager
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- alertmanager
topologyKey: "kubernetes.io/hostname"
volumes:
- name: alertmanager-conf
configMap:
name: alertmanager-conf
- name: alertmanager-email-tmpl
configMap:
name: alertmanager-email-tmpl
- name: alertmanager
emptyDir: {}
- 一切準備就緒後,接下來模拟節點當機,測試告警是否正常發出
image.png
五、告警靜默
接着上文提到的操作,現在work3節點持續處于當機狀态,并配置了repeat_interval: 1h,也就是如果故障沒有解決,每1h會通知一次,直到故障恢複。但有可能這台伺服器硬體損壞,短期内無法恢複,為了避免告警打擾,可以設定臨時靜默。
1. 檢視告警
首先,檢視Alertmanager的alerts。檢視目前未恢複的告警
image.png
2. 設定靜默
然後點選silence,對這個告警設定臨時靜默,然後填寫靜默持續時間(預設2h),以及建立這和備注,填寫完成後點選create建立靜默規則
image.png
3. 檢視驗證
- 此時在alert中就不會看到激活的告警内容 image.png
- 點選silence就可以檢視到已經靜默的告警
image.png
六、告警抑制
Alertmanager的抑制機制可以避免當某種問題告警産生之後使用者接收到大量由此問題導緻的一系列的其它告警通知。例如當叢集不可用時,使用者可能隻希望接收到一條告警,告訴他這時候叢集出現了問題,而不是大量的如叢集中的應用異常、中間件服務異常的告警通知。
1. 基本格式
- Alertmanager中使用inhibit_rules定義一組告警的抑制規則,基本格式如下
inhibit_rules:
- source_match: # 第一條抑制規則
target_match: # 比對标簽
target_match_re: # 比對正則
equal: # 在源和目标中具有相同值的标簽
- source_match: # 第二條抑制規則
…………
當已經發送的告警通知比對到target_match和target_match_re規則,當有新的告警規則如果滿足source_match或者定義的比對規則,并且已發送的告警與新産生的告警中equal定義的标簽完全相同,則啟動抑制機制,新的告警不會發送。
2. 模拟測試-抑制前
場景模拟:目前目前叢集的work2上面運作了nginx服務,通路位址為http://192.168.10.12/test.html,并且配置了網絡探針,檢測http://192.168.10.12/test.html頁面狀态碼是否為200,以及80端口的TCP檢測,還有node_exporter當機檢測。并且都設定了告警,如果此時伺服器當機了,那麼我将收到大量無用的告警資訊,反而不好排查問題原因。
- 我們先在work2伺服器上運作nginx服務,并添加測試頁面,模拟線上生産環境的web服務
image.png
- 然後部署blackbox-exporter元件用于網絡檢測
apiVersion: v1
kind: Service
metadata:
name: blackbox-exporter-svc
namespace: monitoring
labels:
app: blackbox-exporter
spec:
selector:
app: blackbox-exporter
type: ClusterIP
ports:
- name: http
port: 9115
protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: blackbox-exporter
namespace: monitoring
labels:
app: blackbox-exporter
spec:
replicas: 1
selector:
matchLabels:
app: blackbox-exporter
template:
metadata:
labels:
app: blackbox-exporter
spec:
containers:
- image: prom/blackbox-exporter
name: blackbox-exporter
ports:
- containerPort: 9115
name: http
readinessProbe:
httpGet:
path: /-/healthy
port: http
initialDelaySeconds: 10
timeoutSeconds: 60
livenessProbe:
httpGet:
path: /-/healthy
port: http
initialDelaySeconds: 30
timeoutSeconds: 60
resources:
limits:
cpu: 1
memory: "2Gi"
requests:
cpu: 250m
memory: 640Mi
restartPolicy: Always
- 接下來在prometheus配置檔案中添加網絡檢測相關target
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yaml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/rules/*.yaml
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
scrape_configs:
- job_name: blackbox_http_exporter
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- http://192.168.10.12/test.html
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter-svc:9115
- job_name: blackbox_tcp_exporter
metrics_path: /probe
params:
module: [tcp_connect]
static_configs:
- targets:
- 192.168.10.12:80
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter-svc:9115
- 接下來檢視prometheus-target頁面,确認采集項成功添加
- 接下來添加告警規則配置,現在有三條告警,第一條為node status is WODN,事件等級為emergency,第二條為nginx service status is WODN,事件等級為critical,第三條為page status code error,事件等級為critical。三個告警事件從上到下層層依賴,重要程度依次遞減。
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-rule
labels:
name: prometheus-rule
namespace: monitoring
data:
alert-rules.yaml: |-
groups:
- name: node-alert
rules:
- alert: node status is WODN
expr: up{job="node_exporter"} == 0
for: 1m
labels:
severity: emergency
instance: "{{ $labels.instance }}"
annotations:
summary: "node: {{ $labels.instance }} down"
description: "{{$labels.instance}} down more than 1 minutes"
value: "{{ $value }}"
- alert: nginx service status is WODN
expr: probe_success{instance="192.168.10.12:80"} == 0
for: 1m
labels:
severity: critical
instance: "{{ $labels.instance }}"
annotations:
summary: "node: {{ $labels.instance }} nginx service down"
description: "{{$labels.instance}} nginx service down more than 1 minutes"
value: "{{ $value }}"
- alert: page status code error
expr: probe_http_status_code{instance="http://192.168.10.12/test.html"} != 200
for: 1m
labels:
severity: warning
instance: "{{ $labels.instance }}"
annotations:
summary: "url: {{ $labels.instance }} page status code error"
description: "{{$labels.instance}} page status code error more than 1 minutes"
value: "{{ $value }}"
- 先檢視告警規則狀态,目前三條告警規則都沒有被觸發
image.png
- 接下來先關閉其中任意一個節點,模拟伺服器當機。檢視prometheus告警資訊,三條告警被成功觸發。
image.png
- 接下來檢視Alertmanager告警清單,同樣的收到了三條告警資訊
image.png
- 可以看到由于節點當機,導緻這台主機的nginx服務和對應的web頁面均無法通路而産生了大量告警。在實際生産環境中,服務的依賴關系錯綜複雜,例如交換機端口down,可能會導緻伺服器間通信異常,進而收到大量的相關告警,反而無法快速定位出問題。遇到這種情況,就需要梳理告警之間的依賴關系,配置合理的告警抑制政策,避免告警風暴産生。
3. 模拟測試-抑制後
接下來,我們先對這三條告警依賴關系做一個簡單的梳理,三條告警的依賴關系如下圖所示:
- 接下來,我們先對nginx服務異常和web頁面通路異常告警添加一個額外的标簽
,标注這兩條告警同屬一個業務。接下來檢視這三條告警的label,後面配置的告警抑制規則是根據每條告警的标簽比對的。project: test-web
image.png
image.png
image.png
- 接下來,我們編寫告警抑制規則
apiVersion: v1
kind: ConfigMap
metadata:
name: alertmanager-conf
namespace: monitoring
data:
config.yaml: |-
global:
smtp_smarthost: 'smtp.qq.com:465'
smtp_from: '[email protected]'
smtp_auth_username: '[email protected]'
smtp_auth_password: 'XXXXXXX'
smtp_require_tls: false
templates:
- '/etc/alertmanager/tmpl/*.tmpl' # 指定自定義告警模闆位置
route:
receiver: email
group_by:
- alertname
group_wait: 10s
group_interval: 10m
repeat_interval: 1h
receivers:
- name: 'email'
email_configs:
- to: '[email protected]'
send_resolved: false # 告警解除發送恢複通知
html: '{{ template "email-monitor.html" . }}' # 指定告警模闆
headers: { Subject: "告警郵件" } # 郵件主題 如果不寫也可以在模闆中定義預設值
inhibit_rules:
- source_match:
alertname: 'node status is WODN'
instance: k8s-work2
target_match:
project: test-web
- source_match:
severity: critical
target_match:
severity: warning
equal:
- project
其中第一條抑制規則含義為:當收到告警的标簽中instance=k8s-work2并且alertname='node status is WODN’時,觸發抑制規則。後續收到的告警标簽中project=test-web的告警将全部被抑制(也就是nginx告警和page code告警)
第二條抑制規則含義為:當收到告警的标簽中severity=critical時,觸發抑制規則,包含severity=warning的告警将被抑制。需要注意的是,還添加了一個equal标簽,作用就是source和target中都包含project這個标簽,且他們的值一緻時,才會抑制(也就是抑制page code告警)
- 我們先将服務恢複正常狀态
image.png
- 接下來關閉nginx服務,檢視prometheus會發現有page status code error和nginx service status isWODN兩條告警事件
image.png
- 但此時Alertmanager隻有nginx service status is WODN這一條告警事件,另一條page status code error告警被成功抑制。
image.png
- 接下來關閉work2節點,模拟伺服器當機。檢視prometheus告警這三條全部觸發
image.png
- 檢視Alertmanager告警清單,隻有一條node status is WODN,其餘兩條告警被成功抑制。