写点什么

AlertManager 告警发送频率探究

发布于: 5 小时前
AlertManager 告警发送频率探究

我一贯坚持一个观点:一图胜千言,晦涩冗长的技术文字可以用精致的图片完美地展现。据说人脑对图像的加工记忆能力大约是文字的 1000 倍,甭管它是真是假,我们对图片的敏感度确实是远大于文字的,我们的脑袋可以长久地记住图片所包含的内容,却对大片的文字读过即忘。


以后的文章我们都按照如下习惯:一篇文章围绕一张图,讲述一个主题。



说到云原生监控,就不得不提 Prometheus 所提供的监控告警功能和它的搭档 AlertManager。这张图涉及到了这两大主角。关于它俩之间的暧昧关系,我们另起一篇细聊。


本文尝试说清楚以下几个与 alert 相关的问题:


  • alert 和 alert notification 各自长什么样子

  • alert 如何触发以及 Prometheus 发送 alert 的频率是什么

  • AlertManager 发送 notification 的频率是什么

alert 和 alert notification 初探

我是个严谨的人,为了防止后文中的描述引起大家的误解,先说下这两个词。


按 Prometheus 的官网表述,Prometheus 的告警输出叫 alert。AlertMangaer 的输出是 alert notification。


下面是 alert 的数据示例。我们先来看下 alert 的长相,好有个直观的印象。


{  "status": "success",  "data": {    "alerts": [      {        "labels": {          "alertname": "High Pod Memory",          "severity": "slack"        },        "annotations": {          "summary": "High Memory Usage (instance )"        },        "state": "firing",        "activeAt": "2021-06-07T07:41:32.056441315Z",        "value": "2.117730304e+10"      }    ]  }}
复制代码


而于此对应的,观察由 Alert Manager 所产生的 alert notification,它的体量就臃肿了不少。


{    "receiver": "web\\.hook",    "status": "firing",    "alerts": [        {            "status": "firing",            "labels": {                "alertname": "High Pod Memory",                "severity": "slack"            },            "annotations": {                "description": "alert Demo\n VALUE = 9.82222848e+09\n LABELS = map[]",                "summary": "High Memory Usage (instance )"            },            "startsAt": "2021-06-10T14:11:02.056441315Z",            "endsAt": "0001-01-01T00:00:00Z",            "generatorURL": "http://gtsec-prometheus-775474659f-dtw8w:9090/graph?g0.expr=sum%28container_memory_usage_bytes%29+%3E+1\u0026g0.tab=1",            "fingerprint": "f74798f72524fe89"        }    ],    "groupLabels": {        "alertname": "High Pod Memory"    },    "commonLabels": {        "alertname": "High Pod Memory",        "severity": "slack"    },    "commonAnnotations": {        "description": "alert Demo\n VALUE = 9.82222848e+09\n LABELS = map[]",        "summary": "High Memory Usage (instance )"    },    "externalURL": "http://gtsec-alertmanager-f4449f994-9nnsp:9093",    "version": "4",    "groupKey": "{}:{alertname=\"HighPodMemory\"}",    "truncatedAlerts": 0}
复制代码


关于 alert 和 notification 内容详解,后面的文章会继续为您奉上。

alert 的触发及发送

我们回到这张精美的图,首先很容易看出来 Prometheus 负责产生 alert。现在的问题是它是如何触发的呢?


Prom 是一个数据收集和分发中枢。“数据收集”意味着它如大海一样海纳百川,汇聚了各类监控数据源。用技术圈时髦的话说,这叫“大数据”。有了大数据了,下一步就可以“数据挖掘”了。


Prom 收集到的各类监控数据叫 metric。它包含了对某一个监控对象的持续监控数据,每个监测值都配以精确的监测时间点。metric 里面还包含其它的数据,这个以后再聊。下图是一个 metric 的示例。


