Prometheus Alertmanager 生产配置趟过的坑总结
本文最后更新于:2024年7月25日 下午
简介
Alertmanager 处理由客户端应用程序(如 Prometheus server)发送的警报。它负责去重 (deduplicating),分组 (grouping),并将它们路由 (routing) 到正确的接收器 (receiver) 集成,如电子邮件,微信,或钉钉。它还负责处理警报的静默 / 屏蔽 (silencing)、定时发送 / 不发送 (Mute) 和抑制 (inhibition) 问题。
AlertManager 作为 开源的为 Prometheus 而设计的告警应用,已经具备了告警应用各类丰富、灵活、可定制的功能:
- 去重 (deduplicating):比如高可用 AlertManager 部署下,同一个告警同时发到所有的高可用节点,会根据 hash 进行去重
- 分组(grouping):比如可以根据
AlertName
,Instance
,Job
等任意 label 对海量告警进行分组。典型情况就是,突然好多 Pod 都发出了AlertName: InstanceDown
的 Alerts, 那么可以直接根据AlertName
进行分组后发送,这样用户只会收到一封xxx 个 Pods InstanceDown
的告警邮件。大大减少告警接收人员的收件量. - 路由 (routing): 将告警跟进一定的过滤条件发送到指定的 receiver. 如:满足
job=db
的告警路由给 DBA; 满足team=team-A
的告警路由给 team-A 的邮件组… - 接收器 (receiver): 具体的通知渠道 + 收件人。如: 邮件通知渠道 + DBA 邮箱;钉钉通知渠道 + SRE 联系人;
- 静默 / 屏蔽 (silencing): 如应用发布的时间段,屏蔽相关的告警.
- 定时发送 / 不发送 (Mute): 如工作时间 (965, 每周 5 天) 通过邮件渠道发送;非工作时间 (下班、周末、节假日) 正常渠道 mute, 仅通过 on-call 渠道发送给 on-call 人员
- 抑制 (inhibition):常用场景,高级别的告警触发(firing)后,低级别的告警就不用发了。比如:磁盘空间的
critical
级别告警已经触发 (空间使用超过 90%), 这时候warning
级别的告警 (空间使用超过 80%) 就被抑制.
除了没有多租户功能、没有很好的 UI 界面、没有告警历史统计展示之外,作为告警应用, AlertManager 已经是非常强大了。👍️👍️👍️
AlertManager 生产配置趟过的坑
接下来就不东拉西扯了, 直接进入正题:AlertManager 生产配置趟过的坑
📝Notes:
以下所有内容基于 20220723 时 AlertManager 的最新版: v0.24
URL 相关配置
需求
- 对外展示的 URL 是类似这样的:
https://ewhisper.cn/alertmanager/#/alerts
- 是个域名
- 有个
/alertmanager/
前缀
- 请求转到 AlertManager 组件时,还是维持默认的情况不变,如
https://10.0.0.1:9093/#/alerts
即:反向代理发送的路径与用户使用的不同.
实现
Ingress 层面的实现
这里直接使用 Traefik 来实现的,之前已经写过文章了,具体参见这里:
AlertManager 配置
AlertManager 这里需要配置 2 个静态参数,是通过在 AlertManager 的 StatefulSets 中添加 alertmanager --<flags>
来实现的.
默认情况下,Prometheus(和 Alertmanager)假定外部 URL (-web.external-url
) 中的任何路径都是一个前缀路径,将在所有发送到它的请求中出现。然而这并不总是如此,--web.route-prefix
标志允许你更细化地控制这一点。
通过如下配置,这将在向 AlertManager 传递请求之前剥离掉 /alertmanager/
。在这种情况下,你需要指定用户在其浏览器中使用的 URL 是 https://ewhisper.cn/alertmanager/
,而 Prometheus 在其 HTTP 请求中看到的前缀不是 /alertmanager/
,而只是空的 /
。
1 |
|
一个小坑
经过上面的配置,都很完美,但是查看邮件内容的时候发现一个小坑:
- 默认邮件模板最下方的
Sent by Alertmanager
url 没有/
, 导致点击该 url 后无法正常跳转.
这里是通过 Ingress - Traefik 实现了自动加 /
的功能,可以参见另一篇文章:
默认自动 Resolved 告警的坑
如果你没有详细看过文档,直接采用的默认配置,并且 AlertManager 的告警源除了 Prometheus 也有其他监控软件。你会发现一个情况:每过 5min, 某些还在触发中的告警被自动 Resolved (已恢复) 了!
这是因为默认的 AlertManager 的配置中,有个 resolve_timeout
的参数,且其默认配置为: resolve_timeout: 5m
.
📚️Reference:
ResolveTimeout 是 alertmanager 使用的默认值,如果 alerts 不包括 EndsAt,在这个时间过后,如果 alerts 没有被更新,AlertManager 会将其声明为已解决 (Resolved)。
这个参数对来自 Prometheus 的 alerts 没有影响,因为它们总是包括 EndsAt。
这就是 自动 Resolved 的原因,当初碰到的时候,我一看,这好办啊,我想要禁用这个功能,虽然这个参数无法禁用,如果非要在这份爱上加上一个期限,我希望是一万年 , 直接设置个 10000y
得了.
结果报错了…😂😂😂
这个 duration
在文档上,明明说是:
📚️Reference:
<duration>
: 正则表达式匹配的持续时间((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)
, 如.1d
,1h30m
,5m
,10s
但是设置 10000y
满足 ([0-9]+)y)
却报错了. 😂
后面又翻各种源码,终于发现这个 <duration>
是无法设置为 三位数的 y 的:设置 100y
报错,设置 99y
正常运行.
所以,想要禁用 AlertManager 自动 Resolved 的功能,就这么设置: resolve_timeout: 99y
默认 4H 还未解决的告警自动重发告警通知的坑
不管是谁,我觉得都是希望自己每天收到的告警邮件越少越好的,方便一项项跟进解决.
结果 AlertManager 倒好,"贴心" 地提供了 4H 未解决告警自动重发 的功能. 😂😂😂
这是因为默认的 AlertManager 的配置中,有个 repeat_interval
的参数,且其默认配置为: repeat_interval: 4h
…
还是像上回一样,我想要禁用这个功能,虽然这个参数无法禁用 (如果设置为 0, 不会禁用,反而会报错: repeat_interval cannot be zero
), 如果非要在这份爱上加上一个期限,我希望是一万年 , 直接设置个 10000y
得了.
结果又报错了 (严格说是 warning)…😂😂😂
1 |
|
📚️Reference:
repeat_interval 大于数据保留期。这可能导致通知的重复频率超过预期。
也就是说,repeat_interval
设置太大反而可能会导致通知的重复频率更高,如果想把它设置的尽可能大,也不要大于数据的保留时间.
所以,想要尽可能降低 AlertManager 未解决告警自动重发 的频率,就这么设置: repeat_interval: <尽可能大, 但不要大于数据的保留(data retention)时间
设置 AlertManager 的数据保留 (data retention) 时长
接着上文来说,默认的 AlertManager 的数据保留 (data retention) 时长是多久呢?如果想要调大该如何调呢?
查找文档,又没找到😂😂😂
为啥没找到,原因如下:
📚️Reference:
Alertmanager 通过命令行标志 (command-line flags) 和一个配置文件进行配置。
命令行标志配置了不可改变的系统参数,而配置文件定义了抑制规则、通知路由和通知接收者。
文档是没有关于 命令行标志配置 的内容的。在哪儿能找到呢?运行 alertmanager -h
命令,结果如下:
📝Notes:
仅显示部分,cluster 相关的 flags 很多,就不展示了.
1 |
|
可以看到: --data.retention=120h
默认是 120h, 5 天.
太少了,改为 --data.retention=90d
, 结果又错了😂😂😂, 这次是格式,应该写为: --data.retention=--data.retention=2160h
那么相应的,上面的参数就可以设置为: repeat_interval: 90d
(是的,你没看错,这里可以写为 90d …😅😅😅)
完整的生产实践 AlertManager 配置
最终,给到大家一份完整的生产实践 AlertManager 配置,供参考:
不可变参数 (及命令行 flags)
'--storage.path=/alertmanager'
(存储位置,生产上这个目录需要配置持久化存储)'--config.file=/etc/alertmanager/alertmanager.yml'
(配置文件位置,生产上可以通过 ConfigMap 保存并使用)'--cluster.advertise-address=[$(POD_IP)]:9094'
(高可用集群端口 9094)'--cluster.listen-address=0.0.0.0:9094'
(高可用集群端口 9094)--cluster.peer=alertmanager-0.alertmanager-headless:9094
(高可用集群的一个 peer; 需要创建 headless service)--cluster.peer=alertmanager-1.alertmanager-headless:9094
(高可用集群的另一个 peer)--cluster.peer=alertmanager-2.alertmanager-headless:9094
(高可用集群的第三个 peer)'--data.retention=2160h'
'--log.level=info'
(日志级别,开发测试环境可以设置为debug
)'--web.external-url=https://ewhisper.cn/alertmanager/'
'--web.route-prefix=/'
可变参数 (配置文件中的参数)
1 |
|
具体的 route, receiver, inhibit 等配置就不体现了.
以上.
🎉🎉🎉