AlertManager实现监控告警

Prometheus自身不具备告警能力,因此需要结合第三方告警程序来实现监控指标告警。

AlertManager是一款不错的告警程序,首先由prometheus配置告警规则,当告警规则触发后,会把告警信息推送给Altermanager,AlertManager收到告警之后在根据配置的路由,根据报警级别不同分别发送给不同的receive(收件人),AlertManager可以实现email、企业微信等报警

Prometheus作为客户端Alertmanager负责处理由客户端发来的告警通知。对告警通知进行分组、去重后,根据路由规则将其路由到不同的receiver。
Prometheus-Alerts-1

Prometheus监控系统的告警逻辑

首先要配置Prometheus成为Alertmanager的告警客户端;同时Alertmanager也是应用程序,它自身同样应该纳入prometheus的监控目标;Alertmanager也通过默认端口9093metrics路径暴露自身的指标。

部署AlertManager以及配置文件介绍

Altermanager是一个独立的go二进制程序,需要独立部署及维护;
按需下载相应的程序包,展开至特定的目录下即可运行;例如:

1
2
[root@k8s-m1 ~]# wget https://github.com/prometheus/alertmanager/releases/download/v0.22.2/alertmanager-0.22.2.linux-amd64.tar.gz
[root@k8s-m1 ~]# tar -zxv -f alertmanager-0.22.2.linux-amd64.tar.gz

配置文件介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
global:
​ resolve_timeout //解析超时时间,也就是报警恢复不是立马发送的,而是在一个时间范围内不在触发报警,才能发送恢复报警,默认为5分钟
​ smtp_from //收件人的邮箱地址
​ smtp_smarthost //邮箱提供商的smtp地址
​ smtp_auth_username //收件人的邮箱账号
​ smtp_auth_password //邮箱授权码
​ smtp_require_tls //是否需要tls协议,默认是true
​ wechart_api_url //微信api地址
​ wbchart_api_secret //密码
​ wechat_api_corp_id //机器人应用的id
route:
​ group_by //采用哪个标签作为分组
​ group_wait //分组等待的时间,收到报警不是立马发送出去,而是等待一段时间,看看同一组中是否有其他报警,如果有一并发送
​ group_interval //告警时间间隔
​ repeat_interval //重复告警时间间隔,可以减少发送告警的频率
​ receiver //接收者是谁
routes //子路由配置

receivers:
​ name //接收者的名字,这里和route中的receiver对应
​ email_configs
​ - to //接收者的邮箱地址

配置AlertManager邮箱告警

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.163.com:465'
smtp_from: 'system71@163.com'
smtp_auth_username: 'system71@163.com'
smtp_auth_password: 'Ye1111111'
smtp_require_tls: false

route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 10m
receiver: 'mail'
receivers:
- name: 'mail'
email_configs:
- to: '9146002@qq.com'

配置prometheus集成AlertManager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.修改配置文件
[root@prometheus-server ~]# vim /data/prometheus/prometheus.yml
alerting:
AlertManagers:
- static_configs:
- targets:
- 127.0.0.1:9093 #AlertManager地址

rule_files: #告警规则路径
- "rules/alerts.yml"

2.创建rules告警规则目录
[root@prometheus-server ~]# mkdir /data/prometheus/rules

3.加载配置
[root@prometheus-server ~]# curl -XPOST 127.0.0.1:9090/-/reload

配置已更新,目前已经可以使用AlertManager报警了
Prometheus-Alerts-2

告警规则

告警规则语法

1
2
3
4
5
6
7
8
9
10
11
12
groups:                                              //定义一个告警规则组
- name: general.rules //组名,可以将同一类型的报警放到一个分组中
rules: //定义告警规则,可以有多个
- alert: 主机宕机 //告警名称,也就是告警信息的标题,一个alert代表一个告警规则
expr: up == 0 //表达式,根据表达式的值进行匹配
for: 5m //报警收到后多长时间后发送报警信息
labels: //定义标签
serverity: error //告警级别,有warning、error等
annotations: //定义告警内容
summary: "主机 {{ $labels.instance }} 停止工作" //消息内容,$labels.instance就是监控项中的标签变量
description: "{{ $labels.instance }} job {{ $labels.job }} 已经宕机5分钟以上!" //详细描述