{  "status": "success",  "data": {    "resultType": "matrix",    "result": [      {        "metric": {          "__name__": "kube_node_role",          "instance": "kube-state-metrics.kube-system.svc.cluster.local:8080",          "job": "kube-state-metrics",          "node": "bucksware",          "role": "master"        },        "values": [          [            1610261430.781,   // timestamp            "1"               // 监测值          ],          [            1610261490.781,            "1"          ]        ]      }    ]  }}
复制代码


这些 metric 保存在 Prom 自带的时序 DB 里。与此同时,Prom 还贴心地提供了 PromQL (Prometheus Query Language) 以供大家来查询保存在时序 DB 里的数据。当然查询的时候,还可以夹杂着各种可以让 Prom 发疯的骚操作在里面,比如对查询出来的数值做数学运算,对一堆数值做差值处理。


下面就是一个利用 PromQL 查询数据的简单示例。


curl 'http://gtsec-prom-service.greater-security.svc:8080/api/v1/query_range?query=kube_pod_info&start=2020-11-26T01:10:30.781Z&end=2020-11-26T01:12:30.781Z&step=60s'
复制代码


下面是另外一个稍微复杂一点的示例,这个示例里的 PromQL 用到了 sum()和数学计算。


curl 'http://gtsec-prom-service.greater-security.svc:8080/api/v1/query?query=%28sum%28container_memory_working_set_bytes%29%20BY%20%28instance%2C%20name%29%20%2F%20sum%28container_spec_memory_limit_bytes%20%3E%200%29%20BY%20%28instance%2C%20name%29%20%2A%20100%29'
复制代码


HTTP 请求的参数 query 所携带的 value 为 PromQL,被做了 URI Component encode。将其 decode 后为:


(sum(container_memory_working_set_bytes) BY (instance, name) / sum(container_spec_memory_limit_bytes > 0) BY (instance, name) * 100)


说完了 metric 以及 PromQL,该到我们的这节的主角登场了。它就是 rule。rule 长下面这个样子,它包含了alert, expr, for等关键信息。这里我们先把关注点放到expr身上。


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
复制代码


所谓 expr,就是 expression 了。这里就会用到我们上面提到的 PromQL 了。当它的评估值为 true 时,就表示可以发送一个 alert 了,但别急,Prom 是一个办事稳重的人,不会有点风吹草动就惊动别人。它会等待一段时间再观察看看是不是这个表达式还是为 true,如果还是的话,那就是时候发出 alert 了。这个等待的时间由for控制,相应地,这样的变化也体现在 alert 的状态变化上:由 pending 变成 firing。


如图中所示,Prom 默认每隔 60s 会评估一次所有的 rule,当然这个时间可以通过evaluation_interval自行控制。并每隔 60s 向 AlertManager 发送一次 alert。前者是因为 Prom 还有其它的事情要干,总不能一直做数据挖掘,就算 Prom 吃得消,机器的资源也吃不消。后者嘛,我猜是因为社交礼仪。


当 Prom 决定发出 alert 时,alert 的状态会变成 firing,而当它决定解除危机时状态会变成 in-active。这里有一个知识点,Prom 会保持这个 in-active 状态 15 分钟。在这 15 分钟内,它会依然每隔 60s 发送一次 alert 给 Alert Manager,当然这些 alert 的状态已经修改为 in-active 了。实际上,Prom 一共会发 16 次 in-active 状态的 alert。为什么呢?因为第 0 分钟的时候,也会发送一次。

alert notification 的发送

现在让我们把注意力转移到 Alert Manager 这边。


话说 Alert Manager 从 Prom 那边源源不断地收到 Alert 后,对于如何处理这些 alert,以何种方式,何种频率优雅地通过 notification 方式发送出去,它有很多种选择。


首先通过 Grouping 的机制,比如 group by alert name,把从 Prom 发过来的各种各样的 alert 分门别类码放好。我们可以把每个 Group 看成是一个 Queue。图中米黄色框就表示一个 Group,而红色箭头表示每隔一段时间会收到 alert。


结合上一节所述 Prom 每隔 60s 发送一次 alert 给 Alert Manager,可以大致认为这个 Queue 每隔 60s 可能会有新的 alert 插入,但也可能没有。


其次当 alert 进入了 Queue 之后,除了其它诸如去重、抑制等控制措施外,当它决定要发送 notification 出去时,也是有讲究的。这里用到了三个关键的参数group_waitgroup_intervalrepeat_interval


group_wait 默认取值是 30s,它的作用是告诉 Alert Manager,当一个 Group 里面有新的 alert,且 Alert Manager 决定要发 notification 时,要等多久发送第一个 notification,也叫初始 notification。这个 Group 也会被标记成已经发送过初始 notification 的 Group 了。


group_interval 的默认取值是 5m,Alert Manager 会每隔 5m 巡视一下 Group,看看对于这个 Group,如果初始 notification 已经发送了,但又来了新的 alert 塞到它里面,则需要再次发送 notification。比如对于前文的 High Pod Memory 这个 alert, 如果 Pod memory 使用量一直很高,那就意味着 Prom 每隔 1-2 分钟会送一个新的 High Pod Memory alert 进来。于是每隔 5 分钟, 如果没有其它限制因素的话,Alert Manager 会批次处理一次这些新入的 alert,发送 alert notification。也就是说对于已经发送过初始 notification 的 Group,即使有新的 alert 进来也得等 5m 才能再次发送 alert notification,而不是 30s。


repeat_interval 顾名思义,就是重复发送间隔,但它只针对依旧是 firing 状态的 alert。默认是 4 个小时,就是说每隔 4 个小时再发送一次 alert notfication。


不得不说,这 3 个参数,在 alert notification 发送频率方面拿捏得死死的。


【大鱼安全团队出品】- 大鱼安全:国内首个 SaaS 版云原生安全平台 https://www.greatersecurity.com.cn/

发布于: 5 小时前阅读数: 11
用户头像

还未添加个人签名 2021.07.14 加入

还未添加个人简介

评论

发布
暂无评论
AlertManager 告警发送频率探究