prometheus+alertmanager+webhook實現自定義監控報警系統


prometheus+alertmanager+webhook實現自定義監控報警系統

 

1.概述

上一篇文章prometheus+grafana+mtail+node_exporter實現機器負載及業務監控介紹了使用mtail和node_exporter實現的prometheus無埋點監控機器負載和業務的監控系統,本文是在其基礎上實現自定義報警功能。
Prometheus+Alertmanager 的警報分為兩個部分:

  • Prometheus負責中配置警報規則,將警報發送到Alertmanager
  • Alertmanager 負責管理這些警報,包括沉默,抑制,合並和發送通知

Alertmanager 發送通知有多種方式,其內部集成了郵箱、Slack、企業微信等三種方式,也提供了webhook的方式來擴展報警通知方式,網上也有大量例子實現對第三方軟件的集成,如釘釘等。本文介紹郵件報警方式和通過使用java來搭建webhook自定義通知報警的方式。

本文內容主要分為四塊:

  • prometheus報警規則配置
  • alertmanager配置及部署
  • 關聯prometheus和alertmanager
  • 配置報警通知方式

2.prometheus配置報警規則

prometheus.yml屬性配置

屬性 描述
scrape_interval 樣本采集周期,默認為1分鍾采集一次
evaluation_interval 告警規則計算周期,默認為1分鍾計算一次
rule_files 指定告警規則的文件
scrape_configs job的配置項,里面可配多組job任務
job_name 任務名稱,需要唯一性
static_configs job_name的配置選項,一般使用file_sd_configs 熱加載配置
file_sd_configs job_name的動態配置選項,使用此配置可以實現配置文件的熱加載
files: file_sd_configs配置的服務發現的文件路徑列表,支持.json,.yml或.yaml,路徑最后一層支持通配符*
refresh_interval file_sd_configs中的files重新加載的周期,默認5分鍾

此處我們使用rule_files屬性來設置告警文件

# my global config global: scrape_interval: 15s # 采樣周期 evaluation_interval: 15s # 告警規則計算周期 # Alertmanager configuration alerting: alertmanagers: - static_configs: - targets: # - alertmanager:9093 # 報警規則文件可以指定多個,並且可以使用通配符* rule_files: - "rules/*_rules.yml" # - "second_rules.yml" # 采集job配置 scrape_configs: - job_name: 'prometheus' #使用file_sd_configs熱加載配置文件 file_sd_configs: #指定1分鍾加載一次配置 - refresh_interval: 1m files: - config_prometheus.json - job_name: 'linux_base' file_sd_configs: - refresh_interval: 1m files: - config_exporter.json - job_name: 'service_base' file_sd_configs: - refresh_interval: 1m files: - config_mtail.json - job_name: 'grafana' file_sd_configs: - refresh_interval: 1m files: - config_grafana.json 

設置報警規則,rules/host_rules.yml

groups: # 報警組組名稱 - name: hostStatsAlert #報警組規則 rules: #告警名稱,需唯一 - alert: hostCpuUsageAlert #promQL表達式 expr: sum(avg without (cpu)(irate(node_cpu_seconds_total{mode!='idle'}[5m]))) by (instance) > 0.85 #滿足此表達式持續時間超過for規定的時間才會觸發此報警 for: 1m labels: #嚴重級別 severity: page annotations: #發出的告警標題 summary: "實例 {{ $labels.instance }} CPU 使用率過高" #發出的告警內容 description: "實例{{ $labels.instance }} CPU 使用率超過 85% (當前值為: {{ $value }})" - alert: hostMemUsageAlert expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes)/node_memory_MemTotal_bytes > 0.85 for: 1m labels: severity: page annotations: summary: "實例 {{ $labels.instance }} 內存使用率過高" description: "實例 {{ $labels.instance }} 內存使用率 85% (當前值為: {{ $value }})"

采集任務job配置config_exporter.json配置如下(其他job配置文件類似):

