Docker系列——Grafana+Prometheus+Node-exporter伺服器告警中心(二)

溫一壺清酒發表於2021-05-28

在前一篇博文中介紹,伺服器監控已經部署成功。如果每天都需要人去盯著服務情況,那也不太現實。既然監控平臺已經部署好了,是不是可以自動觸發報警呢?

在上一篇Prometheus架構中有講到,核心元件之一:AlertManager,AlertManager即Prometheus體系中的告警處理中心。所以實現告警功能,可以使用該元件,具體如何實現,我們來看。

AlertManager配置

服務部署

拉取映象

使用命令 docker pull prom/alertmanager:latest

服務啟動

使用如下命令:

docker run -d --name alertmanager -p 9093:9093 \
prom/alertmanager:latest

啟動服務後,通過地址訪問,http://:9093可以看到預設提供的 UI 頁面,不過現在是沒有任何告警資訊的,因為我們還沒有配置報警規則來觸發報警。

配置檔案

AlertManager 預設配置檔案為 alertmanager.yml,在容器內路徑為 /etc/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']

簡單介紹一下主要配置的作用:
• global: 全域性配置,包括報警解決後的超時時間、SMTP 相關配置、各種渠道通知的 API 地址等等。
• route: 用來設定報警的分發策略,它是一個樹狀結構,按照深度優先從左向右的順序進行匹配。
• receivers: 配置告警訊息接受者資訊,例如常用的 email、wechat、slack、webhook 等訊息通知方式。
• inhibit_rules: 抑制規則配置,當存在與另一組匹配的警報(源)時,抑制規則將禁用與一組匹配的警報(目標)。

告警規則

alertmanager配置好後,我們來新增告警規則,就是符合規則,才會推送訊息,規則配置如下:

mkdir -p /root/prometheus/rules && cd /root/prometheus/rules/
vim host.rules

新增如下資訊:

groups:
- name: node-up
  rules:
  - alert: node-up
    expr: up{job="linux"} == 0
    for: 15s
    labels:
      severity: 1
      team: node
    annotations:
      summary: "{{ $labels.instance }} 已停止執行超過 15s!"

說明一下:該 rules 目的是監測 node 是否存活,expr 為 PromQL 表示式驗證特定節點 job="linux" 是否活著,for 表示報警狀態為 Pending 後等待 15s 變成 Firing 狀態,一旦變成 Firing 狀態則將報警傳送到 AlertManager,labels 和 annotations 對該 alert 新增更多的標識說明資訊,所有新增的標籤註解資訊,以及 prometheus.yml 中該 job 已新增 label 都會自動新增到郵件內容中 ,參考規則

prometheus.yml配置檔案

修改prometheus.yml配置檔案,新增 rules 規則檔案,已有內容不變,配置檔案中新增如下內容:

alerting:
  alertmanagers:
    - static_configs:
      - targets: 
        - 'ip:9093'
rule_files:
  - "/etc/prometheus/rules/*.rules"

注意: 這裡rule_files為容器內路徑,需要將本地host.rules檔案掛載到容器內指定路徑,修改 Prometheus 啟動命令如下,並重啟服務。

docker run  -d --name prometheus \
  -p 9090:9090 \
  -v /root/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml  \
  -v /root/prometheus/rules/:/etc/prometheus/rules/  \
prom/prometheus

通過ip+埠訪問,檢視rules,如下所示:

這裡說明一下 Prometheus Alert 告警狀態有三種狀態:Inactive、Pending、Firing。

  • Inactive:非活動狀態,表示正在監控,但是還未有任何警報觸發。
  • Pending:表示這個警報必須被觸發。由於警報可以被分組、壓抑/抑制或靜默/靜音,所以等待驗證,一旦所有的驗證都通過,則將轉到 Firing 狀態。
  • Firing:將警報傳送到 AlertManager,它將按照配置將警報的傳送給所有接收者。一旦警報解除,則將狀態轉到 Inactive,如此迴圈。

說了這麼多,就用推送郵件來實踐下結果。

郵件推送

郵件配置

我們來配置一下使用 Email 方式通知報警資訊,這裡以 QQ 郵箱為例,新建目錄 mkdir -p /root/prometheus/alertmanager/ && cd /root/prometheus/alertmanager/

