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 />

参考

相关推荐
龙码精神3 天前
前端嵌入Grafana 报表的自定义方案:隐藏导航栏保留筛选工具
grafana
Cherry的跨界思维4 天前
【AI测试全栈:质量】47、Vue+Prometheus+Grafana实战:打造全方位AI监控面板开发指南
vue.js·人工智能·ci/cd·grafana·prometheus·ai测试·ai全栈
AC赳赳老秦4 天前
云原生AI故障排查新趋势:利用DeepSeek实现高效定位部署报错与性能瓶颈
ide·人工智能·python·云原生·prometheus·ai-native·deepseek
予枫的编程笔记4 天前
【Kafka高级篇】Kafka监控不踩坑:JMX指标暴露+Prometheus+Grafana可视化全流程
kafka·grafana·prometheus·可观测性·jmx·kafka集群调优·中间件监控
AC赳赳老秦5 天前
预见2026:DeepSeek与云平台联动的自动化流程——云原生AI工具演进的核心引擎
人工智能·安全·云原生·架构·自动化·prometheus·deepseek
认真的薛薛5 天前
13.k8s中Prometheus监控集群及其服务,endpoint暴露服务,es采集k8s日志
elasticsearch·kubernetes·prometheus
A-刘晨阳5 天前
K8S部署kube-state-metrics + CAdvisor 并使用 Prometheus 监控 Kubernetes 指标
运维·云原生·kubernetes·云计算·prometheus·cadvisor·state-metrics
AC赳赳老秦6 天前
多模态 AI 驱动办公智能化变革:DeepSeek 赋能图文转写与视频摘要的高效实践
java·ide·人工智能·python·prometheus·ai-native·deepseek