[ { "targets": [ "192.168.113.13:9100"], "labels": { "env": "prod" } }, { "targets": [ "10.12.141.150:9100"], "labels": { "env": "local" } }, { "targets": [ "10.12.141.151:9100"], "labels": { "env": "local2" } } ] 

配置完報警規則重啟prometheus,訪問http://ip:9090/,點擊alerts就能看到配置的報警信息了,如下:
在這里插入圖片描述

3.alertmanager配置及部署

3.1.alertmanager配置

alertmanager會定義一個基於標簽匹配規則的路由樹,用以接收到報警后根據不同的標簽匹配不同的路由,來將報警發送給不同的receiver。如果定義一個路由route則需要接收並處理所有的報警,如果需要區分不同的報警發送給不同的receiver,則需要配置多個子級route來處理不同的報警,而根route此時必須能夠接收處理所有的報警。

#根路由 route: #頂級路由配置的接收者(匹配不到子級路由,會使用根路由發送報警) receiver: 'default-receiver' #設置等待時間,在此等待時間內如果接收到多個報警,則會合並成一個通知發送給receiver group_wait: 30s #兩次報警通知的時間間隔,如:5m,表示發送報警通知后,如果5分鍾內再次接收到報警則不會發送通知 group_interval: 5m #發送相同告警的時間間隔,如:4h,表示4小時內不會發送相同的報警 repeat_interval: 4h #分組規則,如果滿足group_by中包含的標簽,則這些報警會合並為一個通知發給receiver group_by: [cluster, alertname] routes: #子路由的接收者 - receiver: 'database-pager' group_wait: 10s #默認為false。false:配置到滿足條件的子節點點后直接返回,true:匹配到子節點后還會繼續遍歷后續子節點 continue:false #正則匹配,驗證當前標簽service的值是否滿足當前正則的條件 match_re: service: mysql|cassandra #子路由的接收者 - receiver: 'frontend-pager' group_by: [product, environment] #字符串匹配,匹配當前標簽team的值為frontend的報警 match: team: frontend #定義所有接收者 receivers: #接收者名稱 - name: 'default-receiver' #接收者為webhook類型 webhook_configs: #webhook的接收地址 - url: 'http://127.0.0.1:5001/' - name: 'database-pager' webhook_configs: - url: 'http://127.0.0.1:5002/' - name: 'frontend-pager' webhook_configs: - url: 'http://127.0.0.1:5003/'

3.2.alertmanager部署

建議下載最新版本,最新版下載地址請戳此處(可能需要FQ),我使用的版本為alertmanager-0.20.0.linux-amd64.tar.gz,我的版本csdn下載地址請戳
將其解壓到/usr/local后,進入目錄/usr/local/alertmanager-0.20.0.linux-amd64,會有個默認配置文件: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'] 

使用默認配置在后台啟動:

nohup ./alertmanager > alertmanager.out 2>&1 &

查看是否啟動成功:

ps -ef | grep alertmanager 

啟動后訪問http://ip:9093/查看是否啟動成功,點擊status查看alertmanager及其配置,訪問如下(我的配置有改動,請以自己頁面展示為准):
在這里插入圖片描述

4.prometheus關聯alertmanager

prometheus.yml中的alerting標簽下配置上alertmanager的地址即可,配置如下:

# Alertmanager configuration alerting: alertmanagers: - static_configs: - targets: ['192.168.199.23:9093']

添加后重啟prometheus即可。

5.配置報警通知方式

5.1.alertmanager郵箱報警demo

global: #超時時間 resolve_timeout: 5m #smtp地址需要加端口 smtp_smarthost: 'smtp.126.com:25' smtp_from: 'xxx@126.com' #發件人郵箱賬號 smtp_auth_username: 'xxx@126.com' #賬號對應的授權碼(不是密碼),阿里雲個人版郵箱目前好像沒有授權碼,126郵箱授權碼可以在“設置”里面找到 smtp_auth_password: '1qaz2wsx' smtp_require_tls: false route: group_by: ['alertname'] group_wait: 10s group_interval: 1m repeat_interval: 4h receiver: 'mail' receivers: - name: 'mail' email_configs: - to: 'xxx@aliyun.com'