告警模板

Prometheus支持在告警中使用模板;例如,我们上面的示例中就用到了模板。

1
2
3
4
5
* 告警模板是指在告警中的标签和注解上引用时间序列的标签和样本值的方法;
* 它使用标准的Go模板语法,并暴露一些包含时间序列标签和值的变量;
* 标签引用: {{ $labels.<label_name> }}
* 指标样本值引用: {{ $value }}
* 若要在description注解中引用触发告警的时间序列上的instance和job标签的值,可分别使用{{ $labels.instance }}{{ $labels.job }};

点击右上角的Show annotations可以显示模板被替换后的结果。注意下面Labels中的标签是从Target中完全复制过来的,而Alertnameserverity标签是我们在编写Alert规则时添加进去的。
Prometheus-Alerts-4

告警规则状态

告警规则分为三种

  • inactive:无任何报警,一切正常
  • pending:已触发阈值,但未满足告警持续时间,也就是在告警规则中写的for,在for规定的时间内触发都不会发送给AlertManager,当for持续时间一过会立即发送给AlertManager
  • firing:已触发阈值且满足告警持续时间,告警发送给接收者

Prometheus-Alerts-3

编写主机宕机告警规则

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
1.编写规则
[root@prometheus-server /data/prometheus]# vim rules/alerts.yml
groups:
- name: general.rules
rules:
- alert: 主机宕机
expr: up == 0
for: 5m
labels:
serverity: error
annotations:
summary: "主机 {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }} job {{ $labels.job }} 已经宕机5分钟以上!"

2.检查语法
[root@prometheus-server /data/prometheus]# promtool check config /data/prometheus/prometheus.yml
Checking /data/prometheus/prometheus.yml
SUCCESS: 1 rule files found

Checking /data/prometheus/rules/alerts.yml
SUCCESS: 1 rules found

3.加载配置
[root@prometheus-server /data/prometheus]# curl -XPOST 127.0.0.1:49100/-/reload

在页面的Statusrules下即可看到我们创建的告警规则
Prometheus-Alerts-5

在alert也可以看到告警规则有没有触发,没有触发的情况下是绿色显示;红色firing表示已经发送了告警。
Prometheus-Alerts-6

AlertManager页面也已经收到了主机宕机推送过来的告警信息
Prometheus-Alerts-7

查看是否收到邮件报警内容

已经收到,至此我们的流程已经跑通
Prometheus-Alerts-8

同类告警规则触发

同类告警是指:prometheus的告警规则是对所有监控实例都生效的,也就是当同一种类型的告警触发后会显示在一起,并且发送一封邮件。
Prometheus-Alerts-9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
global:
smtp_smarthost: 'smtp.163.com:465'
smtp_from: 'system71@163.com'
smtp_auth_username: 'system71@163.com'
smtp_auth_password: 'Ye11111111'
smtp_require_tls: false
route:
group_by: ['instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 10m
receiver: 'mail'
receivers:
- name: 'mail'
email_configs:
- to: '9146002@qq.com'

例如上面我使用instance作为分组,然后就会有4个组,这样我会就收到4封告警邮件。

Prometheus-Alerts-10

Prometheus-Alerts-11

如果我使用alertname作为分组那么我只会收到一封邮件,他会把4个告警合并成一封邮件发送。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
global:
smtp_smarthost: 'smtp.163.com:465'
smtp_from: 'system71@163.com'
smtp_auth_username: 'system71@163.com'
smtp_auth_password: 'Ye11111111'
smtp_require_tls: false
route:
group_by: ['alertname']
group_wait: 30s
group_interval: 5m
repeat_interval: 10m
receiver: 'mail'
receivers:
- name: 'mail'
email_configs:
- to: '9146002@qq.com'

只有一个组所以会合并同组的告警一起发送
Prometheus-Alerts-32

Prometheus-Alerts-12

AlertManager告警路由配置

路由配置介绍

alertmanager路由配置可以将不同的告警级别分别发送给不同的邮件接收人

Alertmanager的route配置段支持定义“树”状路由表,入口位置称为根节点,每个子节点可以基于匹配条件定义出一个独立的路由分支;

  • 所有告警都将进入路由根节点,而后进行子节点遍历;
  • 若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止;否则,将继续匹配后续的子节点;

Prometheus-Alerts-25

route路由配置文件介绍

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
route:
group_by: ['alertname'] //定义分组,根据label标签进行分组
group_wait: 10s //分组等待时间,也就是说在10秒内同一个组中有没有一起报警的,如果有则同时发出报警邮件,也就是有2个报警同时发在一个邮件
group_interval: 10s //告警时间间隔
repeat_interval: 10m //重复告警间隔,也就是触发的一个告警在10分钟内没有处理则再次发一封邮件。
continue: false //若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止。否则,将继续匹配后续的子节点;
receiver: 'yunwei' //默认邮箱
routes: //启用一个子路由
- receiver: 'dba' //接收者为dba
group_wait: 10s //分组等待时间
match_re: //匹配一个正则
service: mysql|db //service标签包含mysql和db的统一发送给dba的邮箱
continue: false //若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止。否则,将继续匹配后续的子节点;
- receiver: 'yunwei' //接收者为yunwei
group_wait: 10s //分组时间
match_re:
serverity: error //将serverity标签值包含error的发送给yunwei的邮箱
continue: false //若路由上的continue字段的值为false,则遇到第一个匹配的路由分支后即终止。否则,将继续匹配后续的子节点;

receivers: //定义接收者的邮箱
- name: 'yunwei' //接收者名字,要和routes中的receiver对应
email_configs:
- to: '9146002@qq.com' //yunwei的邮箱地址
- name: 'dba' //接收者名字,要和routes中的receiver对应
email_configs:
- to: 'system51@126.com' //dba的邮箱地址

新的报警时间为上次报警之后的group_interval时间
重复报警时间为,group_interval+repeat_interval

上面的match_re是匹配Alerts中的Lables,这里我为其中一个节点打个service标签后面测试用。
Prometheus-Alerts-13

需求描述

需求:server标签包含db、mysql的发送给dba的邮箱,其他的都发送给运维的邮箱

最终效果:要求关于mysql等数据库的告警发送给dba、其他的信息发送给运维

alertmanager实现不同的告警内容发送给不同的接收人

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
1.修改配置文件
[root@prometheus-server /data/AlertManager]# vim AlertManager.yml
global:
smtp_smarthost: 'smtp.163.com:465'
smtp_from: 'system71@163.com'
smtp_auth_username: 'system71@163.com'
smtp_auth_password: 'Ye111111111'
smtp_require_tls: false

route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 10m
receiver: 'yunwei'
routes:
- receiver: 'dba'
group_wait: 10s
match_re:
service: mysql|db
- receiver: 'yunwei'
group_wait: 10s
match_re:
serverity: error

receivers:
- name: 'yunwei'
email_configs:
- to: '9146002@qq.com'
- name: 'dba'
email_configs:
- to: 'system51@126.com'

2.重启生效
[root@prometheus-server /data/AlertManager]# ps aux | grep alert | grep -v grep | awk '{print $2}' |xargs kill -HUP

配置已生效
Prometheus-Alerts-14

编写告警规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1.编写规则
[root@prometheus-server /data/prometheus]# vim rules/alerts.yml
groups:
- name: general.rules
rules:
- alert: 主机宕机
expr: up{service!="mysql"} == 0 #这里取反不然会获取到下面mysql的up
for: 1m
labels:
serverity: error
annotations:
summary: "主机 {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }} job {{ $labels.job }} 已经宕机5分钟以上!"
- alert: mysql宕机
expr: up{service="mysql"} == 0
for: 1m
labels:
service: mysql
annotations:
summary: "主机 {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }} job {{ $labels.job }} 已经宕机5分钟以上!"

2.加载配置
[root@prometheus-server /data/prometheus]# curl -XPOST 127.0.0.1:9090/-/reload

Prometheus-Alerts-15

如果不设置 expr: up{service!="mysql"} == 0 标签取反就会出现下面这种情况,dba邮箱会收到两封邮件。
Prometheus-Alerts-18

error已经发送给运维邮箱

Prometheus-Alerts-16

mysql已经发送给dba邮箱

Prometheus-Alerts-17

AlertManager分组是两个分组

Prometheus-Alerts-19

AlertManager告警收敛

告警分组

分组就是将类似性质的警报分类为单个通知,比如服务器宕机、应用挂掉,这种类型的告警可以分到一个组中,分到一个组时,当同一时间内触发了多条告警,这时都会发送到同一封邮件中,可以避免因告警邮件太多而忽视了重要信息。

这封邮件就很好的说明了这个分组的意义

由于prometheus编写的规则是对所有服务器生效的,因此所有服务器仅需要创建一个类型的报警即可,当同一时间段多台主机触发了这个告警,则会同时向管理员发送一条报警邮件,同种类型告警主要是以alertname来区分的

Prometheus-Alerts-20

AlertManager分组语法

1
2
3
4
5
route:
group_by: [‘alertname’] //根据标签进行分组,alertname就是告警规则的名称,多个标签可以以逗号隔开
group_wait: 10s //发送告警等待时间,也就是一个时间范围内,如果同一组中有其他报警则一并发送
group_interval: 10s //当触发了一组告警后,下一组报警触发的间隔
repeat_interval: 10m //重复报警的时间间隔,也就是当触发了instance down报警后,如果一直没有解决,那么再隔多长时间报警

告警抑制

抑制:当警报发出后,停止重复发送由此警报引发的其他警报

通过抑制可以避免运维收到大量的告警邮件,且都是同一个报警,只是级别不同,我们可以通过抑制限制当这个警报触发了严重级别的告警后,则不再触发警告级别的告警

例如:当集群中的某一个主机节点异常宕机导致告警NodeDown被触发,同时在告警规则中定义了告警级别serverity=critical。由于主机异常宕机,会导致该主机上部署的所有服务和中间件不可用并触发报警。根据抑制规则的定义,如果有新的告警级别为serverity=warning,并且告警中标签'alertname'、'dev'、'instance'的值与NodeDown告警的相同,则说明新的告警是由NodeDown导致的,则启动抑制机制停止向接收器发送通知。

注:也就是节点宕机设置标签为serverity=critical,而节点上的应用告警设置为serverity=warning,当节点宕机后可以使用抑制的方法,仅发送一条节点宕机的信息,而不是发送多条信息。例如:节点宕机信息和应用不可用信息。

配置语法:

1
2
3
4
5
6
inhibit_rules:
- source_match:
serverity: 'critical' //源标签警报触发时抑制含有目标标签的警报,在当前警报匹配serverity=critical
target_match:
serverity: 'warning' //抑制`serverity=warning`类型告警
equal: ['alertname', 'dev', 'instance'] //告警中包含的分组名称。标签内容相同才会抑制,也就是说警报中三个标签值相同才会被抑制。

告警静默

静默就是值在一段时间内不再触发某一个报警,集进入维护阶段

创建一个静默规则

访问AlertManager的9093端口

1.点击右上角的new silence
Prometheus-Alerts-21

2.添加静默配置信息
Prometheus-Alerts-22

3.这时再由docker报警触发后就不会发送邮件了
Prometheus-Alerts-23

4.prometheus触发一条告警实现的流程
首先由prometheus系统进行监控,当一个监控项的阈值到达一定指标时,再由告警规则中配置的for持续时间进行判断,当在一定时间内都超过了阈值,则将报警推送给AlertManager,AlertManager收到报警后进行分组、抑制、静默,最后在通过我们配置的接收器,将报警发送给邮箱、微信、钉钉
Prometheus-Alerts-24

AlertManager实现企业微信报警

AlertManager对接企业微信

AlertManager支持的报警方式有邮件报警、钉钉报警、微信报警,本次将实现企业微信报警,首先你要具有企业微信管理员的权限,如果没有可以自己注册一个,进行测试,我这里有自行注册的企业微信。

第一步登录进入以后,在应用管理中新建应用
Prometheus-Alerts-26

创建成功以后如下图
Prometheus-Alerts-27

这时候需要把 AgentId 和 Secret 记录下来,对于你的这种Secret信息,最好管理好,我的用过就会删除,所以不用担心安全隐患。

注册完企业微信就会有一个部门,后面我又新增了一个test部门,每个部门的ID不一样。主要是警报需要分级,所以需要单独处理,在这里使用的的单独的配置。

Prometheus-Alerts-28

我的企业—最下面就会有企业id

Prometheus-Alerts-29

配置alertmanager支持微信报警

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:
- 'wechat/wechat.tmpl' # 自定义告警模板

route:
group_by: ['alertname']
group_wait: 10s
group_interval: 1m
repeat_interval: 1m
receiver: yunwei
routes:
- receiver: 'db'
group_wait: 10s
match_re:
service: mysql|db
- receiver: 'yunwei'
group_wait: 10s
match_re:
serverity: critical

receivers:
- name: 'yunwei' # 定义接收者名称
wechat_configs: # 企业微信配置
- corp_id: 'wwxxxxx' # 企业ID是唯一标识
send_resolved: true # 设置发送警报恢复信息
to_party: '1' # 部门id,比如我的默认组,显示的是1,如果你DB组,就可能会是2,WEB组就是3,依次类推,另外需要接收警报的相关人员必须在这个部门里。
agent_id: '1000002' # 新建应用的agent_id
api_secret: 'F-fzpgsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # 新建应用的Secret
- name: 'db'
email_configs:
- to: 'system51@126.com'

编写微信告警内容模板

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
38
39
40
41
42
43
44
[root@k8s-m1 alertmanager-0.22.2.linux-amd64]# mkdir wechat

[root@k8s-m1 alertmanager-0.22.2.linux-amd64]# vim wechat/wechat.tmpl
{{ define "wechat.default.message" }}
{{ if gt (len .Alerts.Firing) 0 -}}
Alerts Firing:
{{ range .Alerts }}
告警状态: {{ .Status }}

警报级别: {{ .Labels.serverity }}

警报类型: {{ .Labels.alertname }}

故障主机: {{ .Labels.instance }}

警报主题: {{ .Annotations.summary }}

警报详情: {{ .Annotations.description }}

⏱ : {{ (.StartsAt.Local).Format "2006-01-02 15:04:05" }}
{{- end }}
{{- end }}

{{ if gt (len .Alerts.Resolved) 0 -}}
Alerts Resolved:
{{ range .Alerts }}
告警状态: {{ .Status }}

警报级别: {{ .Labels.serverity }}

警报类型: {{ .Labels.alertname }}

故障主机: {{ .Labels.instance }}

警报主题: {{ .Annotations.summary }}

警报详情: {{ .Annotations.description }}

⏱ : {{ (.StartsAt.Local).Format "2006-01-02 15:04:05" }}
⏲ : {{ (.EndsAt.Local).Format "2006-01-02 15:04:05" }}
{{- end }}
{{- end }}
{{- end }}

Prometheus-Alerts-30

我们可以根据上图邮件告警中的类容能大概知道模板中需要写些什么
可以参考官方网站提供的参数设置更多内容:https://prometheus.io/docs/alerting/latest/notifications/

最终效果

Prometheus-Alerts-31


AlertManager实现监控告警
https://system51.github.io/2021/07/12/Alertmanager/
作者
Mr.Ye
发布于
2021年7月12日
许可协议