關于Grafana的儀表板Dashboard,以及面板Panel,參考Grafana系列之Dashboard。可以直接在面板上創建Alert,即所謂的Grafana Alert,參考Grafana系列之Grafana Alert。除了Grafana Alert外,面板也可接入Prometheus Alertmanager。
Alertmanager
關于Alertmanager的講解,網上有很多不錯的資料。
配置文件
alertmanager.yaml
配置文件如下:
global:resolve_timeout: 10m # 10分鐘內不再產生告警,則表示告警恢復
inhibit_rules:
- equal:- namespace- alertnamesource_matchers:- severity = criticaltarget_matchers:- severity =~ warning|info
- equal:- namespace- alertnamesource_matchers:- severity = warningtarget_matchers:- severity = info
- equal:- namespacesource_matchers:- alertname = InfoInhibitortarget_matchers:- severity = info
- target_matchers:- alertname = InfoInhibitor
receivers:
- name: web.hook.promalert.feishu # 飛書群機器人告警通知webhook_configs:- url: http://prometheus-alert-center:8080/prometheusalert?type=fs&tpl=fs-tpl-pretty&fsurl=https://open.feishu.cn/open-apis/bot/v2/hook/9234ce69-1111-2222-96ce-f9136e47ac7&split=false # 不要試了,我已經篡改了send_resolved: false # 告警恢復后,不發送恢復通知
- name: 'web.hook.promalert.email' # 郵件告警通知webhook_configs:- url: 'http://prometheus-alert-center:8080/prometheusalert?type=email&tpl=email-tpl-pretty&email=aaa@tesla.com,bbb@tesla.com&split=false'send_resolved: false
- name: "null"
route:group_by:- namespace- instance- alertname- severitygroup_interval: 5mgroup_wait: 30sreceiver: web.hook.promalert.feishurepeat_interval: 60m # 持續產生的告警,每隔1h才發送,避免告警轟炸,默認10mroutes:- receiver: web.hook.promalert.feishu- matchers:- alertname = "Watchdog"receiver: "null"
templates:
- /etc/alertmanager/config/*.tmpl
配置中一般會包含以下幾個主要部分:
- 全局配置(global):用于定義一些全局的公共參數,如全局的SMTP配置,Slack配置等內容;
- 模板(templates):用于定義告警通知時的模板,如HTML模板,郵件模板等;
- 告警路由(route):根據標簽匹配,確定當前告警應該如何處理;
- 接收人(receivers):支持郵箱、微信、Slack、Webhook等,接收人一般配合告警路由使用;
- 抑制規則(inhibit_rules):合理設置抑制規則可減少垃圾告警的產生
恢復通知
恢復通知到底要不要發送,不同的團隊可采用不一樣的實踐。
這里給出一個綠色的恢復通知的樣式:
分組
一個規則文件下可以配置若干個告警規則,規則文件也可以有若干個。比較好的做法是,關于節點的放在一個文件里,關于pod的放在一個文件里,業務告警規則放在另一個文件里,最后的效果
實戰
新增一個alert.yaml
文件如下:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:labels:# labels與Prometheus CRD中match ruleSelector -> matchLabels保持一致。release: kube-prom-stackname: tesla
spec:groups:- name: teslarules:- alert: "tesla登錄耗時大于6s"expr: 'round(rate(tesla_login_seconds_sum[1m])/rate(tesla_login_seconds_count[1m]), 0.01) > 6'for: 0slabels:severity: criticalannotations:summary: tesla登錄耗時大于6sdescription: "tesla登錄耗時大于6s<br> 實際耗時: {{ $value }}s<br> <a href=\"http://grafana.test.tesla.com:8800/d/ce83e684dcqv4c/tesla登錄?from=now-5m&to=now&timezone=browser&var-appId={{ $labels.appId }}&var-tenantId={{ $labels.tenantId }}\">查看詳情</a>"- alert: "接口異常"expr: 'round(rate(http_server_requests_seconds_count{status=~"4..|5.."}[1m]), 0.01) > 0'for: 0slabels:severity: criticalannotations:summary: 接口異常description: "接口異常<br> 應用: {{ $labels.job }}<br> 方法: {{ $labels.method }}<br> 狀態碼: {{ $labels.status }}<br> 接口: {{ $labels.uri }}<br> 報錯: {{ $labels.exception }}<br> <a href=\"http://grafana.test.tesla.com:8800/d/ee990bqfj9nuoe/api?from=now-1h&to=now&var-job={{ $labels.job }}&var-uri={{ $labels.uri }}&var-status={{ $labels.status }}\">查看詳情</a>"
然后執行命令:kubectl apply -f alert.yaml -o observe
,或kc apply -f alert.yaml -o observe
,kc是kubecolor的縮寫。
來到Prometheus Alert頁面,會發現新增的告警規則
Prometheus告警有一個獨立的模塊,Alertmanager,告警效果如下
上面直接給出最后的實現效果。
round
分析上面的告警配置,不難發現規則配置的核心自然就是expr
表達式。
一開始并沒有使用round
函數,rate(tesla_login_seconds_sum[1m])/rate(tesla_login_seconds_count[1m]) > 6
,給出的告警是這樣的:
小數點后位數太多,不友好。
description里的這個數據對應于{{ $value }}
,取自于expr
表達式的比較操作符的前面那部分。description里不能用round
等PromQL函數,于是對expr
統一增加round
函數。
踩坑:對所有的expr表達式統一加round
函數。
round
函數不帶小數點,也就是沒有寫成round(0.1)
或round(0.01)
的兩個問題:
- 對API接口的4xx或5xx異常監控:
expr
表達式為round(rate(http_server_requests_seconds_count{status=~"4..|5.."}[1m])) > 0
,意思是過去1分鐘內平均值。試想一下,過去1分鐘有1次接口異常,rate(http_server_requests_seconds_count{status=~"4..|5.."}[1m])
結果是什么?好好想一想,或者去Grafana頁面驗證一下。正確的結果是1/60=0.0166667
,這個數據使用round
取整,肯定不滿足大于0,也就是說本應該告警的事件,發生漏保。 - 四舍五入并不精準:比如說某個登錄請求耗時是6.2秒,經過
round
函數處理后,自然變成6。6.2 > 6
自然成立,round(6.2) > 6
則不成立;本應該告警的事件,因為round
使用不當,告警漏報。
如下圖,指標數是0.0166667的2倍,過去1分鐘發生2次。
結論:統一調整優化round
語法為取兩位小數點,也就是一開始給出的規則配置文件。
跳轉鏈接
告警成功發出后,在告警內容里增加該Prometheus Alert對應的Grafana面板鏈接,這一點很容易想到。
主要說四點:
- 換行符:兼容郵件和markdown,換行符是
<br>
,而不是\n
; - 跳轉鏈接:markdown語法
[some-url](some-url)
支持有限(自己不會),改為使用href
方式; - 轉義字符:description本身是雙引號,在里面使用
href
標簽,需要對href
標簽引入的雙引號加以轉義處理,否則執行kc apply -f alert.yaml
命令失敗,報錯如下面截圖所示。值得一提的是,如果對k8s(的yaml)不熟,死死盯著報錯提示的第18行,就會陷入死胡同。kubectl
執行yaml文件時,會忽略yaml文件里的注釋行;真實的配置錯誤行,并不是報錯提示的那一行。
- 變量定位:配置的跳轉地址寫成 http://grafana.test.tesla.com:8800/d/ee990bqfj9nuoe/api,當然沒有問題。既然是API接口異常,并且Grafana面板里配置有變量,能不能直接跳轉到觸發告警的異常API呢?當然可以,{{ $labels.job }}即可從標簽組里獲取到具體的某個標簽。寫法:http://grafana.test.tesla.com:8800/d/ee990bqfj9nuoe/api?from=now-1h&to=now&var-job={{ $labels.job }}&var-uri={{ $labels.uri }}&var-status={{ $labels.status }}
Markdown
Prometheus Alert提供對Markdown語法的支持,不過需要測試和配置。
有待進一步學習
模板配置
告警方式有很多,本文暫且只考慮和配置飛書、郵件。不管什么樣的通知方式,告警內容都是其中非常核心的一環(也就是上面的配置文件中的templates
模塊)。
當同時接入郵件、飛書、企業微信、阿里云短信,同一套告警內容如何同時適配多個不同的接收終端?
借助于開源項目(https://github.com/feiyu563/PrometheusAlert),可一定程度上解決上面提出的問題。
飛書的告警模板:
可供參考的飛書模板:
{{ $var := .externalURL}}{{range $k,$v:=.alerts}}
{{if eq $v.status "resolved"}}
生產環境(GPU)告警恢復通知
🟡【告警名稱】{{$v.labels.alertname}}
🚨【告警級別】{{$v.labels.severity}}
?【告警狀態】{{$v.status}}
🧭【開始時間】{{GetCSTtime $v.startsAt}}
🧭【結束時間】{{GetCSTtime $v.endsAt}}
📝【告警詳情】{{$v.annotations.description}}
{{else}}
非生產環境(GPU)告警通知
🟡【告警名稱】{{$v.labels.alertname}}
🚨【告警級別】{{$v.labels.severity}}
🔥【告警狀態】{{$v.status}}
🧭【開始時間】{{GetCSTtime $v.startsAt}}
📝【告警詳情】{{$v.annotations.description}}
{{end}}
{{end}}
{{ $urimsg:=""}}{{range $key,$value:=.commonLabels}}{{$urimsg = print $urimsg $key "%3D%22" $value "%22%2C"}}{{end}}[👉 點我屏蔽該告警 👈](http://alert.test.tesla.com/#/silences/new?filter=%7B{{SplitString $urimsg 0 -3}}%7D)
可供參考的郵件模板:
{{if eq .state "ok"}}
<h1><a href ={{.ruleUrl}}>Grafana恢復信息</a></h1>
<h2>{{.ruleName}}</h2>
<h5>告警級別:嚴重</h5>
<h5>開始時間:{{GetCSTtime ""}}</h5>
<h3>{{.message}}</h3>
{{else}}
<h1><a href ={{.ruleUrl}}>Grafana恢復信息</a></h1>
<h2>{{.ruleName}}</h2>
<h5>告警級別:嚴重</h5>
<h5>開始時間:{{GetCSTtime ""}}</h5>
<h3>{{.message}}</h3>
{{end}}
<img src=https://raw.githubusercontent.com/feiyu563/PrometheusAlert/master/doc/alert-center.png />