如鲸向海,似鸟投林
1.Prometheus邮件报警
Prometheus的架构中被划分为两个部分,在Prometheus Server中定义告警规则以及产生告警,Alertmanager组件则用于处理这些由Prometheus产生的告警。Alertmanager即Prometheus体系中告警的统一处理中心。Alertmanager提供了多种内置第三方告警通知方式,同时还提供了对Webhook通知的支持,通过Webhook用户可以完成对告警更多个性化的扩展。
Prometheus报警简介
告警能力在Prometheus的架构中被划分成两个独立的部分。如下所示,通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。
在Prometheus中一条告警规则主要由以下几部分组成:
1. 告警名称:用户需要为告警规则命名,当然对于命名而言,需要能够直接表达出该告警的主要内容
2. 告警规则:告警规则实际上主要由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页面上进行设置。
2.自定义Prometheus告警规则
Prometheus中的告警规则允许你基于PromQL表达式定义告警触发条件,Prometheus后端对这些触发规则进行周期性计算,当满足触发条件后则会触发告警通知。默认情况下,用户可以通过Prometheus的Web界面查看这些告警规则以及告警的触发状态。当Promthues与Alertmanager关联之后,可以将告警发送到外部服务如Alertmanager中并通过Alertmanager可以对这些告警进行进一步的处理。
定义告警规则
一条典型的告警规则如下所示:
groups:
- name: example
rules:
- alert: HighErrorRate
expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5
for: 10m
labels:
severity: page
annotations:
summary: High request latency
description: description info
在告警规则文件中,我们可以将一组相关的规则设置定义在一个group下。在每一个group中我们可以定义多个告警规则(rule)。一条告警规则主要由以下几部分组成:
alert:告警规则的名称。 expr:基于PromQL表达式告警触发条件,用于计算是否有时间序列满足该条件。
for:评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在等待期间新产生告警的状态为pending。
labels:自定义标签,允许用户指定要附加到告警上的一组附加标签。
annotations:用于指定一组附加信息,比如用于描述告警详细信息的文字等,annotations的内容在告警产生时会一同作为参数发送到Alertmanager。
为了让Prometheus能够启用定义的告警规则,我们需要在Prometheus全局配置文件中通过rule_files指定一组告警规则文件的访问路径,Prometheus启动后会自动扫描这些路径下规则文件中定义的内容,并且根据这些规则计算是否向外部发送通知:
rule_files:
[ - <filepath_glob> ... ]
默认情况下Prometheus会每分钟对这些告警规则进行计算,如果用户想定义自己的告警计算周期,则可以通过evaluation_interval来覆盖默认的计算周期:
global:
[ evaluation_interval: <duration> | default = 1m ]
模板化
在告警规则文件的annotations中使用summary描述告警的概要信息,description用于描述告警的详细信息。同时Alertmanager的UI也会根据这两个标签值,显示告警信息。为了让告警信息具有更好的可读性,Prometheus支持模板化label和annotations的中标签的值。
通过$labels.变量可以访问当前告警实例中指定标签的值。$value则可以获取当前PromQL表达式计算的样本值。
# To insert a firing element's label values:
{{ $labels.<labelname> }}
# To insert the numeric expression value of the firing element:
{{ $value }}
例如,可以通过模板化优化summary以及description的内容的可读性:
groups:
- name: example
rules:
# Alert for any instance that is unreachable for >5 minutes.
- alert: InstanceDown
expr: up == 0
for: 5m
labels:
severity: page
annotations:
summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes."
# Alert for any instance that has a median request latency >1s.
- alert: APIHighRequestLatency
expr: api_http_request_latencies_second{quantile="0.5"} > 1
for: 10m
annotations:
summary: "High request latency on {{ $labels.instance }}"
description: "{{ $labels.instance }} has a median request latency above 1s (current value: {{ $value }}s)"
查看告警状态
如下所示,用户可以通过Prometheus WEB界面中的Alerts菜单查看当前Prometheus下的所有告警规则,以及其当前所处的活动状态。
同时对于已经pending或者firing的告警,Prometheus也会将它们存储到时间序列ALERTS{}中。
可以通过表达式,查询告警实例:
ALERTS{alertname="" , alertstate="pending|firing", <additional alert labels>}
样本值为1表示当前告警处于活动状态(pending或者firing),当告警从活动状态转换为非活动状态时,样本值则为0。
示例:定义主机监控报警
修改Prometheus配置文件prometheus.yml,添加以下配置:
rule_files:
- /usr/local/prometheus/*.rules
在目录/usr/local/prometheus/下创建告警文件alert.rules内容如下:
groups:
- name: hostStatsAlert
rules:
- alert: hostCpuUsageAlert
expr: sum(avg without (cpu)(irate(node_cpu_seconds_total{mode!='idle'}[1m]))) by (instance) > 0.5
for: 1m
labels:
severity: page
annotations:
summary: "Instance {{ $labels.instance }} CPU usgae high"
description: "{{ $labels.instance }} CPU usage above 50% (current value: {{ $value }})"
- alert: hostMemUsageAlert
expr: (node_memory_MemTotal - node_memory_MemAvailable)/node_memory_MemTotal > 0.7
for: 1m
labels:
severity: page
annotations:
summary: "Instance {{ $labels.instance }} MEM usgae high"
description: "{{ $labels.instance }} MEM usage above 50% (current value: {{ $value }})"
重启Prometheus后访问Prometheus UI http://127.0.0.1:9090/rules可以查看当前以加载的规则文件。这里我将阀值调小了,但是配置文件忘记修改不必在意。
切换到Alerts标签http://127.0.0.1:9090/alerts可以查看当前告警的活动状态。
此时,我们可以手动拉高系统的CPU使用率,验证Prometheus的告警流程,在主机上运行以下命令:
cat /dev/zero>/dev/null
运行命令后查看CPU使用率情况,如下图所示:
Prometheus首次检测到满足触发条件后,hostCpuUsageAlert显示由一条告警处于活动状态。由于告警规则中设置了1m的等待时间,当前告警状态为PENDING,如果1分钟后告警条件持续满足,则会实际触发告警并且告警状态为FIRING,如下图所示:
3.部署AlertManager
Alertmanager和Prometheus Server一样均采用Golang实现,并且没有第三方依赖。一般来说我们可以通过以下几种方式来部署Alertmanager:二进制包、容器以及源码方式安装。
AlertManager常用命令参数:
-h,--help显示上下文相关的帮助(也可以尝试--help-long和--help-man)。
--config.file =“ alertmanager.yml”
Alertmanager配置文件名。
--storage.path =“ data /”数据存储的基本路径。
--data.retention = 120h保留数据的时间。
--alerts.gc-interval = 30m警报GC之间的间隔。
--web.external-url = WEB.EXTERNAL-URL
从外部可访问Alertmanager的URL(例如,如果Alertmanager是通过反向提供的
代理)。用于生成返回到Alertmanager本身的相对和绝对链接。如果该网址包含路径部分,
它将用于为Alertmanager服务的所有HTTP端点添加前缀。如果省略,则相关的URL组件将为
自动派生。
--web.route-prefix = WEB.ROUTE-PREFIX
Web端点内部路由的前缀。默认为--web.external-url的路径。
--web.listen-address =“:9093”
侦听Web界面和API的地址。
--web.get-concurrency = 0并发处理的最大GET请求数。如果为负数或零,则限制为GOMAXPROC或8,以两者中的最大值为准
更大。
--web.timeout = 0 HTTP请求超时。如果为负或零,则不设置超时。
--cluster.listen-address =“ 0.0.0.0:9094”
集群的监听地址。设置为空字符串以禁用高可用性模式。
--cluster.advertise-address = CLUSTER.ADVERTISE-ADDRESS
在群集中进行广播的显式地址。
--cluster.peer = CLUSTER.PEER ...
最初的同伴(可以重复)。
--cluster.peer-timeout = 15秒
等待对等方之间发送通知的时间。
--cluster.gossip-interval = 200ms
发送八卦消息之间的间隔。通过降低此值(更频繁),可以传播八卦消息
以增加带宽为代价更快地跨集群运行。
--cluster.pushpull-interval = 1m0s
八卦状态同步的间隔。将此间隔设置得越低(越频繁),将加快整个过程的收敛速度
较大的群集,但以增加带宽使用为代价。
--cluster.tcp-timeout = 10s与远程节点建立流连接以进行完整状态同步以及流读写的超时
操作。
--cluster.probe-timeout = 500ms
在假定它不正常之前,等待被探测节点发出的确认超时。应将其设置为99%
网络上的RTT(往返时间)。
--cluster.probe-interval = 1s
随机节点探测之间的间隔。将此值设置得较低(更频繁)将导致群集检测到故障
节点更快地增加带宽使用率。
--cluster.settle-timeout = 1m0s
在评估通知之前,等待集群连接建立的最长时间。
--cluster.reconnect-interval = 10秒
尝试重新连接到丢失的对等方之间的间隔。
--cluster.reconnect-timeout = 6h0m0s
尝试重新连接到丢失的对等设备的时间长度。
--log.level = info仅记录具有给定严重性或更高严重性的消息。下列之一:[调试,信息,警告,错误]
--log.format = logfmt日志消息的输出格式。下列之一:[logfmt,json]
--version显示应用程序版本。
tar xf alertmanager-0.21.0.linux-amd64.tar.gz -C /usr/local/ && cd /usr/local/
ln -s /usr/local/alertmanager-0.21.0.linux-amd64/ alertmanager
mkdir -p /usr/local/alertmanager/data/
vim /etc/systemd/system/alertmanager.service
添加如下内容:
[Unit]
Description=alertmanager
After=network.target
[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/alertmanager-0.21.0.linux-amd64/alertmanager --config.file=/usr/local/alertmanager/alert-test.yml --storage.path=/usr/local/alertmanager/data/
Restart=on-failure
[Install]
WantedBy=multi-user.target
–config.file用于指定alertmanager配置文件路径
–storage.path用于指定数据存储路径。
创建alertmanager配置文件
Alertmanager解压后会包含一个默认的alertmanager.yml配置文件,内容如下所示:
cd /usr/local/alertmanager
cp alertmanager.yml alert-test.yml
vim alert-test.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。
Alermanager会将数据保存到本地中,默认的存储路径为data/。因此,在启动Alertmanager之前需要创建相应的目录
启动Alertmanager
chown -R prometheus:prometheus /usr/local/alertmanager-0.21.0.linux-amd64/
systemctl status alertmanager.service
Alertmanager启动后可以通过9093端口访问,http://192.168.0.10:9093
默认监听端口:9093 集群监听端口9094
Alert菜单下可以查看Alertmanager接收到的告警内容。Silences菜单下则可以通过UI创建静默规则.
关联Prometheus与Alertmanager
在Prometheus的架构中被划分成两个独立的部分。Prometheus负责产生告警,而Alertmanager负责告警产生后的后续处理。因此Alertmanager部署完成后,需要在Prometheus中设置Alertmanager相关的信息。
编辑Prometheus配置文件prometheus.yml,并添加以下内容:
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093']
重启Prometheus服务,成功后,可以从http://192.168.0.10:9090/config查看alerting配置是否生效。
此时,再次尝试手动拉高系统CPU使用率:
cat /dev/zero>/dev/null
等待Prometheus告警进行触发状态:
查看Alertmanager UI此时可以看到Alertmanager接收到的告警信息。