使用vim命令 vim alertmanager.yml,配置檔案中新增如下內容:

global:
  resolve_timeout: 5m
  smtp_from: '11111111@qq.com'
  smtp_smarthost: 'smtp.qq.com:465'
  smtp_auth_username: '11111111@qq.com'
  smtp_auth_password: 'XXXXXXXXX'
  smtp_hello: 'qq.com'
  smtp_require_tls: false
route:
  group_by: ['alertname']
  group_wait: 5s
  group_interval: 5s
  repeat_interval: 5m
  receiver: 'email'
receivers:
- name: 'email'
  email_configs:
  - to: '222222222@foxmail.com'
    send_resolved: true
    #insecure_skip_verify: true
inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'dev', 'instance']

其中幾個關鍵的配置說明一下:

  • smtp_smarthost: 這裡為 QQ 郵箱 SMTP 服務地址,官方地址為 smtp.qq.com 埠為 465 或 587,同時要設定開啟 POP3/SMTP 服務。
  • smtp_auth_password: 這裡為第三方登入 QQ 郵箱的授權碼,非 QQ 賬戶登入密碼,否則會報錯,獲取方式在 QQ 郵箱服務端設定開啟 POP3/SMTP 服務時會提示。
  • smtp_require_tls: 是否使用 tls,根據環境不同,來選擇開啟和關閉。如果提示報錯 email.loginAuth failed: 530 Must issue a STARTTLS command first,那麼就需要設定為 true。著重說明一下,如果開啟了 tls,提示報錯 starttls failed: x509: certificate signed by unknown authority,需要在 email_configs 下配置 insecure_skip_verify: true 來跳過 tls 驗證。

重啟AlertManager

修改 AlertManager 啟動命令,將本地alertmanager.yml檔案掛載到容器內指定位置,是配置生效,命令如下所示:

docker run -d --name alertmanager -p 9093:9093 \
-v /root/prometheus/alertmanager/:/etc/alertmanager/ \
prom/alertmanager:latest

觸發報警

之前我們定義的 rule 規則為監測 job="linux" Node 是否活著,那麼就可以停掉node-exporter服務來間接起到 Node Down 的作用,從而達到報警條件,觸發報警規則。

使用命令 docker stop 容器id,停止服務後,等待 60s 之後可以看到 Prometheus target 裡面 linux 狀態為 unhealthy 狀態,等待 60s 後,alert 頁面由綠色 node-up (0 active) Inactive 狀態變成了黃色 node-up (1 active) Pending 狀態,繼續等待 60s 後狀態變成紅色 Firing 狀態,向 AlertManager 傳送報警資訊,此時 AlertManager 則按照配置規則向接受者傳送郵件告警。

停掉服務後,我們來看狀態的變化,首先是Inactive狀態,AlertManager也沒有報警資訊,如下所示:

等待60s後,再次檢視服務狀態,變成了Pending狀態,如下所示:

繼續等待 60s,變成了Firing狀態,如下所示:

並且AlertManager 有報警資訊,如下所示:

檢視自己的郵件,收到了郵件推送,如下所示:

服務一直處於停止狀態,會一直推送訊息,5分鐘一次,如下所示:

說到這裡,對有些時間節點有點不理解,這裡有幾個地方需要解釋一下:
• 每次停止/恢復服務後,60s 之後才會發現 Alert 狀態變化,是因為 prometheus.yml中 global -> scrape_interval: 60s 配置決定的,如果覺得等待 60s 時間太長,可以修改小一些,可以全域性修改,也可以區域性修改。例如區域性修改 linux 等待時間為 5s。
• Alert 狀態變化時會等待 15s 才發生改變,是因為host.rules中配置了for: 15s狀態變化等待時間。
• 報警觸發後,每隔 5m 會自動傳送報警郵件(服務未恢復正常期間),是因為alertmanager.yml中route -> repeat_interval: 5m配置決定的。

郵件自定義

在剛才的郵件內容中,基本資訊有,但不直觀,那可不可以自定義模板內容呢?答案是有的,我們繼續來看。

自定義模板

自定義一個郵件模板,在/root/prometheus/alertmanager/目錄下,vim email.tmpl配置如下:

