Grafana系列之面板接入Prometheus Alertmanager

关于Grafana的仪表板Dashboard,以及面板Panel,参考Grafana系列之Dashboard。可以直接在面板上创建Alert,即所谓的Grafana Alert,参考Grafana系列之Grafana Alert。除了Grafana Alert外,面板也可接入Prometheus Alertmanager。

Alertmanager

关于Alertmanager的讲解,网上有很多不错的资料。

配置文件

alertmanager.yaml配置文件如下:

yaml 复制代码
global:
  resolve_timeout: 10m # 10分钟内不再产生告警,则表示告警恢复
inhibit_rules:
- equal:
  - namespace
  - alertname
  source_matchers:
  - severity = critical
  target_matchers:
  - severity =~ warning|info
- equal:
  - namespace
  - alertname
  source_matchers:
  - severity = warning
  target_matchers:
  - severity = info
- equal:
  - namespace
  source_matchers:
  - alertname = InfoInhibitor
  target_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
  - severity
  group_interval: 5m
  group_wait: 30s
  receiver: web.hook.promalert.feishu
  repeat_interval: 60m # 持续产生的告警,每隔1h才发送,避免告警轰炸,默认10m
  routes:
  - 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文件如下:

yaml 复制代码
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    # labels与Prometheus CRD中match ruleSelector -> matchLabels保持一致。
    release: kube-prom-stack
  name: tesla
spec:
  groups:
  - name: tesla
    rules:
      - alert: "tesla登录耗时大于6s"
        expr: 'round(rate(tesla_login_seconds_sum[1m])/rate(tesla_login_seconds_count[1m]), 0.01) > 6'
        for: 0s
        labels:
          severity: critical
        annotations:
          summary: tesla登录耗时大于6s
          description: "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: 0s
        labels:
          severity: critical
        annotations:
          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),可一定程度上解决上面提出的问题。


飞书的告警模板:

可供参考的飞书模板:

yaml 复制代码
{{ $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)

可供参考的邮件模板:

html 复制代码
{{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 />

参考

相关推荐
计算机毕设定制辅导-无忧学长21 小时前
Grafana 与 InfluxDB 可视化深度集成(二)
信息可视化·数据分析·grafana
云游1 天前
大模型性能指标的监控系统(prometheus3.5.0)和可视化工具(grafana12.1.0)基础篇
grafana·prometheus·可视化·监控
qq_232045572 天前
非容器方式安装Prometheus和Grafana,以及nginx配置访问Grafana
nginx·grafana·prometheus
测试开发Kevin2 天前
详解grafana k6 中stage的核心概念与作用
测试工具·压力测试·grafana
夜莺云原生监控2 天前
Prometheus 监控 Kubernetes Cluster 最新极简教程
容器·kubernetes·prometheus
SRETalk3 天前
Prometheus 监控 Kubernetes Cluster 最新极简教程
kubernetes·prometheus
川石课堂软件测试3 天前
JMeter并发测试与多进程测试
功能测试·jmeter·docker·容器·kubernetes·单元测试·prometheus
SRETalk4 天前
夜莺监控的几种架构模式详解
prometheus·victoriametrics·nightingale·夜莺监控
天翼云开发者社区4 天前
Grafana无法启动修复解决
grafana
Ditglu.5 天前
使用Prometheus + Grafana + node_exporter实现Linux服务器性能监控
服务器·grafana·prometheus