prometheus可以配置告警最后发给alertmanager。但是有些坑的地方需要注意。
下面就是一个标准的表达式的例子,我们接下来说说坑点。
groups:
- name: example
rules:
- alert: HighRequestLatency
expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5
for: 10m
labels:
severity: page
annotations:
summary: High request latency
周期计算不准
表达式里填写的是当时计算的表达式,这里一般就是做条件判断,上面的条件判断是单点值的,所以可以直接写,如果是分钟的那就有点问题了。例如下面
sum_over_time(job:request_latency_seconds:mean5m{job="myjob"}[5m]) > 0.5
我们如果写这样的表达式,肯定是想表达一些指标的一个变化,例如30s拉取一次数据,如果我们想表达1m的时候,其实想表达的是2次采集的结果。这么看写1m其实没什么问题,但是当执行这个表达式的时候,你会发现,这个表达式是至多2个点,大部分都是一个点的结果。
他的计算的区间是从当前时间算的,30s一次,如果不是正好在间隔周期里查数据,那么只会查询到1条,时间正好有一定的错位。如果如果我们想稳稳的查出正好两个点就需要拉长查询的周期,例如75s。1分半,3个点至少需要30s,选取一个比2个周期长,三个周期短的数据只要不出现抓取失败的情况,每次计算都会有2个点的值参与运算。
无法处理非连续数据
我们告警常见的几种表达,一个时间段内总共出现多少次。这个表达力包含一个特征就是时间段的一个产物,例如20s内cpu使用率达到5次80%。连续出现,不连续出现都是满足这种情况的。如果仔细查看了所有的prometheus的表达式,你会发现似乎没有这种表达。
解决方案是做计算的转化。通过预计算,把达到某种条件的值转化为新的指标,让那个指标的值只有1,只有达到某种条件才会产生新的指标,最后只要计算sum_over_time计算新产生的指标就可以做到我们的表达。例如
cpu使用率 | 80 | 10 | 80 |
转化cpu超过60 | 1 | 1 |
我们把指标做了转化以后,对转化值做统计就可以了。
告警的数据比真实产生的多
我们写了超过80%的告警,结果收到多条告警,但是真实超过80%的只有一个时间点。
这是另外一个参数影响的
evaluation_interval
这个是触发告警检测的时间,默认为1m。
假如我们的指标是5m被拉取一次。
检测根据evaluation_interval 1m一次,所以在值被更新前,我们一直用的旧值来进行多次判断,造成了1m一次,同一个指标被告警了4次。
持续触发不准确
在表达式里可以通过写for的值,来表示告警的持续时间。
我们一般设置这个值,其实想表达的是这个情况被持续一段时间,并不是每次触发都告警。
prometheus检测的流程是这样的,在evaluation_interval的设置下进行多次轮训检测,如果满足条件,就会记录,等下次检测是否还满足,如果满足就检测for的时间设置,只要没超过就继续检测,超过的话就告警。
这个就和间隔有了很大的关系。
如果10秒采集一次,1m检测一次,那么其实是1m内检测表达式的连续性,就是每个1m中执行,忽略了中间其他10s采集的值,可能只有第一次和第六次满足,中间都不满足,这样也会导致继续判断告警,而不是直接中断掉。
如果2m采集一次,那么for的时间必须不能短于2m,否则只要连续1次就告警了,没有什么持续多久的情况。