背景
随着云原生和高动静服务端的倒退,在运维畛域,以 Prometheus 为代表的古代工夫序列存储正在减速代替以 Zabbix 为代表的传统监控零碎。运维畛域在享受工夫序列技术倒退红利的同时,也面临工夫序列治理思路上的转变和监控零碎理论利用的上一些难点 —— nodata 告警便是其中之一。nodata 告警是传统监控零碎的必备性能,但却缺席了简直所有古代工夫序列存储实际,这给运维监控带了诸多缺点。本文尝试剖析其中起因,并给出一些可能的解决办法。
nodata 告警触发器的特殊性与必要性
nodata 告警触发器(Trigger
)与一般告警触发器相比具备原生的特殊性。一般告警触发器的作用是对一组监控指标(Metric
)的过滤,通常是基于数值大小的过滤。
运维监控场景下,产生 nodata 告警最大的可能性是监控零碎自身的生效,比方采集点生效或采集对象生效,在咱们的实际中,服务器意外下线、磁盘故障、服务解体等都会导致 nodata 告警;另外还有一类监控指标,这类指标以 nodata 为『失常状态』,如 5xx code 产生的速率,在没有 5xx code 产生时,尽管咱们心愿指标的数值为 0 (而不是 nodata) ,但在实践中往往很难保障,对于这类指标有效性的保障,咱们会在其余文章中具体阐明。
nodata 告警触发器的难点之一在于选集 U 的获取。在高动静的服务端环境中,往往很难失去『全副服务器汇合』、『全副 IP 地址汇合』、『全副 Pod 汇合』、『某服务全副运行实例汇合』这样的选集。所以,在数值型的监控采集之外,必须建设更加结构化的信息组织形式,并配以主动、半自动与人工相结合的信息保护办法。如果在结构化信息中很难不便精确地获取『全副某某汇合』这样的信息,就无奈制作真正无效地 nodata 告警触发器。
nodata 告警触发器的另一个难点是计算的开销大。一般告警触发器对指标的数值过滤,能够通过『带条件的查问』做到,这实质上是将告警计算的开销一次性卸载到工夫序列存储系统中,而古代的工夫序列存储系统个别都反对这样做。由上文对 nodata 告警触发器的定义能够失去,nodata 的计算必须在数值过滤之前,也就是说 nodata 告警计算的计算对象是全量的监控指标,对全量监控指标求补集自身是一个开销微小的计算。另外选集 U 并不存在于工夫序列存储中(否则 nodata 告警就失去了客观性),把选集 U 带入 nodata 告警计算可会给工夫序列存储带来额定的传输与计算压力。
尽管有诸多困难,但 nodata 告警的重要性显而易见。如果没有 nodata 告警,监控指标的生效是静默的,监控零碎自身的有效性无奈失去保障。对于云原生的服务端环境,监控对象的动态化水平更高,尽管能够制作更加宏观的监控指标(如某类 Pod 的总实例数),但 nodata 告警能够帮忙咱们获悉更加宏观的服务端运行工况。
在 OpsMind 的实际中,咱们应用 CMDB 和经典的 CMDB 办法来取得选集 U ,并革新 Prometheus ,将 nodata 计算卸载到存储层。下文联合咱们的实际,并尽可能剥离咱们非凡的业务场景,以 Prometheus 为例,介绍几个绝对通用的 nodata 告警触发器的实现思路。
繁多维度的 nodata
繁多维度的 nodata 是最常见的 nodata 告警触发器,Zabbix 等传统监控零碎提供的也是这类 nodata 性能。以服务器 Load 监控为例
在咱们的实际中,为了将 nodata 的补集运算卸载到 Prometheus,咱们将 CMDB 作为一个监控点,由 Prometheus 向 CMDB 拉取选集 H ,具体的指标相似于
nodata_hosts{host="h1", nodata="True"} 1
nodata_hosts{host="h2", nodata="True"} 1
nodata_hosts{host="h3", nodata="True"} 1
...
同时,假如 Load 监控指标 L 相似于
host_cpu_load5{host="h1"} 42
host_cpu_load5{host="h2"} 43
host_cpu_load5{host="h3"} 44
...
咱们针对 L 生成如下告警触发器
host_cpu_load5{host=~"h.*"} > 42
则卸载 nodata 之后的运算可示意为
host_cpu_load5{host=~"h.*"} or on(host) nodata_hosts{host=~"h.*"} * 1/0 > 42
此告警触发器能够生成如下的告警信息
host_cpu_load5{host="h2"} 43
host_cpu_load5{host="h3"} 44
host_cpu_load5{host="hx", nodata="True"} +inf
这里有如下几个关键点
- 将 CMDB 中的结构化信息转储到 Prometheus
- 应用
or
运算符做补集运算 on()
的 label 为 nodata 的繁多维度- 一般指标与 nodata 指标在 nodata 维度上的查问条件统一
or
之后的表达式通过* 1/0
转为+inf
以保障数值条件成立
咱们通过将选集 转为监控指标,并通过 or
运算符做补集运算实现了繁多维度的 nodata 告警触发器。
多维度正交的 nodata
多维度正交 nodata 也是运维监控场景中的常见需要。假如有 n 台服务,每台服务器上都运行雷同的一组 m 个服务实例,那么对于服务的监控指标,就须要在服务器和服务两个维度上做 nodata 计算。问题形容如下
与单维度相似,咱们转储服务的选集指标
nodata_services{service="s1", nodata="True"} 1
nodata_services{service="s2", nodata="True"} 1
nodata_services{service="s3", nodata="True"} 1
...
假如监控指标 Q 相似于
service_qps{host="h1", service="s1"} 42
service_qps{host="h1", service="s2"} 43
service_qps{host="h2", service="s1"} 44
...
则对于监控指标 Q 的一个告警触发器相似于
service_qps{host=~"h.*", service=~"s.*"} > 42
卸载 nodata 计算之后的告警触发器
service_qps{host=~"h.*", service=~"s.*"} or on(host, service) absent(nodata_hosts{host=~"h.*"}, nodata_services{service=~"s.*"}) * 1/0 > 42
此告警触发器能够生成如下告警信息
service_qps{host="h1", service="s2"} 43
service_qps{host="h2", service="s1"} 44
service_qps{host="hx", service="s1", nodata="True"} +inf
service_qps{host="h1", service="sx", nodata="True"} +inf
...
除了与繁多维度 nodata 相似的关键点之外,这里还有如下几个关键点:
- 重写 Prometheus 的
absent
函数反对多vector
的正交计算 on()
的 label 为多个 nodata 的计算维度
咱们通过与繁多维度 nodata 相似的手法实现了反对多维度正交的 nodata 告警触发器。
更个别的多维度 nodata
多维度 nodata 更个别的表述是多维度之间无奈造成正交关系的状况。这些状况较难解决,须要 CMDB 与工夫序列存储建设较亲密的分割(而非简略的数据转储),但如果能够解决切当,能够大大加强监控零碎的能力。
针对这个监控指标的一个告警触发器
service_qps{host=-"h1,h2,h3"service=-"s1,s2"} > 42
留神这里咱们扩大了 PromQL 的语法,反对『列表匹配』=-
,对于这个语法带来的性能和性能的优化本文暂不赘述。
为了对 Q 具备这类简单多维度关系的指标,咱们须要在 CMDB 中建设服务器与服务实例的关系表
通过 CMDB 中的关系表,将 nodata 卸载后的告警触发器为
service_qps{host=-"h1[0,1],h2[2],h3[3]"service=-"s1[0,2,3],s2[1,3]"} > 42
这里咱们扩大了列表匹配的语法,反对 “nodata key” [0,1]
,示意某个列表项在全集中的 ID。Promethues 查问时会针对每个 label 计录缺失列表项的 nodata key,并将多个 label 记录下来的 nodata key 求并集。
结语
本文剖析了古代工夫序列治理计划中 nodata 的特殊性与必要性,并以 Prometheus 为例尝试给出几个解决方案。能够看到,古代工夫序列治理计划中的 nodata 解决是十分复杂的,咱们认为这和云原生环境下其余的监控难题一样具备原生复杂性,这只是云原生给运维带来的诸多根本性挑战的外在表现形式,这些挑战须要系统性地剖析和解决。OpsMind 为应答云原生的挑战做了大量的技术研判和产品包装,咱们将在其余文章中与大家陆续分享。