1. 告警功能概述
Prometheus 对指标的收集、存储同告警能力分别属于 Prometheus Server 和 AlertManager 两个独立的组件,前者仅负责基于“告警规则”生成告警通知,具体的告警操作则由后者完成
Alertmanager 负责处理由客户端发来的告警通知
-
客户端通常是 Prometheus Server,但它也支持接收来自其他工具的告警
-
Alertmanager 对告警通知进行分组、去重后,根据路由规则将其路由到不同的 receiver,如 Email、短信或PagerDuty等
2. Prometheus 监控系统的告警逻辑
首先要配置 Prometheus 成为 Alertmanager 的告警客户端,反过来,Alertmanager 也是应用程序,它自身同样应该纳入 Prometheus 的监控目标
配置逻辑
-
在 Alertmanager 上定义 receiver,他们通常是能够基于某个媒介接收告警信息的特定用户
-
Eamil、WeChat、Pagerduty、Slack 和 Webhook 等是为常见的发送告警信息的媒介
-
在不同的媒介上,代表告警信息接收人的地址表示方式也会有所不同
-
-
在 Alertmanager 上定义路由规则(route),以便将收到的告警通知按需分别进行处理
-
在 Prometheus 上定义告警规则生成告警通知,发送给 Alertmanager
3. Alertmanager
除了基本的告警通知能力外,Alertmanager 还支持对告警进行去重、分组、抑制、静默和路由等功能
-
分组(Grouping):将相似告警合并为单个告警通知的机制,在系统因大面积故障而触发警潮时,分组机制能避免用户被大量的告警噪声淹没,进而导致关键信息的隐没
-
抑制(Inbihition):系统中某个组件或服务故障而触发告警通知后,那些依赖于该组件或服务的其他组件或服务可能也会因此而触发告警,抑制便是避免类似的级联报警的一种特性,从而让用户能将精力集中于真正的故障所在
-
静默(Silent):是指在一个特定的时间窗口内,即便接收到告警通知,Alertmanager 也不会真正向用户发送报警信息的行为;通常,在系统例行维护期间,需要激活告警系统的静默特性
-
路由(route):用于配置 Alertmanager 如何处理传入的特定类型的告警通知,其基本逻辑是根据路由匹配规则的匹配结果来确定处理当前报警通知的路径和行为
4. 部署 Alertmanager
Altermanager 是一个独立的 Go 二进制程序,需要独立部署及维护
https://prometheus.io/download/
wget https://github.com/prometheus/alertmanager/releases/download/v0.23.0/alertmanager-0.23.0.linux-amd64.tar.gz
tar zxvf alertmanager-0.23.0.linux-amd64.tar.gz -C /usr/local
ln -s /usr/local/alertmanager-0.23.0.linux-amd64 /usr/local/alertmanager
# 编辑启动文件
vim /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=alertmanager System
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/alertmanager/alertmanager --config.file /usr/local/alertmanager/alertmanager.yml
Restart=on-failure
[Install]
WantedBy=multi-user.target
邮件报警
Alertmanager 的配置文件遵循 YAML 格式,通常给予一个类似如下的基础配置,即可启动相关的进程
[root@promethues alertmanager]# cat /usr/local/alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.qq.com:25' # 使用 qq 邮箱服务器发邮件
smtp_from: '111111@qq.com' # 发件人,填写你的 qq 邮箱
smtp_auth_username: '111111@qq.com' # 与上面保持一致
smtp_auth_password: 'cnhvcbyucdhcbihg111' # 你 qq 邮箱的授权码
smtp_require_tls: false # 不使用加密认证
#templates:
# - '/usr/local/alertmanager/templates/email.tmpl'
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h # 1 小时重复一次报警
receiver: 'email'
receivers:
- name: 'email'
email_configs:
- to: '111111@qq.com'
# html: '{{ template "email.to.html" . }}'
send_resolved: true # 故障恢复后发送邮件
inhibit_rules: # 告警抑制规则
- source_match:
serverity: 'critical'
target_match:
serverity: 'warning'
equal: ['alertname','dev','instance']
[root@promethues alertmanager]#
global 配置段用于定义全局配置、templates 配置段负责定义告警模板文件、route 配置段用于指定如何处理传入的告警
示例中仅定义了基本的路由信息(静默路由),而 receiver 配置段则定义了告警信息的接收器,每个接收器都应该有其具体的定义
提示:上面配置中用于处理和发送告警信息的媒介是运行于本地节点上的 SMTP 服务,因而需要安装配置 postfix 一类的程序已完成测试
检查语法
[root@promethues ~]# /usr/local/alertmanager/amtool check-config /usr/local/alertmanager/alertmanager.yml
Checking '/usr/local/alertmanager/alertmanager.yml' SUCCESS
Found:
- global config
- route
- 1 inhibit rules
- 1 receivers
- 0 templates
[root@promethues ~]#
启动 Alertmanager
# 内建的 HTTP 服务默认监听于 TCP 协议的 9093 端口,且 /metric 路径暴露了其内建的指标
systemctl enable --now alertmanager
systemctl status alertmanager
[root@promethues ~]# ss -anltp|grep alertmanager
LISTEN 0 128 [::]:9093 [::]:* users:(("alertmanager",pid=3772,fd=8))
LISTEN 0 128 [::]:9094 [::]:* users:(("alertmanager",pid=3772,fd=3))
[root@promethues ~]#
5. 结合 Prometheus 与 Alertmanager
调用的 Alertmanager 实例的配置信息定义在顶级的 Alertmanager 配置段中,它同样支持静态配置和动态发现机制,其配置方式类似于被监控的 target 的方式
静态配置示例
[root@promethues ~]# mkdir /usr/local/prometheus/rules -p
[root@promethues ~]# cat /usr/local/prometheus/prometheus.yml
# 1. 修改 prometheus.yml 的 alerting 部分
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
- 192.168.31.157:9093 # AlterManager 地址
# 2. 定义告警文件
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
- "rules/*.yml"
动态配置示例
alerting:
alertmanagers:
- file_sd_configs:
- files:
- "targers/altermanager*.yaml"
基于文件发现时,其用到的配置示例
- targets:
- alert.test.com:9093
labels:
app: alertmanager
job: alertmanager
还可以将 Alertmanager 程序作为监控目标,例如将如下配置添加到 scrape_configs 中
- job_name: 'alertmanager'
file_sd_configs:
- files:
- target/prometheus/alertmanager*.yaml
6. 配置 Prometheus 加载告警规则文件
类似于记录规则,告警规则(Alerting rule)也定义在独立的文件中,而后由 Prometheus 在 rule_files 配置段中加载
尽管可以将所有的告警规则定义在同一文件中,但出于便捷管理的目的,建议将其按功能分别放置于不同的文件中
rule_files 配置段加载告警规则的文件,同样可以使用文件名通配机制
示例:我们假设所有的规则文件放置于专用的 alert_rules 目录下,均以 “.yaml” 为文件名后缀,于是一条文件记载配置项即可加载相应目录下所有的告警规则文件
rule_files:
- "rules/*.yml"
- "alert_rules/*.yml" # 专用于加载告警规则相关的文件
7. 添加报警规则
根据配置,在 alert_rules 目录中所有以 “.yaml” 为后缀的文件均识别为告警规则文件,下面便是一条告警规则示例
若某个 Instance 的 up 指标的值转为 0 持续超过 1 分钟后,将触发告警
[root@promethues ~]# cat /usr/local/prometheus/rules/host_monitor.yml
groups:
- name: node-up
rules:
- alert: node-up
expr: up == 0
for: 15s # 评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在等待期间新产生告警的状态为 pending
labels: # 自定义标签,允许用户指定要附加到告警上的一组附加标签
severity: 1
team: node
annotations:
summary: "{{$labels.instance}} Instance has been down for more than 15 seconds"
[root@promethues ~]#
告警规则
类似于记录规则,有着类似或相关联功能的告警规则同样可以组织为 group,从而为规则名称提供名称空间,一个组内的每个告警规则必须有个名称,且在该组内其名称必须唯一
-
alert:告警规则的名称
-
expr:基于 PromQL 表达式的告警触发条件(布尔表达式),用于计算是否有时间序列可以满足该条件,可以使用由 Recording rule定义为指标
-
for:控制在触发报警之前,测试表达式的值必须为 true 的时长
-
表达式值为 true,但其持续时间未能满足 for 定义的时长时,相关的告警状态为 pending
-
满足该时长之后,相关的告警将被触发,并转为 firing 状态
-
表达式的值为 false时,告警状态将处于 inactive 状态
-
-
labels:告警规则被激活时,相关时间序列上的所有标签都会添加到生成告警实例之上,而 labels 则允许用户在告警上附加其他自定义标签;该标签值支持模板化
- 告警的名称及其标签即为告警地标识,因而,这类似于时间序列的标识机制
-
annotations:附加在告警之上的注解信息,其格式类似于标签,但不能被用于标识告警实例,经常用于存储告警摘要,且其值支持模板化
- 用于指定一组附加信息,比如用于描述告警详细信息的文字等,annotations 的内容在告警产生时会一同作为参数发送到 Alertmanager
-
summary 描述告警的概要信息,description 用于描述告警的详细信息
-
同时 Alertmanager 的 UI 也会根据这两个标签值,显示告警信息
验证配置文件
[root@promethues ~]# /usr/local/prometheus/promtool check config /usr/local/prometheus/prometheus.yml
Checking /usr/local/prometheus/prometheus.yml
SUCCESS: 1 rule files found
Checking /usr/local/prometheus/rules/host_monitor.yml
SUCCESS: 1 rules found
[root@promethues ~]# /usr/local/alertmanager/amtool check-config /usr/local/alertmanager/alertmanager.yml
Checking '/usr/local/alertmanager/alertmanager.yml' SUCCESS
Found:
- global config
- route
- 1 inhibit rules
- 1 receivers
- 0 templates
[root@promethues ~]#
重启 Prometheus
[root@promethues ~]# systemctl restart prometheus
[root@promethues ~]# systemctl status prometheus
8. 触发告警
Prometheus 以一个固定的周期来评估所有告警规则,其值由 evaluate_interval 参数定义,默认为 15s,在每个评估周期内,Prometheus 会计算每条告警规则中的布尔表达式并更新告警状态
未使用 for 字句的告警,会自动从 Inactive 状态转为 Firing ,它只需要一个评估周期便能触发,而带有 for 字句的告警状态将先转为 Pending ,而后才到 Firing,因而至少需要两个评估周期才能触发
-
处于 Pending 状态的告警,在其持续时长满足 for 字句的定义之前,若布尔表达式的值转回了 false,则告警状态将转回 Inactive
-
由此可见,经由 Pending 再到 Firing的转换,可以确保告警更有效,且不会来回浮动
Prometheus 将为 Pending 和 Firing 状态中的每个告警创建指标,该指标名称为 ALERT,其值给定为 1,并且在告警处于 Pending 和 Firing 状态期间存在,在此之后,它将不接收任何更新,直到过期
Pending 状态的告警
-
已发出的告警,告警状态被 Alertmanager接收到
-
告警被触发后,便可在 Alertmanager 的 Web UI 上看到相关的信息,而且也将被告警信息也将被发送到目标 email
模拟故障
[root@promethues ~]# systemctl stop node_exporter
[root@promethues ~]# ss -antlp|grep 9100
状态说明 Prometheus Alert 告警状态有三种状态:Inactive、Pending、Firing
-
Inactive:非活动状态,表示正在监控,但是还未有任何警报触发。
-
Pending:表示这个警报必须被触发。由于警报可以被分组、压抑/抑制或静默/静音,所以等待验证,一旦所有的验证都通过,则将转到 Firing 状态。
-
Firing:将警报发送到 AlertManager,它将按照配置将警报的发送给所有接收者。一旦警报解除,则将状态转到 Inactive,如此循环。
报警邮件
恢复服务
[root@promethues ~]# systemctl start node_exporter
[root@promethues ~]# ss -antlp|grep 9100
LISTEN 0 128 [::]:9100 [::]:* users:(("node_exporter",pid=3919,fd=3))
[root@promethues ~]#
恢复邮件
9. 告警模板
Prometheus 支持在告警中使用模板
-
告警模板是指在告警中的标签和注解上引用时间序列的标签和样本值的方法
-
它使用标准的 Go 语法,并暴露一些包含时间标签和值的变量
-
标签引用:{{ $label.<label_name> }}
-
指标样本值引用:{{ $value }}
-
-
若要在 description 注解中引用触发告警的时间序列上的 instance 和 job 标签的值,可分别使用 {{ $label.instance }} 和 {{ $label.job }}
优化告警模板
1.新建模板文件
[root@promethues rules]# cat /usr/local/alertmanager/email.tmpl
{{ define "email.to.html" }}
{{ range .Alerts }}
=========start==========<br>
告警程序: prometheus_alert <br>
告警级别: {{ .Labels.severity }} 级 <br>
告警类型: {{ .Labels.alertname }} <br>
故障主机: {{ .Labels.instance }} <br>
告警主题: {{ .Annotations.summary }} <br>
告警详情: {{ .Annotations.description }} <br>
触发时间: {{ .StartsAt }} <br>
=========end==========<br>
{{ end }}
{{ end }}
[root@promethues rules]#
2.修改配置文件使用模板
[root@promethues ~]# cat /usr/local/alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.qq.com:25' # 使用 qq 邮箱服务器发邮件
smtp_from: '111111@qq.com' # 发件人,填写你的 qq 邮箱
smtp_auth_username: '111111@qq.com' # 与上面保持一致
smtp_auth_password: 'cnhvcbyucdhcbihg111' # 你 qq 邮箱的授权码
smtp_require_tls: false # 不使用加密认证
templates:
- '/usr/local/alertmanager/email.tmpl'
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h # 1 小时重复一次报警
receiver: 'email' # 注意和下面的 receivers.name 同名
receivers:
- name: 'email'
email_configs:
- to: '111111@qq.com'
html: '{{ template "email.to.html" . }}' # 使用模板的方式发送
send_resolved: true # 故障恢复后发送邮件
inhibit_rules: # 告警抑制规则
- source_match:
serverity: 'critical'
target_match:
serverity: 'warning'
equal: ['alertname','dev','instance']
[root@promethues ~]#
报警测试
[root@promethues ~]# /usr/local/alertmanager/amtool check-config /usr/local/alertmanager/alertmanager.yml
Checking '/usr/local/alertmanager/alertmanager.yml' SUCCESS
Found:
- global config
- route
- 1 inhibit rules
- 1 receivers
- 1 templates
SUCCESS
[root@promethues ~]# systemctl restart alertmanager
模拟宕机报警
[root@promethues ~]# systemctl stop node_exporter
[root@promethues ~]# ss -antlp|grep 9100
恢复报警
[root@promethues rules]# systemctl start node_exporter
[root@promethues rules]# ss -antlp|grep 9100
LISTEN 0 128 [::]:9100 [::]:* users:(("node_exporter",pid=4930,fd=3))
[root@promethues rules]#
告警恢复
在配置的时候,加上:send_resolved: true
1.修改模板添加恢复信息
[root@promethues ~]# cat /usr/local/alertmanager/email.tmpl
{{ define "email.to.html" }}
{{ if gt (len .Alerts.Firing) 0 }}{{ range .Alerts }}
@告警
告警程序: prometheus_alert <br>
告警级别: {{ .Labels.severity }} 级 <br>
告警类型: {{ .Labels.alertname }} <br>
故障主机: {{ .Labels.instance }} <br>
告警主题: {{ .Annotations.summary }} <br>
告警详情: {{ .Annotations.description }} <br>
触发时间: {{ .StartsAt }} <br>
{{ end }}
{{ end }}
{{ if gt (len .Alerts.Resolved) 0 }}{{ range .Alerts }}
@恢复:
告警主机:{{ .Labels.instance }} <br>
告警主题:{{ .Annotations.summary }} <br>
恢复时间: {{ .EndsAt }} <br>
{{ end }}
{{ end }}
{{ end }}
[root@promethues ~]#
报警邮件
恢复邮件