{{ define "email.from" }}1111111111@qq.com{{ end }}
{{ define "email.to" }}222222222222@foxmail.com{{ end }}
{{ define "email.html" }}
{{ range .Alerts }}
=========start==========<br>
告警程式: prometheus_alert <br>
告警級別: {{ .Labels.severity }} 級 <br>
告警型別: {{ .Labels.alertname }} <br>
故障主機: {{ .Labels.instance }} <br>
告警主題: {{ .Annotations.summary }} <br>
告警詳情: {{ .Annotations.description }} <br>
觸發時間: {{ .StartsAt.Format "2006-01-02 08:08:08" }} <br>
=========end==========<br>
{{ end }}
{{ end }}

簡單說明一下,上邊模板檔案配置了 email.from、email.to、email.to.html 三種模板變數,可以在 alertmanager.yml 檔案中直接配置引用。這裡 email.to.html 就是要傳送的郵件內容,支援 Html 和 Text 格式,這裡為了顯示好看,採用 Html 格式簡單顯示資訊。下邊 {{ range .Alerts }} 是個迴圈語法,用於迴圈獲取匹配的 Alerts 的資訊,下邊的告警資訊跟上邊預設郵件顯示資訊一樣,只是提取了部分核心值來展示。

修改alertmanager.yml

由於已經定義了變數,所以我們在alertmanager配置檔案中可以引用變數,並且引用我們自定義的模板,引用模板需要增加 templates ,配置如下:

global:
  resolve_timeout: 5m
  smtp_from: '{{ template "email.from" . }}'
  smtp_smarthost: 'smtp.qq.com:465'
  smtp_auth_username: '{{ template "email.from" . }}'
  smtp_auth_password: 'XXXXXXXXXXXXXXXXX'
  smtp_hello: 'qq.com'
  smtp_require_tls: false
templates:
  - '/etc/alertmanager/*.tmpl'
route:
  group_by: ['alertname']
  group_wait: 5s
  group_interval: 5s
  repeat_interval: 5m
  receiver: 'email'
receivers:
- name: 'email'
  email_configs:
  - to: '{{ template "email.to" . }}'
    html: '{{ template "email.html" . }}'
    send_resolved: true
    #insecure_skip_verify: true
inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'dev', 'instance']

重啟AlertManager

修改 AlertManager 啟動命令,將本地email.tmpl檔案掛載到容器內指定位置並重啟。由於我的配置是跟alertmanager的配置檔案在同一個目錄下,所以不用重新掛載,重啟容器即可。
我們將node服務停止,再次查收郵件,檢視下效果,如下所示:

模板優化

時間格式

我們從上圖可以看出,郵件內容格式已經改變,但時間卻顯示的有點離譜,原因是時間格式問題,修改郵件模板,針對時間配置格式,如下所示:

{{ define "email.from" }}11111111111@qq.com{{ end }}
{{ define "email.to" }}2222222222222@foxmail.com{{ end }}
{{ define "email.html" }}
{{ range .Alerts }}
=========start==========<br>
告警程式: prometheus_alert <br>
告警級別: {{ .Labels.severity }} 級 <br>
告警型別: {{ .Labels.alertname }} <br>
故障主機: {{ .Labels.instance }} <br>
告警主題: {{ .Annotations.summary }} <br>
告警詳情: {{ .Annotations.description }} <br>
觸發時間: {{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} <br>
=========end==========<br>
{{ end }}
{{ end }}

儲存後再次重啟alertmanager服務,重新操作一遍之前的動作,檢視最終的郵件效果,如下所示:

配置時間格式後,我們看效果圖,時間是修正了的。

郵件標題

還可以自定義郵件標題,修改alertmanager.yml配置檔案,增加引數:headers即可,如下所示:

receivers:
- name: 'email'
  email_configs:
  - to: '{{ template "email.to" . }}'
    html: '{{ template "email.html" . }}'
    send_resolved: true
    headers: { Subject: "{{ .CommonAnnotations.summary }}" }

配置好重啟alertmanager服務,再次觸發告警郵件,收到的內容如下:

以上就是今天的分享內容,報警系統功能就已完成,後續介紹微信、釘釘推送,下期再見。

相關文章