設置后如果有通知,即可收到郵件如下:
在這里插入圖片描述

5.2.alertmanager使用webhook(java)報警demo

global: resolve_timeout: 5m route: group_by: ['alertname'] group_wait: 10s group_interval: 1m repeat_interval: 4h receiver: 'webhook' receivers: - name: 'webhook' webhook_configs: - url: 'http://192.168.199.152/demo'

使用webhook方式,alertmanager會給配置的webhook地址發送一個http類型的post請求,參數為json字符串(字符串類型),如下(此處格式化為json了):

{ "receiver":"webhook", "status":"resolved", "alerts":[ { "status":"resolved", "labels":{ "alertname":"hostCpuUsageAlert", "instance":"192.168.199.24:9100", "severity":"page" }, "annotations":{ "description":"192.168.199.24:9100 CPU 使用率超過 85% (當前值為: 0.9973333333333395)", "summary":"機器 192.168.199.24:9100 CPU 使用率過高" }, "startsAt":"2020-02-29T19:45:21.799548092+08:00", "endsAt":"2020-02-29T19:49:21.799548092+08:00", "generatorURL":"http://localhost.localdomain:9090/graph?g0.expr=sum+by%28instance%29+%28avg+without%28cpu%29+%28irate%28node_cpu_seconds_total%7Bmode%21%3D%22idle%22%7D%5B5m%5D%29%29%29+%3E+0.85&g0.tab=1", "fingerprint":"368e9616d542ab48" } ], "groupLabels":{ "alertname":"hostCpuUsageAlert" }, "commonLabels":{ "alertname":"hostCpuUsageAlert", "instance":"192.168.199.24:9100", "severity":"page" }, "commonAnnotations":{ "description":"192.168.199.24:9100 CPU 使用率超過 85% (當前值為: 0.9973333333333395)", "summary":"機器 192.168.199.24:9100 CPU 使用率過高" }, "externalURL":"http://localhost.localdomain:9093", "version":"4", "groupKey":"{}:{alertname="hostCpuUsageAlert"}" } 

此時需要使用java(其他任何語言都可以,反正只要能處理http的請求就行)搭建個http的請求處理器來處理報警通知,如下:

package com.demo.demo1.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Slf4j @Controller @RequestMapping("/") public class AlertController { @RequestMapping(value = "/demo", produces = "application/json;charset=UTF-8") @ResponseBody public String pstn(@RequestBody String json) { log.debug("alert notify params: {}", json); Map<String, Object> result = new HashMap<>(); result.put("msg", "報警失敗"); result.put("code", 0); if(StringUtils.isBlank(json)){ return JSON.toJSONString(result); } JSONObject jo = JSON.parseObject(json); JSONObject commonAnnotations = jo.getJSONObject("commonAnnotations"); String status = jo.getString("status"); if (commonAnnotations == null) { return JSON.toJSONString(result); } String subject = commonAnnotations.getString("summary"); String content = commonAnnotations.getString("description"); List<String> emailusers = new ArrayList<>(); emailusers.add("xxx@aliyun.com"); List<String> users = new ArrayList<>(); users.add("158*****5043"); try { boolean success = Util.email(subject, content, emailusers); if (success) { result.put("msg", "報警成功"); result.put("code", 1); } } catch (Exception e) { log.error("=alert email notify error. json={}", json, e); } try { boolean success = Util.sms(subject, content, users); if (success) { result.put("msg", "報警成功"); result.put("code", 1); } } catch (Exception e) { log.error("=alert sms notify error. json={}", json, e); } return JSON.toJSONString(result); } } 

6.總結

alertmanager配置功能確認很強大,完全能夠按照自己的目標定義靈活的通知和報警方式,尤其是對webhook的支持,簡直不能更靈活了。而且alertmanager還支持定義template來更清晰的彰顯要通知的內容。但是本人還沒有發現alertmanager該怎么進行配置的熱加載,后面還要再研究下怎么優化通知,避免告警轟炸和提高告警的准確性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM