Prometheus + Alertmanager 进行邮件告警
Prometheus告警简介
告警能力在Prometheus的架构中被划分成两个独立的部分。如下所示,通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。
在Prometheus中一条告警规则主要由以下几部分组成:
- 告警名称:用户需要为告警规则命名,当然对于命名而言,需要能够直接表达出该告警的主要内容
- 告警规则:告警规则实际上主要由PromQL进行定义,其实际意义是当表达式(PromQL)查询结果持续多长时间(During)后出发告警
在Prometheus中,还可以通过Group(告警组)对一组相关的告警进行统一定义。当然这些定义都是通过YAML文件来统一管理的。
Alertmanager作为一个独立的组件,负责接收并处理来自Prometheus Server(也可以是其它的客户端程序)的告警信息。Alertmanager可以对这些告警信息进行进一步的处理,比如当接收到大量重复告警时能够消除重复的告警信息,同时对告警信息进行分组并且路由到正确的通知方,Prometheus内置了对邮件,Slack等多种通知方式的支持,同时还支持与Webhook的集成,以支持更多定制化的场景。例如,目前Alertmanager还不支持钉钉,那用户完全可以通过Webhook与钉钉机器人进行集成,从而通过钉钉接收告警信息。同时AlertManager还提供了静默和告警抑制机制来对告警通知行为进行优化。
Alertmanager特性
Alertmanager除了提供基本的告警通知能力以外,还主要提供了如:分组、抑制以及静默等告警特性:
分组
分组机制可以将详细的告警信息合并成一个通知。在某些情况下,比如由于系统宕机导致大量的告警被同时触发,在这种情况下分组机制可以将这些被触发的告警合并为一个告警通知,避免一次性接受大量的告警通知,而无法对问题进行快速定位。
例如,当集群中有数百个正在运行的服务实例,并且为每一个实例设置了告警规则。假如此时发生了网络故障,可能导致大量的服务实例无法连接到数据库,结果就会有数百个告警被发送到Alertmanager。
而作为用户,可能只希望能够在一个通知中中就能查看哪些服务实例收到影响。这时可以按照服务所在集群或者告警名称对告警进行分组,而将这些告警内聚在一起成为一个通知。
告警分组,告警时间,以及告警的接受方式可以通过Alertmanager的配置文件进行配置。
抑制
抑制是指当某一告警发出后,可以停止重复发送由此告警引发的其它告警的机制。
例如,当集群不可访问时触发了一次告警,通过配置Alertmanager可以忽略与该集群有关的其它所有告警。这样可以避免接收到大量与实际问题无关的告警通知。
抑制机制同样通过Alertmanager的配置文件进行设置。
静默
静默提供了一个简单的机制可以快速根据标签对告警进行静默处理。如果接收到的告警符合静默的配置,Alertmanager则不会发送告警通知。
静默设置需要在Alertmanager的Werb页面上进行设置。
部署Alertmanager
Alertmanager和Prometheus Server一样均采用Golang实现,并且没有第三方依赖。一般来说我们可以通过以下几种方式来部署Alertmanager:二进制包、容器以及源码方式安装。
使用二进制包部署AlertManager
获取并安装软件包
Alertmanager最新版本的下载地址可以从Prometheus官方网站https://prometheus.io/download/获取。
这边使用的不是最新版,使用的版本为alertmanager-0.20.0.linux-amd64.tar.gz
[root@server ~]# wget https://github.com/prometheus/alertmanager/releases/download/v0.20.0/alertmanager-0.20.0.linux-amd64.tar.gz [root@server ~]# tar xvf alertmanager-0.20.0.linux-amd64.tar.gz -C /usr/local/ [root@server ~]# cd /usr/local/ [root@server local]# mv alertmanager-0.20.0.linux-amd64 alertmanager
创建alertmanager配置文件
Alertmanager解压后会包含一个默认的alertmanager.yml配置文件,内容如下所示:
[root@server local]# cd alertmanager/ [root@server alertmanager]# cp alertmanager.yml alertmanager.yml.bak [root@server alertmanager]# cat alertmanager.yml global: resolve_timeout: 5m route: group_by: ['alertname'] group_wait: 10s group_interval: 10s repeat_interval: 1h receiver: 'web.hook' receivers: - name: 'web.hook' webhook_configs: - url: 'http://127.0.0.1:5001/' inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['alertname', 'dev', 'instance']
Alertmanager的配置主要包含两个部分:路由(route)以及接收器(receivers)。所有的告警信息都会从配置中的顶级路由(route)进入路由树,根据路由规则将告警信息发送给相应的接收器。
在Alertmanager中可以定义一组接收器,比如可以按照角色(比如系统运维,数据库管理员)来划分多个接收器。接收器可以关联邮件,Slack以及其它方式接收告警信息。
当前配置文件中定义了一个默认的接收者default-receiver由于这里没有设置接收方式,目前只相当于一个占位符。
在配置文件中使用route定义了顶级的路由,路由是一个基于标签匹配规则的树状结构。所有的告警信息从顶级路由开始,根据标签匹配规则进入到不同的子路由,并且根据子路由设置的接收器发送告警。目前配置文件中只设置了一个顶级路由route并且定义的接收器为default-receiver。因此,所有的告警都会发送给default-receiver。
启动Alertmanager
Alermanager会将数据保存到本地中。
[root@server alertmanager]#./amtool check-config alertmanager.yml #检查配置是否生效 [root@server alertmanager]#./alertmanager --config.file=alertmanager.yml #启动Alertmanager
用户也在启动Alertmanager时使用参数修改相关配置。
用于指定alertmanager配置文件路径,
用于指定数据存储路径。
查看运行状态
Alertmanager启动后可以通过9093端口访问,IP:9063
Alert菜单下可以查看Alertmanager接收到的告警内容。Silences菜单下则可以通过UI创建静默规则。进入Status菜单,可以看到当前系统的运行状态以及配置信息。
Status页面
关联Prometheus与Alertmanager
在Prometheus的架构中被划分成两个独立的部分。Prometheus负责产生告警,而Alertmanager负责告警产生后的后续处理。因此Alertmanager部署完成后,需要在Prometheus中设置Alertmanager相关的信息。
编辑Prometheus配置文件prometheus.yml,并添加以下内容
[root@server prometheus]# vim prometheus.yml # Alertmanager configuration alerting: alertmanagers: - static_configs: - targets: ['192.168.12.128:9093'] # - alertmanager:9093
编辑完成后检测更改后的配置文件是否有效:
[root@server prometheus]# ./promtool check config prometheus.yml Checking prometheus.yml SUCCESS: 0 rule files found
重启Prometheus服务,使配置文件生效
[root@server prometheus]# systemctl restart prometheus.service
重启Prometheus服务,成功后,可以从 IP:9090/config查看alerting配置是否生效。
此时,再次尝试手动拉高系统CPU使用率,即可看到Prometheus告警触发状态:
cat /dev/zero>/dev/null
Alertmanager配置概述
在上面的部分中已经简单介绍过,在Alertmanager中通过路由(Route)来定义告警的处理方式。路由是一个基于标签匹配的树状匹配结构。根据接收到告警的标签匹配相应的处理方式。
Alertmanager主要负责对Prometheus产生的告警进行统一处理,因此在Alertmanager配置中一般会包含以下几个主要部分:
- 全局配置(global):用于定义一些全局的公共参数,如全局的SMTP配置,Slack配置等内容;
- 模板(templates):用于定义告警通知时的模板,如HTML模板,邮件模板等;
- 告警路由(route):根据标签匹配,确定当前告警应该如何处理;
- 接收人(receivers):接收人是一个抽象的概念,它可以是一个邮箱也可以是微信,Slack或者Webhook等,接收人一般配合告警路由使用;
- 抑制规则(inhibit_rules):合理设置抑制规则可以减少垃圾告警的产生
其完整配置格式如下:
global: [ resolve_timeout: <duration> | default = 5m ] [ smtp_from: <tmpl_string> ] [ smtp_smarthost: <string> ] [ smtp_hello: <string> | default = "localhost" ] [ smtp_auth_username: <string> ] [ smtp_auth_password: <secret> ] [ smtp_auth_identity: <string> ] [ smtp_auth_secret: <secret> ] [ smtp_require_tls: <bool> | default = true ] [ slack_api_url: <secret> ] [ victorops_api_key: <secret> ] [ victorops_api_url: <string> | default = "https://alert.victorops.com/integrations/generic/20131114/alert/" ] [ pagerduty_url: <string> | default = "https://events.pagerduty.com/v2/enqueue" ] [ opsgenie_api_key: <secret> ] [ opsgenie_api_url: <string> | default = "https://api.opsgenie.com/" ] [ hipchat_api_url: <string> | default = "https://api.hipchat.com/" ] [ hipchat_auth_token: <secret> ] [ wechat_api_url: <string> | default = "https://qyapi.weixin.qq.com/cgi-bin/" ] [ wechat_api_secret: <secret> ] [ wechat_api_corp_id: <string> ] [ http_config: <http_config> ] templates: [ - <filepath> ... ] route: <route> receivers: - <receiver> ... inhibit_rules: [ - <inhibit_rule> ... ]
在全局配置中需要注意的是
,该参数定义了当Alertmanager持续多长时间未接收到告警后标记告警状态为resolved(已解决状态)。该参数的定义可能会影响到告警恢复通知的接收时间,可根据自己的实际场景进行定义,其默认值为5分钟。
与SMTP邮件集成
邮箱应该是目前企业最常用的告警通知方式,Alertmanager内置了对SMTP协议的支持,因此对于企业用户而言,只需要一些基本的配置即可实现通过邮件的通知。
在Alertmanager使用邮箱通知,用户只需要定义好SMTP相关的配置,并且在receiver中定义接收方的邮件地址即可。在Alertmanager中我们可以直接在配置文件的global中定义全局的SMTP配置:
global: [ smtp_from: <tmpl_string> ] [ smtp_smarthost: <string> ] [ smtp_hello: <string> | default = "localhost" ] [ smtp_auth_username: <string> ] [ smtp_auth_password: <secret> ] [ smtp_auth_identity: <string> ] [ smtp_auth_secret: <secret> ] [ smtp_require_tls: <bool> | default = true ]
完成全局SMTP之后,我们只需要为receiver配置email_configs用于定义一组接收告警的邮箱地址即可,如下所示:
name: <string> email_configs: [ - <email_config>, ... ]
每个email_config中定义相应的接收人邮箱地址,邮件通知模板等信息即可,当然如果当前接收人需要单独的SMTP配置,那直接在email_config中覆盖即可:
[ send_resolved: <boolean> | default = false ] to: <tmpl_string> [ html: <tmpl_string> | default = '{{ template "email.default.html" . }}' ] [ headers: { <string>: <tmpl_string>, ... } ]
如果当前收件人需要接受告警恢复的通知的话,在email_config中定义
为true即可。
如果所有的邮件配置使用了相同的SMTP配置,则可以直接定义全局的SMTP配置。
官方配置以Gmail邮箱为例,定义了一个全局的SMTP配置,并且通过route将所有告警信息发送到default-receiver中:
global: smtp_smarthost: smtp.gmail.com:587 smtp_from: <smtp mail from> smtp_auth_username: <usernae> smtp_auth_identity: <username> smtp_auth_password: <password> route: group_by: ['alertname'] receiver: 'default-receiver' receivers: - name: default-receiver email_configs: - to: <mail to address> send_resolved: true
我这里以163邮箱为例,定义了一个全局的SMTP配置,并且通过route将所有告警信息发送到163.email中:
smtp_auth_password填写的是第三方登录邮箱的授权码,非邮箱账户登录密码。
163邮箱授权码的获取:
因为我之前已经添加过一次,所以这里会显示两条授权码。
常见的Smtp/POP3邮箱地址和端口邮箱端口:
163.com:
接收邮件服务器: http://pop.163.com
接收端口: 110或995(使用ssl时)
接收邮件服务器: http://imap.163.com
接收端口: 143或993(使用ssl时)
发送邮件服务器: http://smtp.163.com
发送端口: 25或465/994(使用ssl时)
126邮箱:
接收邮件服务器: http://pop.126.com
接收端口: 110
发送邮件服务器: http://smtp.126.com
发送端口: 25
139邮箱:
POP3服务器地址:http://POP.139.com(端口:110)
SMTP服务器地址:http://SMTP.139.com(端口:25)
QQ邮箱:
接收邮件服务器: http://pop.qq.com
接收端口: 110或995(使用ssl时)
接收邮件服务器: http://imap.qq.com
接收端口: 143或993(使用ssl时)
发送邮件服务器: http://smtp.qq.com
发送端口: 25或465/587(使用ssl时)
QQ企业邮箱 :
POP3服务器地址:http://pop.exmail.qq.com (SSL启用 端口:995)
SMTP服务器地址:http://smtp.exmail.qq.com【端口:25或465/587(使用ssl时)】
gmail(http://google.com) :
POP3服务器地址:http://pop.gmail.com(SSL启用 端口:995)
SMTP服务器地址:http://smtp.gmail.com(SSL启用 端口:587)
雅虎邮箱:
接收邮件服务器: http://pop.mail.yahoo.cn
接收端口: 110或995(使用ssl时)
接收邮件服务器: http://imap.mail.yahoo.cn
接收端口: 143或993(使用ssl时)
发送邮件服务器: http://smtp.mail.yahoo.cn
发送端口: 25或465(使用ssl时)
我这里是参考网上后自定义的163邮箱配置:
# 全局配置,包括报警解决后的超时时间、SMTP 相关配置、各种渠道通知的 API 地址等等。 global: # 告警超时时间 resolve_timeout: 5m # 发送者邮箱地址 smtp_from: 'yin1205@163.com' # 邮箱smtp服务器地址及端口 smtp_smarthost: 'smtp.163.com:25' # 发送者邮箱账号 smtp_auth_username: 'yin1205@163.com' # 发送者邮箱密码,这里填入第一步中获取的授权码 smtp_auth_password: 'LZVTWMQXXGFWRCIU' # 是否使用tls smtp_require_tls: false smtp_hello: '163.com' # 路由配置,设置报警的分发策略,它是一个树状结构,按照深度优先从左向右的顺序进行匹配。 route: # 用于将传入警报分组在一起的标签。 # 基于告警中包含的标签,如果满足group_by中定义标签名称,那么这些告警将会合并为一个通知发送给接收器。 group_by: ['alertname'] # 发送通知的初始等待时间 group_wait: 30s # 在发送有关新警报的通知之前需要等待多长时间 group_interval: 5m # 如果已发送通知,则在再次发送通知之前要等待多长时间,通常约3小时或更长时间 repeat_interval: 30s # 接受者名称 receiver: '163.email' # 配置告警消息接受者信息,例如常用的 email、wechat、slack、webhook 等消息通知方式 receivers: - name: '163.email' email_configs: # 配置接受邮箱地址 - to : 'yin1205@163.com'
这时如果手动停止前面文章部署的 Node Exporter,MySQLD Exporter,使得监控样本数据满足告警触发条件。
[root@client_01 ~]# systemctl stop node_exporter.service [root@client_02 ~]# systemctl stop mysqld-exporter
在SMTP配置正确的情况下,可以接收到如下的告警内容:
因为上文在SMTP配置里面定义过邮件发送时间,所以在服务没有重启的话,会一直报警发送邮件。