本期作者:吴洋
爱可生上海研发核心成员,研发工程师。
景象
测试环境中呈现了一个异样的告警景象:一条告警通过 Thanos Ruler 的 HTTP 接口察看到继续处于 active 状态,然而从 AlertManager 这边看这条告警为已解决状态。依照 DMP 平台的设计,告警已解决指的是告警上设置的完结工夫曾经过了以后工夫。一条发送至 AlertManager 的告警为已解决状态有三种可能:
1. 手动解决了告警
2. 告警只产生了一次,第二次计算告警规定时会发送一个已解决的告警
3. AlertManager 接管到的告警会带着一个主动解决工夫,如果还没达到主动解决工夫,则将该工夫重置为 24h 后首先,
因为理解到测试环境没有手动解决过异样告警,排除第一条;
其次,因为该告警继续处于 active 状态,所以不会是因为告警只产生了一次而接管到已解决状态的告警,排除第二条;
最初,告警的告警的产生工夫与主动解决工夫相差不是 24h,排除第三条。
那问题出在什么中央呢?
剖析
上面咱们开始剖析这个问题。综合第一节的形容,初步的猜测是告警在达到 AlertManager 前的某些阶段的处理过程太长,导致告警达到 AlertManager 后就曾经过了主动解决工夫。咱们从剖析平台里一条告警的流转过程动手,找出告警 在哪个解决阶段耗时过长。首先,一条告警的产生须要两方面的配合:
- metric 数据
- 告警规定
将 metric 数据输出到告警规定进行计算,如果符合条件则产生告警。DMP 平台集成了 Thanos 的相干组件,数据的提供和计算则会离开,数据还是由 Prometheus Server 提供,而告警规定的计算则交由 Thanos Rule(下文简称 Ruler)解决。下图是 Ruler 组件在集群中所处的地位:
看来,想要弄清楚现告警的产生到 AlertManager 之间的过程,须要先弄清除 Ruler 的大抵机制。官网文档对 Ruler 的介绍是:You can think of Rule as a simplified Prometheus that does not require a sidecar and does not scrape and do PromQL evaluation (no QueryAPI)。
不难揣测,Ruler 应该是在 Prometheus 上封装了一层,并提供一些额定的性能。通过翻阅材料大抵理解,Ruler 应用 Prometheus 提供的库计算告警规定,并提供一些额定的性能。上面是 Ruler 中告警流转过程:
首先,图中每个告警规定 Rule 都有一个 active queue(上面简称本地队列),用来保留一个告警规定下的沉闷告警。
其次,从本地队列中取出告警,发送至 AlertManager 前,会被放入 Thanos Rule Queue(上面简称缓冲队列),该缓冲队列有两个属性:
- capacity(默认值为 10000):管制缓冲队列的大小,
- maxBatchSize(默认值为 100):管制单次发送到 AlertManager 的最大告警数
理解了上述过程,再通过翻阅 Ruler 源码发现,一条告警在放入缓冲队列前,会为其设置一个默认的主动解决工夫(以后工夫 + 3m),这里是影响告警主动解决的开始工夫,在这当前,有两个阶段可能影响告警的解决:
1. 缓冲队列阶段
2. 出缓冲队列到 AlertManager 阶段(网络提早影响)
因为测试环境是局域网环境,并且也没在环境上发现网络相干的问题,咱们初步排除第二个阶段的影响,上面咱们将注意力放在缓冲队列上。通过相干源码发现,告警在缓冲队列中的处理过程大抵如下:
如果本地队列中存在一条告警,其上次发送之间间隔当初超过了 1m(默认值,可批改),则将该告警放入缓冲队列,并从缓冲队列中推送最多 maxBatchSize 个告警发送至 AlertManager。反之,如果所有本地队列中的告警,在最近 1m 内都有发送过,那么就不会推送缓冲队列中的告警。也就是说,如果在一段时间内,产生了大量反复的告警,缓冲队列的推送频率会降落。队列的生产方太多,生产方太少,该队列中的告警就会产生沉积的景象。
因而咱们不难猜测,问题起因很可能是是缓冲队列推送频率变低的状况下,单次推送的告警数量太少,导致缓冲队列沉积。上面咱们通过两个方面验证上述猜测:
首先通过日志能够失去队列在大概 20000s 内推送了大概 2000 次,即均匀 10s 推送一次。联合缓冲队列的具体属性,一条存在于队列中的告警大概须要 (capacity/maxBatchSize)*10s = 16m,AlertManager 在接管到告警后早已超过了默认的主动解决工夫(3m)。
其次,Ruler 提供了 3 个 metric 的值来监控缓冲队列的运行状况:
- thanos_alert_queue_alerts_dropped_total
- thanos_alert_queue_alerts_pushed_total
- thanos_alert_queue_alerts_popped_total
通过观察 thanos_alert_queue_alerts_dropped_total 的值,看到存在告警失落的总数,也能佐证了缓冲队列在某些时刻存在已满的状况。
解决
通过以上的剖析,咱们根本确定了问题的本源:Ruler 组件内置的缓冲队列沉积造成了告警发送的提早。针对这个问题,咱们抉择调整队列的 maxBatchSize 值。上面介绍一下这个值如何设置的思路。
因为每计算一次告警规定就会尝试推送一次缓冲队列,咱们通过预计一个告警数量的最大值,失去 maxBatchSize 能够设置的最小值。假如你的业务零碎须要监控的实体数量别离为 x1、x2、x3、…、xn,实体上的告警规定数量别离有 y1、y2、y3、…、yn,那么一次能产生的告警数量最多是(x1 y2 + x2 y2 + x3 y3 + … + xn yn),最多推送(y1 + y2 + y3 + … + yn)次,所以要使缓冲队列不沉积,maxBatchSize 应该满足:
maxBatchSize >= (x1 y2 + x2 y2 + x3 y3 + … + xn yn) / (y1 + y2 + y3 + … + yn),假如 x = max(x1,x2, …,xn), 将不等式左边适当放大后为 x,即 maxBatchSize 的最小值为 x。也就是说,能够将 maxBatchSize 设置为零碎中数量最大的那一类监控实体,对于 DMP 平台,一般来说是 MySQL 实例。
注意事项
下面的计算过程只是提供一个参考思路,如果最终计算出该值过大,很有可能对 AlertManager 造成压力,因此失去缓冲队列的作用,所以还是须要结合实际状况,具体分析。
因为 DMP 将 Ruler 集成到了本人的组件中,所以能够比拟不便地对这个值进行批改。如果是按照官网文档的介绍应用的 Ruler 组件,那么须要对 源码文件 进行定制化批改。
源码文件:
https://github.com/thanos-io/…
参考资料
1. https://thanos.io/tip/thanos/…
2. https://thanos.io/tip/compone…
相干内容方面的常识,大家还有什么疑难或者想晓得的吗?连忙留言通知小编吧!