AlertManager 报警收敛的若干种方法

本篇博客介绍了 AlertManager 报警收敛的若干种方法。

背景

当一个监控-告警系统建立起来后,告警系统将会面临这样的问题:警报消息太多,接收人很容易麻木,不再继续理会,关键的告警常常被淹没。

对于这一问题,AlertManger 提供了非常好的解决方案。Prometheus 把一条告警信息发送给了 AlterManagerAlterManager 并不是简简单单地直接发送出去,而是对告警信息进行了一些诸如分组、延时等收敛处理。

对报警收敛的支持,AlertManager 提供了以下四种方式:

  • 分组
  • 抑制
  • 静默
  • 延时

告警分组

告警分组是通过对具有相同属性值的告警进行分组聚合,可以有效的减少告警消息的数量。

对应 AlertManager 的配置,通过 route 部分的 group_by 字段对具有相同属性的告警进行分组聚合。

1
2
3
route:
  # AlertManager 将会把具有相同 alertname 的告警分到相同的组  
  group_by: ['alertname']

告警抑制

当告警发出后,停止重复发送由此告警引发的其他告警。一般是由更高级别的告警抑制低级别的告警。这可以消除冗余的告警,仅发送关键警报,避免误导运维排查问题的方向。

AlertManager 的配置中,通过 inhibit_rules 部分来配置

1
2
3
4
5
6
inhibit_rules:
  - source_match:        # source_match:匹配当前告警发生后其他告警抑制掉
      severity: 'critical'
    target_match:        # target_match:抑制告警
      severity: 'warning'
    equal: ['alertname'] # equal:只有包含指定标签才可成立规则

以上配置告诉 AlertManager,对于具有相同 alertname 的告警,含 severity: 'critical' 标签的告警将会抑制含 severity: 'warning' 标签的告警。

告警静默

对可预期的告警,在特定时间段阻止告警的发送,比如,线上环境资源调整或上线,可能会导致告警,此时,可以增加告警静默,阻止相关的告警发送。

可以在 http://localhost:9093/#/silences 中进行创建。

告警延时

当故障发生时,若故障未能及时解决,频繁地发送告警是令人崩溃的。group_wait 把开始产生的告警收集起来,最后作为一条告警信息发送出来,repeat_interval 可以将重复的告警以更大的时间间隔发送。

AlertManager 的配置中进行如下配置:

1
2
3
4
route:
  group_wait: 60s       # 分组等待的时间为 60 秒,收到告警后并不是马上发送出去,看是否还有具有 alertname 这个标签的报警发过来,如果有的话,一起发出报警
  group_interval: 60s   # 上一组报警与下一组报警的间隔时间为 60 秒
  repeat_interval: 15m  # 重复报警时间

其他方式

我们也可以考虑把告警信息都收集起来,做统计分析,基于统计数据按周、月生成告警报告,比如,哪些应用在哪段时间里产生了最多的报警,哪些指标在哪段时间里产生了最多的报警,某个报警阈值的 90% 分位数、95%分位数、99%分位数,哪个部门产生了最多的报警数等等。一来要求业务团队改造程序或结构,调整资源配置,比如有些代码写得性能特别差,资源占用高,导致告警信息频繁发送;二来可以作为我们设置各种资源阈值的统计参考数据,取代常用的经验值或习惯值,比如,根据历史报警数据的统计,采取百分位数,使得某告警在 95% 的情况下不再发送告警信息。

总结和思考

做好告警的收敛是很有必要的,也有多种方法。借助于 AlertManager,我们可以通过分组、抑制、静默和延时等方法来做告警的收敛。

AlertManager 而言,在告警抑制上,我们还可以考虑更多的告警抑制规则,比如,在多种告警级别(criticalemergencywarning等)的情况下,每一种高级别告警抑制所有比它低的级别的告警;在告警延时上,高级别告警的延时参数缩短,低级别告警的延时参数增长。

另外,基于统计数据按周、月生成告警报告,改进应用程序和架构,合理设置阈值,更好和更准确地报警。

考虑这样一种设计,我们想把 AlertManager 发送的报警收集起来,那么,由于 AlertManager 会把从 Prometheus 发送来的报警信息进行分组聚合,抑制等操作,从而导致实际产生的报警一般会多于发送出来的报警。如果我们想把 AlertManager 的报警信息收集起来,那么,我们是应该在 AlertManager 接收到报警的时候收集,还是在真正发送报警之前进行收集?

如果是在接收到报警时收集,那么我们实际上会收集到所有产生的报警,数据量大,信息详尽。如果使用这些进行分析,进而改进代码、程序架构和资源配置,那么,将会从上游彻底地减少报警,并且促进整个研发运维的进步和系统的稳定性。

如果是在实际发送时收集,那么我们收集到的数据量就会比较小,报警是经过聚合的,被抑制的报警不发送,经过分析优化后,将会使得接收到的报警数量减少,但是产生的报警(按原来的标准,这种情况下会产生报警)却可能增多,比如在不做上游改变的情况下,调整阈值,使得 99% 的报警不发送,问题则会堆积在 Prometheus 那边,不会向 AlertManager 发送报警。

根据以上分析,我们选择在 AlertManager 接收到报警时即收集之。

updatedupdated2020-02-272020-02-27
加载评论