起因
公司这边主要是通过Prometheus来进行监控的,告警媒介主要是通过webhook在钉钉群中完成告警。
但是现在的告警信息只能知道有异常,不能快速定位,而且报警信息过多的话,很容易遗漏,不能根据报警信息找到对应的人员,因此想通过告警来自动完成ding某人的操作。
之前的报警信息如下,采用markdown类型,只能知道机器和端口,需要根据端口去找对应的进程,而进程名称和文件夹名称不对应,像我这种刚接触这种环境的,就比较痛苦(图片外链比较麻烦,base64串太长了此处就用文本展示了)。
1 2 3 4 5 6 7
| 监控告警-服务异常 Prometheus恢复信息 告警级别:提示 开始时间:time 结束时间:time 故障主机IP:ip:port ip:port:tomcat_jvm服务异常,已恢复!
|
之前对Prometheus了解不对,正好趁此机会好好了解下相关生态
学习Prometheus推荐去看下面的文章
https://yunlzheng.gitbook.io/prometheus-book/
Prometheus监控项配置
详细的概念此处就不再描述了,监控项的配置需要修改三个文件
分组告警
此处的分组告警有两种
一种是根据不同的报警级别等条件实现相同级别的告警只发送一条。
另一种就是根据不同的业务类型发送给不同的业务团队,这个就需要自己去定义标签,监控任务来完成了。
prometheus.yml
只截取了监控任务的配置
1 2 3 4 5 6 7 8 9 10 11
| #监控任务名称 - job_name: "tomcat_jvm_MedicalCloud" #获取监控的通用url metrics_path: /actuator/prometheus #获取监控时间的间隔 scrape_interval: 30s file_sd_configs: - refresh_interval: 1m files: #具体的监控项配置文件 - "/etc/prometheus/conf.d/tomcat_jvm/tomcat_jvm.yml"
|
rules.yml
报警条件的定义和自定义标签的添加,为了分组告警
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| groups: - name: alert_system rules: - alert: 监控告警-大人出事了 #报警条件 expr: up{job="tomcat_"} == 0 for: 2m #自定义标签,想要实现业务分组,此处很重要 labels: service: group1 serverity: warning annotations: summary: "{{$labels.project}} {{$labels.instance}} 无法访问!" description: "{{$labels.project}} {{$labels.instance}} 无法访问!" resolved: "{{$labels.project}} {{$labels.instance}} 无法访问,已恢复!" grafana_url: "http://grafana.cn/"
|
tomcat_jvm.yml
具体的监控机器
1 2 3 4 5
| - targets: - "ip:port" labels: #这里可以自定义应用名称 业务组等都可以在这里加上 instance: ip:port
|
报警方式
一般的报警是通过alertmanager进行的,流程是Prometheus根据监控条件promQL定时查询,如果有结果 就触发报警,Prometheus自身不会发出告警的,需要通过alert manager进行发送。
我这里是 不需要进行@某人操作的 通过alertmanager进行发送
需要@某人的则通过prometheus-webhook-dingtalk进行发送报警
alert manager告警优先级
推荐阅读:https://aleiwu.com/post/alertmanager/
alertmanager.yml
alertmanager github地址
github上面有详细的使用教程
报警的转发是通过alert manager进行完成的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| global: resolve_timeout: 1m route: group_wait: 30s # 在组内等待所配置的时间,如果同组内,30秒内出现相同报警,在一个组内出现。 group_interval: 1m # 如果组内内容不变化,5m后发送。 repeat_interval: 24h # 发送报警间隔,如果指定时间内没有修复,则重新发送报警 group_by: ['alertname','project'] # 报警分组,根据 prometheus 的 lables 进行报警分组,这些警报会合并为一个通知发送给接收器,也就是警报分组。 receiver: ops routes: #报警通知的对象 - receiver: 'group1' group_wait: 10s #匹配Prometheus的rules.yml中的标签 match_re: service: 'group1' serverity: critical|warning - receiver: 'ops' group_wait: 10s match_re: serverity: critical|warning
receivers: #通知对象的webhook地址 - name: 'ops' webhook_configs: #这里的url通过alertmanager的web界面生成:http://ip:8080/template - url: '' #业务组告警 - name: 'group1' webhook_configs: #此处的url通过prometheus-webhook-dingtalk的配置生成 - url: 'http://localhost:8060/dingtalk/webhook_mention_users/send'
|
prometheus-webhook-dingtalk markdown告警
prometheus-webhook-dingtalk组件支持markdown类型的告警,因为钉钉webhook接口的限制,必须要在告警文本中含有@手机号的信息才可以
例子:在Prometheus的rule.yml中添加手机号信息
Users: “@1831101,@186501”
在prometheus-webhook-dingtalk的config.yml中填写
mention:
mobiles: [“1831101”,”186501”]
完成以上配置即可实现markdown类型的告警消息。
prometheus-webhook-dingtalk
prometheus-webhook-dingtalk
github上面有详细的介绍,但是根据它的介绍配置完后,无法进行@某人的操作
通过分析它的issue 试了好长时间才完成配置
issue
结论
- prometheus-webhook-dingtalk默认为markdown形式的报警,写在代码中的,跟template.tmpl没有关系
- @某人的操作必须要告警文本改为文本形式,markdown形式不行(issue中有说尝试makrdown@所有人成功的)
- 钉钉群机器人接口信息中是有写支持markdown形式的
- 不能使用它提供好的包,需要下载源码修改notifier/notification.go中的代码 重新编译
修改代码
notifier/notification.go
修改的72 73 74
pkg/models/dingtalk.go代码修改notifier/notification.go
修改后重新编译成包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 60 func (r *DingNotificationBuilder) Build(m *models.WebhookMessage) (*models.DingTalkNotification, error) { 61 title, err := r.renderTitle(m) 62 if err != nil { 63 return nil, err 64 } 65 content, err := r.renderText(m) 66 if err != nil { 67 return nil, err 68 } 69 70 notification := &models.DingTalkNotification{ 71 MessageType: "text", 72 Text: &models.DingTalkNotificationText{ 73 Title: title, 74 Content: content, 75 }, 76 } 77 78 79 notification.At = &models.DingTalkNotificationAt{ 80 IsAtAll: r.target.Mention.All, 81 AtMobiles: r.target.Mention.Mobiles, 82 } 83 84 return notification, nil 85 }
|
prometheus-webhook-dingtalk 源码安装
源码安装博文地址:https://blog.csdn.net/Buster_ZR/article/details/105848811\
/etc/prometheus-webhook-dingtalk/config.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #模板文件地址 templates: - /etc/prometheus-webhook-dingtalk/template.tmpl
targets: webhook1: url: https: # secret for signature secret: SEC000000000000000000000 webhook2: url: https: webhook_legacy: url: https: # Customize template content message: # Use legacy template title: '{{ template "legacy.title" . }}' text: '{{ template "legacy.content" . }}' webhook_mention_all: url: https: mention: all: true webhook_mention_users: #换成自己webhook的token即可 url: https: mention: #手机号为对应人员的手机号,多个手机号通过"183111","150222",完成即可 mobiles: ["1811111111"]
|
/etc/prometheus-webhook-dingtalk/template.tmpl
它的template是golang的template语法,需要自己去定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| {{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "Firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }} {{ define "__alertmanagerURL" }}{{ .ExternalURL }}/#/alerts?receiver={{ .Receiver }}{{ end }}
{{ define "__text_alert_list" }}{{ range . }} **Labels** {{ range .Labels.SortedPairs }} - {{ .Name }}: {{ .Value | markdown | html }} {{ end }} **Annotations** {{ range .Annotations.SortedPairs }} - {{ .Name }}: {{ .Value | markdown | html }} {{ end }} **Source:** [{{ .GeneratorURL }}]({{ .GeneratorURL }}) {{ end }}{{ end }}
{{ define "default.__text_alert_list" }}{{ range . }}
------------------------------------------------------------------------------------ **告警级别:** {{ .Labels.serverity | upper }}
**运营团队:** {{ .Labels.team | upper }}
**触发时间:** {{ dateInZone "2006.01.02 15:04:05" (.StartsAt) "Asia/Shanghai" }}
**结束时间:** {{ dateInZone "2006.01.02 15:04:05" (.EndsAt) "Asia/Shanghai" }}
**事件信息:** {{ range .Labels.SortedPairs }}{{ if and (ne (.Name) "serverity") (ne (.Name) "summary") (ne (.Name) "team") }} - {{ .Name }}: {{ .Value | markdown | html }} {{ end }}{{ end }} {{ end }} {{ end }}
-----------------------------------------------------------------------------------
{{ if gt (len .Alerts.Resolved) 0 -}} {{ template "default.__text_alertresovle_list" .Alerts.Resolved }}
{{- end }}
|
告警信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #### \[RESOLVED\] **[监控告警-服务异常](http://url/#/alerts?receiver=ops)**
**Alerts Resolved**
------------------------------------------------------------------------------------ **告警级别:**
**运营团队:**
**触发时间:** 2021.04.02 10:07:16
**结束时间:** 2021.04.02 10:23:46
**事件信息:** - alertname: 监控告警-服务异常 - instance: ip - job: node\_exporter\_coll - level: 提示 - serverity: warning
@A
|
后记
这只是一个业务分组 @某人的初步过程,很多地方需要去优化如告警信息,分组的标签等