触发告警和恢复的底层逻辑是什么?

告警规则里有3个配置非常关键,promql、执行频率、持续时长,意思就是按照执行频率,每隔一段时间执行promql查询(即时查询,即调用Prometheus协议的/api/v1/query接口),如果查到数据就认为触发了阈值,触发了阈值是否会产生告警事件,不一定,还要看持续时长,如果持续时长为0,就相当于不用等待,触发了阈值就立马生成事件,如果持续时长大于0,那就要等待,要保证持续时长这段时间内,每次执行promql的查询都触发阈值,才认为应该生成事件。持续时长就相当于prometheus.yml中的alert rule中的for。

比如promql为 cpu_usage_idle{cpu="cpu-total"} < 20,执行频率是10s,持续时长是60s,就表示在60s内每10s执行一次promql查询,看promql查询是否返回内容,如果6次都返回了,说明应该生成告警事件。

恢复的逻辑:比如已经产生了告警事件,然后再次拿着promql去查询,发现没有返回内容,那就说明当前的监控数据已经不符合promql中指定的阈值条件了,就表示恢复了。当然, 如果数据丢点了,promql自然也查不到,这种情况也是会报恢复,因为夜莺确实无法区分到底是因为丢点了,还是因为没有满足阈值而导致没有返回内容。那你可能会问,把promql解析一下,去掉promql中的操作符和阈值,只拿着前面部分去查询,不就能区分到底是没数据还是因为没有满足阈值了吗?其实很难,上面举例的promql是一种简单情况,复杂的promql非常复杂,没法这么轻易的拿掉操作符和阈值。

为何有时莫名奇妙报了恢复?

根据上面介绍的原理,报了恢复,就是因为夜莺拿着 promql 去时序库查询,没有返回内容。通常可能的原因是时序库的 --query.lookback-delta 参数设置的太小了,这个参数会影响即时查询返回的结果,如果数据滞后了,就查不到了,所以这个值不能设置的太小,一般和采集频率一样。比如大部分数据的采集频率在2分钟内,那这个值就可以设置为 2m。具体可以 google 一下,关键字:prometheus query.lookback-delta instant query。

告警规则的 ql 可以写 metricsql 么?

这个问题的提出者,用的是 VictoriaMetrics 作为时序库,VictoriaMetrics 提供了 metricsql 查询语言,扩展了 promql 的能力。因为夜莺只是转发,所以只要后端时序库支持,自然可以写。但是具体在配置告警规则的时候,前端JavaScript会做promql合法性校验,因为 metricsql 是 promql 的超集,所以有些 metricsql 可能被 JavaScript 认为不合法,会有红色波浪线,没关系,忽略即可,不影响后端逻辑。

告警恢复的时候可以在通知消息里带上恢复时的值吗?

不能。Nightingale 和 Prometheus 的告警逻辑是一样的,都不能做到。

仔细看上面的原理。Nightingale 拿着 promql 去查,没有返回数据故而报恢复,既然没有返回数据,自然也就无法拿到当前的值。