一、需求
每个 pod 重启/删除时,都能发出告警。要及时和准确。
二、告警架构
集群部署在 k8s 上,告警使用 Prometheus alertManager prometheusManager,helm 方式部署。
三、实现
根据 pod 容器状态判断,容器状态为 notReady 时,触发告警。需要注意的是缩短采集间隔到 15s,让重启 pod 数据别漏过去。 告警规则 alert: PodDown # 15s 采集 15s 扫描规则,规则是1分钟前存在 pod 为 not ready 的 pod,15s 扫描一次的间隔,至少能扫描 3次,所以一定会发送
代码语言:javascript复制expr: min_over_time(kube_pod_container_status_ready{pod!~".*job.*|backup.*|minio-backup.*|clean-docker|dynamic-index-patterns|node-shell.*|.*jenkins.*"} [1m])== 0
for: 1s # 持续多久确认报警信息
labels:
group: CAAS
severity: warning
annotations:
summary: 'Container: {{ $labels.container }} down'
message: 'Namespace: {{ $labels.namespace }}, Pod: {{ $labels.pod }} 服务不可用'
promethues 配置
代码语言:javascript复制global:
scrape_interval: 15s # 数据采集时间,默认一分钟
evaluation_interval: 15s # 规则扫描时间,默认一分钟
alertmanager 配置
代码语言:javascript复制group_wait: 10s # 分组等待的时间
group_interval: 30s # 上下两组发送告警的间隔时间。比如有同组的告警A和告警B,如果A触发告警,会等待30s,如果B在等待时间内也出发告警,会合并在一起发送,如果告警A 触发两次,告警A 发送后,30s 之后在发告警A第二次触发
repeat_interval: 12h # 重发间隔
三、参数讲解
alert.for: 持续多久发送报警信息,它至少需要连续两次扫描都出现异常才告警。比如 for 设置为 1s 中,异常存在 10s,以下两种情况也不发出告警。
- 默认采集间隔和扫描间隔为 1min,采集时异常恢复,不会触发;
- 异常在采集点上报,但在第二次采集前恢复,也不会告警。 只有至少连续扫描两次都存在异常,且持续时间大于 for 的异常才会发送告警。
scrape_interval: 数据采集时间,默认一分钟,告警的原始数据基于采集的数据,采集频率过小,会漏掉告警。 evaluation_interval: 规则扫描时间,默认一分钟,将采集数据按告警规则扫描,超过阀值发给 alertmanager。 group_interval: 同一 group 等待间隔,在时间段内的告警会聚合,等时间到一起发送。
四、QA
4.1 为什么告警有时发的及时,有时发的慢
运维异常到告警发出与多个参数相关,采集间隔,扫描间隔,group 发送间隔,规则 for 相关。 告警的生命周期
- 监控数据定期采集
- 告警规则定期扫描,发现告警发给 alertmanager,prometheus 页面可看到 pending
- 多次发送的 alertmanager,且持续时长超过告警配置的 for,prometheus 页面可看到 fire
- 等待 group_interval 时间聚合发送。
pending 状态告警
firing 状态告警
比如服务器内存超过 80%,持续 30s 中发送告警。告警发送过程如下
- 服务器 12:00:00 内存使用 90%,达到告警值
- promethues 12:00:10 采集到数据
- 12:00:20 promethues 开始扫描规则发现告警时,发送给 alertmanager,此时告警处于 pending 状态,不会发送。
- promethues 12:01:10 第二次采集到数据
- promethues 12:01:20 第二次扫描发现告警持续,计算持续时间超过 30s, 告警状态为 firing,准备发送发送告警。
- 12:01:50 group 聚合时间到,告警聚合发送。
虽然 12:00:30 就应该发出告警,实际在一分半之后的 12:01:50 才发出。 相关配置
代码语言:javascript复制alert: PodDown
expr: min_over_time(kube_pod_container_status_ready{pod!~".*job.*|backup.*|minio-backup.*|clean-docker|dynamic-index-patterns|node-shell.*|.*jenkins.*"} [1m])== 0
for: 1s # 持续多久确认报警信息
labels:
group: CAAS
severity: warning
annotations:
summary: 'Container: {{ $labels.container }} down'
message: 'Namespace: {{ $labels.namespace }}, Pod: {{ $labels.pod }} 服务不可用'
global:
scrape_interval: 15s # 数据采集时间,默认一分钟
evaluation_interval: 15s # 规则扫描时间,默认一分钟
group_wait: 10s # 分组等待的时间
group_interval: 30s # 上下两组发送告警的间隔时间。比如有同组的告警A和告警B,如果A触发告警,会等待30s,如果B在等待时间内也出发告警,会合并在一起发送,如果告警A 触发两次,告警A 发送后,30s 之后在发告警A第二次触发
repeat_interval: 12h # 重发间隔
4.2 为什么告警总在重复发,有时不重复发,怎么避免
告警会在两种情况下重发
- group 列表中告警有变更
- 到了 repeat_interval 配置的重发时间。
列表变更理解:在 alertManager 中,同 group 在 group_interval 的时间段内触发的告警会聚合到一个列表,如图一。当下次规则扫描,触发告警时,告警列表有变更,则触发告警。如同个 group 的告警 A, B,C 在 30s 触发,会聚合发送。之后 A,B,C 持续异常,在下次扫描规则时,不重发;如果新告警D 触发,告警列表中存在 A, B, C, D,会触发发送;原列表中告警恢复也会导致触发发送。 如果告警 A,B,C 一直异常,列表也没有新增告警,直到 repeat_interval 的间隔时间,再次触发。 解决办法
- group 将易变的告警和容易持续异常的告警分到不同的组,发送时组内就不会存在一直是异常的告警。
- 快速把告警修好。
group_wait: 10s # 分组等待的时间
group_interval: 30s # 上下两组发送告警的间隔时间。比如有同组的告警A和告警B,如果A触发告警,会等待30s,如果B在等待时间内也出发告警,会合并在一起发送,如果告警A 触发两次,告警A 发送后,30s 之后在发告警A第二次触发
repeat_interval: 12h # 重发间隔
图1