1 AleartManager介绍
1.1 什么是 AleartManager
由于Prometheus本身⽆法实现告警,因此需要借助AlertManager来实现告警的推送。
Prometheus Server 会对已经设定好的“告警规则”进⾏定期评估,当检测到问题时,会⽣成相应的告警通知并发送给 AlertManager。AlertManager 则会根据告警消息所携带的“标签”和事先配置的“路由规则(Routes)”,将告警消息分发⾄不同的接收器/接收⼈(receivers)。例如,带有"system"标签的告警会通过Email发送给运维团队,⽽带有"database"标签的告警则通过WeChat发给数据库团队。
prometheus--->评估规则--->持续满⾜触发条件--->触发告警--->alertmanager--->根据路由规则匹配标签-->通过不同的媒介--->发送不同的接收⼈(邮件|钉钉|微信)。
1.2 AleartManager特性
除了基本的告警通知能⼒外,Altermanager还⽀持对告警进⾏去重、分组、抑制、 静默和路由等功能;
1、去重:prometheus⼀条报警发送给多个AlertManager,AlertManager会对其进⾏去重并发送。
2、分组(Group):将相似告警合并为单个告警发送,在系统因⼤⾯积故障⽽触发告警潮时,分组机制能避免⽤户被⼤量的告警淹没,进⽽导致关键信息的隐没;
例如:我们可能会使⽤⽽Alertmanager 的分组功能它允许你定义合并的规则,例如将 alertname 相同的告警合并在⼀起,发送单⼀的通知。这意味着,如果多台主机同时出现不存活的情况,Alertmanager 会将消息合并为⼀个通知发送出去,其中包含受影响的所有主机的信息,⽽不是通知每个主机的故障。
3、路由(route):它负责决定告警的分发逻辑。它通过检查告警的属性,使⽤“预定义的匹配规则”来判断告警的类别,然后根据这些规则把告警发送到合适的接收器
例如:我们使⽤Prometheus监控了很多服务,包括数据库、web、⽀付系统等。⽽不同类型的服务故障需要通知到不同的团队,这样问题才能得到快速的解决。像数据库问题需要通知DBA团队,⽽应⽤层⾯的问题需要通知给运维团队。在Alertmanager中,可以为不同类型的告警,设置不同的接收器(receivers),Alertmanager 路由规则会将告警发送到对应的接收器,确保消息能正确的通知到不同的团队。
4、静默(Silence):是指在⼀个特定的时间窗⼝内,即便接收到告警通知,Alertmanager也不会真正向⽤户发送告警信息
例如:在系统维护或升级过程中,通常会触发⼤量的告警。这些告警往往是维护系统的过程中引起的,⽽⾮真正出现了故障。如果我们不对告警通知进⾏调整,将会收到⼤量的告警信息,造成不必要的⼲扰。为了应对这种情况,在维护期间,我们可以在Alertmanager 中设置静默(silence)规则。这些规则能够禁⽌对外发送告警通知。等到维护⼯作完成后,我们再取消静默规则,恢复正常的告警通知流程。这样可以保证告警系统的有效性,同时避免了在维护期间产⽣⼤量不必要的告警信息。
5、抑制(Inhibition):是⼀种告警管理机制,⽤以减少因组件故障导致的连锁告警。当⼀个核⼼组件发⽣故障时,依赖它的其他组件或服务也可能产⽣告警。启⽤抑制功能后,系统将⾃动抑制这些级联的次要告警,从⽽让⽤户将精⼒集中于真正的故障所在。
例如:当⼀台主机宕机,主机之上的所有应⽤也会随之宕机,每个应⽤异常都会单独发送告警,从⽽导致告警数量激增。为避免告警泛滥,我们可以通过告警抑制功能来设置告警规则:在主机宕机的情况下,抑制所有由主机引起的其他应⽤的告警。 仅关注主机本身的告警信息。这样我们就能更快的定位到根本的问题并解决该问题。
6、⾼可⽤(High Availability):AlertManager可以使⽤gossip留⾔协议实现⾼可⽤性;
1.3 AlertManager配置说明
Alertmanager 负责对 Prometheus ⽣成的告警进⾏统⼀处理。常⻅的配置分为以下⼏个主要部分:
1、全局配置 (global): 定义了全局通⽤的参数。例如:( SMTP配置(⽤于邮件通知)、Slack配置(⽤于Slack通知)、以及其他第三⽅服务的配置)
2、模板 (templates): 定义告警通知时使⽤的模板。例如:(HTML模板、邮件模板)
3、告警路由 (route): 根据告警的标签进⾏匹配,确定分组逻辑,以及告警通知给谁。
4、接收⼈ (receivers): 接收⼈可以是邮箱、微信、Slack、Webhook
等。配合告警路由使⽤,确保告警通知到达正确的⽬的地。
5、抑制规则 (inhibit_rules): 通过设置抑制规则来减少不必要的告警,避免告警泛滥。
global:
# 已经触发了告警的消息,在多长时间内没有收到该告警的消息,则会自动将该告警标记为已解决。默认值是 5 分钟。
[ 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 ]
# 其他全局配置...
[ wechat_api_url: <string> | default = "https://qyapi.weixin.qq.com/cgi-bin/" ]
[ wechat_api_secret: <secret> ]
[ wechat_api_corp_id: <string> ]
# 模板配置
templates:
# 路径到告警模板文件
[ - <filepath> ... ]
# 告警路由
route:
# 告警的子路由配置
<route>
# 定义接收告警的接收人或服务
receivers:
- <receiver> ...
inhibit_rules:
# 抑制规则,用于减少告警噪声
[ - <inhibit_rule> ... ]
2 AleartManager部署
2.1 AleartManager安装
1、访问AlertManager的github,获取AlertManager的下载地址
https://github.com/prometheus/alertmanager/releases
# 加速地址
wget https://mirror.ghproxy.com/https://github.com/prometheus/alertmanager/releases/download/v0.26.0/alertmanager-0.26.0.linux-amd64.tar.gz
2、解压AlertManager
tar -xf alertmanager-0.26.0.linux-amd64.tar.gz -C /app/module/
ln -s /app/module/alertmanager-0.26.0.linux-amd64/ /app/module/alertmanager
3、查看AlertManager⽬录结构
alertmanager # ⼆进制命令
alertmanager.yml # 配置⽂件
2.2 AleartManager配置
1、定义Alertmanager的配置⽂件,设定发件⼈的邮箱,以及路由匹配规则,和接收⼈ (group_wait与group_interval区别)
cp alertmanager.yml alertmanager.yml.bk
vim alertmanager.yml
global:
resolve_timeout: 2h # 已经触发了告警的消息,在多长时间内没有收到该告警的消息,则会自动将该告警标记为已解决。
smtp_smarthost: 'smtp.139.com:25'
smtp_from: '123456789@139.com' # 发件人邮件
smtp_auth_username: '123456789@139.com' # 发件人用户名
smtp_auth_password: 'XXXXXXXXXXXX' # 发件人密码[授权码]
smtp_hello: '139.com'
smtp_require_tls: false
# 所有报警信息进入后的根路由,⽤来设置报警的分发策略
route:
group_by: ['alertname'] # 告警信息会根据告警名称分组,同名的告警消息会被归到一组,然后一起发送。 (一个学校的一起搭车回家)
group_wait: 30s # 当一组新告警产生时,系统会等待30秒,以便把这段时间内相同组的其他告警一起合并发送。(发车时间,保不齐在等待的30s内会有新的同校学生上车)
group_interval: 1m # 已经发送了一个分组的告警通知之后,即使又有新的相同分组的告警到来,也需要等待至少1分钟后才会发送该分组的告警通知。(类似于发车间隔,>没赶上就得等)
repeat_interval: 5m # 如果同一个组中的报警信息已经发送成功了,下一次这个组发送告警的时间间隔(重复发送相同告警,的时间间隔)
receiver: default # 默认的receiver:如果一个报警没有被一个route匹配,则发送给默认的接收器
receivers:
- name: 'default'
email_configs:
- to: '123456789@qq.com'
send_resolved: true # 接受告警恢复的通知
2、检查AlertManager的配置⽂件是否正确
/app/module/alertmanager/amtool check-config alertmanager.yml
2.3 AlertManager启动
1、配置system管理alertmanager启动和停⽌
vim /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=alertmanager
Documentation=https://prometheus.io/
After=network.target
[Service]
ExecStart=/app/module/alertmanager/alertmanager \
--web.listen-address=:9093 \
--config.file=/app/module/alertmanager/alertmanager.yml \
--storage.path=/app/module/alertmanager/data \
--data.retention=120h
ExecReload=/bin/kill -HUP
TimeoutStopSec=20s
Restart=always
[Install]
WantedBy=multi-user.target
2、启动alertmanager
systemctl daemon-reload
systemctl start alertmanager.service
3、检查alertmanager监听的9093、9094端⼝
4、访问alertmanager,通过 http://IP:9093 访问
2.4 AlertManager测试
1、使⽤具有相同alertname 名称,但不同内容的告警,以验证AlertManager 是否会将它们合并成⼀个组。
# 编写告警脚本
vim sendAlert.sh
#!/bin/bash
alterHost=$1
lable=$2
######################################################
alertname=$(echo $lable|awk -F '[=,]' '{print $2}')
severity=$(echo $lable|awk -F '[=,]' '{print $4}')
instance=$(echo $lable|awk -F '[=,]' '{print $6}')
job=$(echo $lable|awk -F '[=,]' '{print $8}')
########################################################
#######################################################
body=$(printf '[ {"labels": {"alertname": "%s", "severity": "%s", "instance": "%s", "job": "%s"}} ]' "$alertname" "$severity" "$instance" "$job")
########################################################
curl -X POST -H 'Content-Type: application/json' -d "$body" http://${alterHost}:9093/api/v1/alerts
chmod a+x sendAlert.sh
发送测试数据
# 节点故障(指定alertmanager服务器所在的地址)
./sendAlert.sh "192.168.137.131" "alertname=节点故障,instance=192.168.137.129,severity=critical,job=node_exporter"
./sendAlert.sh "192.168.137.131" "alertname=节点故障,instance=192.168.137.130,severity=critical,job=node_exporter"
# cpu故障
./sendAlert.sh "192.168.137.131" "alertname=cpu故障,instance=192.168.137.129,severity=critical,job=node_exporter"
./sendAlert.sh "192.168.137.131" "alertname=cpu故障,instance=192.168.137.130,severity=critical,job=node_exporter"
2、验证结果,会发现AlertManager是根据,这样能够有效避免了消息重复通知。
3、登录邮件查看告警信息,理想的结果是收到两封电⼦邮件通知,每封包含两条关联告警,⽽⾮四封单独的邮件。
3.Prometheus对接AleartManager
3.1 配置Prom对接AleartManager
1、编辑prometheus.yml⽂件,然后将告警接⼊⾄AlertManager组件;
alerting:
alertmanagers:
- static_configs:
- targets:
- "192.168.137.131:9093"
2、由于AlertManager也对外提供了Metrics接⼝,我们可以直接将AlertManager纳⼊监控中来;
3、重新加载Prometheus服务
curl -X POST http://192.168.137.131:9090/-/reload
3.2 配置Prometheus告警规则
1、在Prometheus服务器上编辑⼀个测试的告警规则
2、在Prometheus的告警规则⽂件中,可以将相关的规则放在⼀起,形成⼀个规则组group。每个组内可以包含多个告警规则rule。每个告警规则主要包含以下⼏个关键部分:
- alert:告警规则的名称(后期可以基于该名称进⾏告警分组。)
- expr:这是⼀个PromQL表达式,⽤来确定何时触发告警。如果这个表达式的结果是true,就表示告警的条件被满⾜了。
- for:⽤来定义表达式结果必须持续为true多⻓时间后,才正式触发告警。 如果没有持续满⾜则处于“pending”状态;⼀旦持续满⾜并且则处于Fring状态。
- labels:这些是⾃定义的标签,可以⽤来添加额外的信息到告警上。这些标签值还可以⽤模板来设置。
- annotations:这是附加在告警上的注释信息。注释通常⽤来存储更详细的告警信息,它们的值也可以被模板调⽤并通知给相应的⼈。
简单来说,在Prometheus中,你可以创建告警规则来定义何时应该发出告警。这些规则有名称、条件、等待时间以及可以带有附加的⾃定义标签和详细说明的注释。这样,当你的系统出现问题时,就会收到⼀条包含所有必要信息的告警消息。
3.3 配置Prometheus加载规则
为了能够让Prometheus能够定期评估告警规则,我们需要在Prometheus全局配置⽂件中通过 rule_files 指定告警规则⽂件的路径,⽽后
1、配置Prometheus加载告警规则⽂件
#告警规则文件
rule_files:
- "rules/*.yml"
2、检查Prometheus语法
/app/module/prometheus/promtool check config /app/module/prometheus/prometheus.yml
3、重启Prometheus服务
curl -X POST http://192.168.137.131:9090/-/reload
3.4 触发规则并验证告警通知
1、停⽌node_exporter服务,那么就会触发告警
systemctl stop node_exporter.service
2、检查Prometheus的Alert⻚⾯的状态是否处于Firing
3、检查AlertManager是否收到了告警
4、检查邮件是否能看到告警的信息,因为三条告警的alertname是⼀致的,因此它们会合并为⼀条消息发送出来。
5、如果成功修复了故障,那么等待⼀段时间会发送恢复消息
3.5 ⾃定义邮件告警模板
1、定义告警的通知模板和恢复模板
mkdir /app/module/alertmanager/template
vim /app/module/alertmanager/template/email.tmpl
{{ define "email.html" }}
{{- if gt (len .Alerts.Firing) 0 -}}
{{ range .Alerts }}
<h2 style="color: red;">@告警通知</h2>
告警程序: AlertManager <br>
告警级别: {{ .Labels.severity }} <br>
告警类型: {{ .Labels.alertname }} <br>
故障主机: {{ .Labels.instance }} <br>
告警主题: {{ .Annotations.summary }} <br>
告警详情: {{ .Annotations.description }} <br>
触发时间: {{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} <br>
{{ end }}{{ end -}}
{{- if gt (len .Alerts.Resolved) 0 -}}
{{ range .Alerts }}
<h2 style="color: green;">@告警恢复</h2>
告警程序: AlertManager <br>
告警级别: {{ .Labels.severity }} <br>
告警类型: {{ .Labels.alertname }} <br>
告警主机: {{ .Labels.instance }} <br>
告警主题: {{ .Annotations.summary }} <br>
告警详情: {{ .Annotations.description }} <br>
触发时间: {{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} <br>
恢复时间: {{ (.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} <br>
{{ end }}{{ end -}}
{{ end }}
2、配置AlertManager,引⽤该模板
3、检查配置
/app/module/alertmanager/amtool check-config /app/module/alertmanager/alertmanager.yml
4、重新加载AlertManager
curl -X POST http://192.168.137.131:9093/-/reload
5、触发告警,验证告警模板是否正常渲染