首页 > 其他分享 >Prometheus 新手常犯的 6 项错误,你该如何避免?

Prometheus 新手常犯的 6 项错误,你该如何避免?

时间:2023-12-25 10:02:48浏览次数:48  
标签:常犯 rate 标签 Prometheus job 新手 告警 total method

本文翻译自文章 https://promlabs.com/blog/2022/12/11/avoid-these-6-mistakes-when-getting-started-with-prometheus,感觉作者总结比较深刻,都是 Prometheus 新人们经常犯的错误,故简要翻译一下,方便和大家一起审查与自省。

错误 1:高基数炸弹

这是 Prometheus 使用者经常会犯的一个错,因为 Prometheus 时序是基于多标签的,它非常灵活,有时你想新增一个标签,从而将一个粗粒度的指标进行拆分,但切记添加的标签的值应该做到尽量收敛,不然会导致同一指标名的标签数量巨大而导致 Prometheus 严重的性能问题(OOM)。

举个例子,您有一个只包含 method 标签的时间序列 http_requests_total:

http_requests_total{method="POST"}
http_requests_total{method="GET"}
http_requests_total{method="PUT"}
http_requests_total{method="DELETE"}

这个时间序列定义没问题,因为 HTTP 的 method 类型是有限的,但有一天,您可能想根据用户 id 进行区分,类似这样:

http_requests_total{method="POST",user_id="1"}
http_requests_total{method="POST",user_id="2"}
http_requests_total{method="POST",user_id="3"}
[…更多…]
http_requests_total{method="POST",user_id="16434313"}


http_requests_total{method="GET",user_id="1"}
http_requests_total{method="GET",user_id="2"}
http_requests_total{method="GET",user_id="3"}
[…更多…]
http_requests_total{method="GET",user_id="16434313"}
[…更多…]

假设您有非常多的不同用户,所以此时就存在严重的高基数问题,这将导致 Prometheus 内存使用激增,直至 OOM。

所以请您牢记:指标上标签的每一种唯一组合都会自动创建一个对应时间序列,Prometheus 都会对其进行摄取、索引、存储和处理。


虽然针对单个标签的不同值的数量没有明确的限制,但因为不同值都是一个新的时间序列,您需要确保其数量保持在您 Prometheus 服务器容量之下(一个大型 Prometheus 单节点能够处理数几百万个时间序列),所以你在设计时间序列的标签的时候,需要确保它们的所有组合总数在您 Prometheus 服务器可以承受的范围内。


对此,有一些标签值我们要特别注意避免,例如:

  • 公网 IP 或者邮件地址。
  • HTTP 请求 Path 全路径,尤其这些路径带有动态 ID 等信息。
  • 进程ID(除非是有限集合)。

有时您想在不完全删除标签的情况下解决标签高基数的问题,那么我们就要想办法减少其值的基数。例如,对于 /api/users/739567637385/posts/28388445 的 HTTP 请求, 我们将动态信息部分使用 user_id 和 post_id 占位符统一替换,所以整个 path 可以替换为 /api/users/{user_id}/posts/{post_id} ,从而有效减少 path 标签的值数量。

错误 2:告警表达式中因聚合导致价值标签丢失

在做告警的时候,我们往往会通过聚合计算去除不关心的一些标签。例如,如果您想确定某个服务的总体错误率(跨所有标签维度)是否过高,您可以编写如下规则:

sum(rate(errors_total{job="my-job"}[5m])) > 10

这看上去没问题,但默认情况下,sum() 聚合器会去掉时序的所有标签。它不仅会删除您想要聚合的维度(如实例、错误类型等),还会删除一些比较通用的标签,这些标签对于 alertmanager 中进行告警的路由或静默是有帮助的。特别是 job 标签,因为不同 job 通常由不同的运维团队负责。因此我们应该尽可能在聚合中保留此标签:sum by(job) (rate(errors_total{job=”my-job”}[5m])) > 10

一个更好的选择是通过使用 without() 聚合修饰符替换 by() 聚合修饰符,从而显示排除不想要的标签,而尽可能保留下一些你不确定需要删除的标签:

sum without(instance, type) (rate(errors_total{job="my-job"}[5m])) > 10

这样,聚合时您没有明确指定删除的标签在 Alertmanager 中仍然可以使用,这对于告警的聚合和路由非常有用,也能帮助您更好了解警报的来源。

错误 3:使用不带任何限定范围的(裸)选择器

在编写 PromQL 查询(尤其是告警)的时候,我们需要格外小心,应该从关心的业务或服务的数据中进行查询,而不是全局范围。因为不同的业务可能使用了相同的指标名称,它们甚至表达了不同的含义,随着时间的推移,相同指标名称的服务会越来越多,这可能会完全影响您的告警规则或者仪表盘数据。

为避免不小心从不相关的任务或者服务中查询数据,我们一般使用 job 标签来限定选择器的范围,确保其查询的数据都是您关心的业务或服务。

例如,以下查询就是一个不安全的“裸”选择器,它可能会从您不期望的其他 job 中选择具有相同指标名的数据:

rate(errors_total[5m]) > 10

我们可以使用 {job=”my-job”} 的选择器从而将指标限定在 my-job 服务范围:

rate(errors_total{job="my-job"}[5m]) > 10

这显然是一个更安全的方式,它可以有效避免从无关服务中查询数据,对您告警产生干扰,也能大大提升查询性能。

错误 4:告警规则没有使用 for 字段

for 字段主要用于告警规则评估,它允许您能够指定任意告警需要在连续的规则评估周期中出现多长时间才从 pending 状态变为 firing。大多数告警规则可能我们可以忽略该字段,只需要两个评估周期即可触发告警,但有时,我们为了排除抖动的干扰,比如一些 CPU 使用率,或者某个节点因为一两次抓取异常就判定 down 了。

考虑一个警报规则,它使用 up 指标来查找无法成功抓取的目标,并省略了可选的 for 修饰符:

alert: InstanceDown
expr: up == 0

一次失败的抓取(很容易发生)将导致触发此规则。通常你希望让你的警报规则不那么容易触发,并至少等待几分钟,看看问题是否真的存在,然后再触发通知:

alert: InstanceDown
expr: up == 0
for: 5m  # 一个实例只有真的挂掉或者无法访问长达 5 分钟才创建告警信息。

不带 for 针对一些内置的带有平均数计算的查询表达式也同样有问题,例如表示高错误率的告警:

alert: HighErrorRate
expr: rate(my_errors_total{job="my-job"}[5m]) > 10

这个规则将在第一次查询到最近 5m 中该错误数的平均值 > 10 就立即创建告警,虽然 5m 的平均周期能够带来一定的稳健性,但是由于 Promtheus rate() 特性,我们考虑一下,一个完全新的服务或者一段时间未收集到数据会发生什么:

  • 5 分钟的 rate() 窗口只会考虑一些最近的样本,实际上并不会对五分钟的数据进行平均。
  • 时间序列甚至根本还没五分钟数据,该规则也可能会立即创建告警。

因此我们可以使用 for 修饰符来解决此问题:

alert: HighErrorRate
expr: rate(my_errors_total{job="my-job"}[5m]) > 10
for: 5m

几乎大多数的告警规则都可以添加此参数,从而使使警报规则更加稳健。但请记住,这也会导致警报的反应时间变慢,因此找到这个平衡很重要。

错误 5:rate() 函数窗口时间太短

在太短的时间窗口内计算速率时,您是否曾对间隙或完全空的图表感到沮丧,例如 rate(my_counter[1m])?rate() 和其他 PromQL 函数(如 increase()、irate()、deriv())告诉您时间序列在给定时间窗口内上升或下降的速度,在输入时间窗口下至少需要两个样本,从而能够告诉你这两个样本之间的序列是如何发展的。如果将时间窗口设置得太小,则在该窗口下可能只有一个或零个样本,在这种情况下,输出结果为空。

例如,如果您采用 20s 的时间窗口对一个 15s 抓取间隔的指标进行 rate(),那么在这 20 秒时间窗口内很可能不会涵盖两个样本,因此您会得到一个与实际结果差异很大的比率:

Prometheus 新手常犯的 6 项错误,你该如何避免?_重置

采取极端的做法:如果将 rate 窗口缩小到 16s,当两个相距 15s 的点恰好落在任意对齐的 16s 窗口中时,您只会偶尔得到一个输出点:

Prometheus 新手常犯的 6 项错误,你该如何避免?_重置_02

因此,您需要选择一个足够大的时间窗口——不仅仅是抓取间隔的 2 倍,因为您还需要面对偶尔抓取失败和不幸的窗口对齐。所以通常我们选择 rate 窗口大小至少为抓取间隔的 4 倍:

Prometheus 新手常犯的 6 项错误,你该如何避免?_时间序列_03

提示:使用 Grafana 时,可以使用 $__rate_interval 模板变量自动为您选择一个安全间隔。

错误 6:rate() 相关函数用错了指标类型

查询函数与指标类型用错的典型例子有:

rate() 函数用在 gauge 类型指标

rate()、irate() 和 increase() 函数被设计成为仅适用于 counter 类型指标。counter 类型是追踪累计计数的指标,这些计数只会上升(永远不会下降),除了在追踪过程中偶尔因为重启而重置为 0。为了在 rate 计算中尽可能消除计数器重置的影响,这些函数尝试将提供的时间窗口内样本的值的任何减小都解释为重置并对其进行补偿。这种计数器的重置检测和补偿意味着您只能从这些函数中获得正数的结果(或 0)。

如果你不小心传入了一个可以自然上升和下降的指标(比如内存使用量),PromQL 将无法判断这个错误,而只会返回一个不正确的输出值。这是因为每次您的仪表指标下降时,rate() 都会将其理解为计数器重置并且会错误地“纠正”它。

deriv() 函数用在 counter 类型指标

您可以认为 deriv() 函数大致等同于 rate(),但它作用于 gauge 类型。deriv() 告诉您在输入时间窗口内 gauge 类型指标每秒上升或下降的速度。虽然并不常见,但这里与 rate() 相同的陷阱可能会给你带来另外的困扰:因为 deriv() 函数没有实现任何围绕 counter 类型重置的逻辑(gauge 没有这些),试图使用 deriv() 计算一个在提供的窗口下有重置的 counter 的类型指标,就会得到一个不正确的结果,有时甚至是一个负数。

如何避免传入错误类型的指标?

由于 PromQL 无法自动检测这种不正确的用法,所以您在使用这些函数时必须格外小心。我们除了经验和已有知识外,还可以依赖一些开源项目,例如 PromLens 查询构建器这样的工具来辅助您检测是否传了错误的指标类型:

Prometheus 新手常犯的 6 项错误,你该如何避免?_重置_04

结论

以上 6 点就是一些刚开始使用 Prometheus 的朋友经常会犯的错误,希望这些技巧对您使用 Prometheus 的有所帮助!

标签:常犯,rate,标签,Prometheus,job,新手,告警,total,method
From: https://blog.51cto.com/u_15576159/8963563

相关文章

  • 【新手升级必看】从 TiDB v6.5升级到 v7.5 的实践步骤
    作者:春风十里TiDB7.5已发布了支持并行运行多个ADDINDEX语句并且兼容MySQL8.0.是时候测试一下了,要测试必须先升级。那么下面就是按官方文档指示升级的过程。升级说明:本次升级测试为测试环境,单机部署。操作系统版本CentOSLinuxrelease7.8.2003(Core)原tidb版本6.5.......
  • day20 企业级监控大盘配置管理-Prometheus Operator部署管理 (7.11.1-7.12)
    一、企业级监控大盘配置管理(上)1、Grafana简述Grafana是一个开源的度量分析与可视化工具。提供查询、可视化、报警和指标展示等功能,能灵活创建图表、仪表盘等可视化界面。主要功能:可视化:提供多种可选择的不同类型的图形,能够灵活绘制不同样式,且还提供很多插件。动态仪表......
  • ctf.show新手必刷_菜狗杯 杂项签到/损坏的压缩包/谜之栅栏/你会数数吗/你会异或吗
    杂项签到下完压缩包打开获得一张糊糊的图片丢进010editor看一下,既然是签到,会不会直接就藏在里面呢..ctrl+F搜下ctf,找到flag:(小提示:记得把查找的对象从HexBytes换成Text)损坏的压缩包打开压缩包,发现打不开,确实是损坏的压缩包。损坏的话可能是格式不太对,或者格式对了但是内......
  • Android新手程序员提升技术最快的3个方法,你知道吗?
    前言对于刚刚进入职场的1-3年的程序员来说,首要任务无疑是全身心地投入到技术开发工作中,用最专业的技术知识和熟练度来开展工作。这项任务需要你花费大量的时间和精力去学习、探索和实践。只有充分掌握了当前技术的使用方法和功能,以及行业内的趋势和动态,你才能够在这个领域中不断进......
  • jmeter +prometheus+grafana做性能测试监控
    1,环境搭建--->mac系统打开终端terminal,复制并粘贴以下命令:/bin/bash-c"$(curl-fsSLhttps://raw.githubusercontent.com/Homebrew/install/master/install.sh)然后按回车brew-version查看版本 2,安装prometheus方法一:brewinstallprometheus 安装完毕后,通过pwd查看......
  • 新手友好、轻量级的C#/.NET万能工具库
    前言今天分享一个基于MITLicense协议开源、免费、新手友好、轻量级的C#/.NET万能工具库、帮助类库(支持.NET和.NETCore,可以帮助开发者们减少常见重复功能方法查找,提高开发工作效率):Masuit.Tools。项目官方介绍全龄段友好的C#万能工具库,码数吐司库,包含一些常用的操作类,大都是......
  • prometheus告警记录——grafana模板
    grafana面板{"annotations":{"list":[{"builtIn":1,"datasource":{"type":"datasource","uid":"grafana"},......
  • Cloudeye对接Prometheus实现华为云全方位监控
    本文分享自华为云社区《Cloudeye对接Prometheus实现华为云全方位监控》,作者:可以交个朋友。一、背景云眼系统Cloudeye服务为我们提供了针对弹性云服务器、宽带等资源的立体化监控平台。帮助我们全面了解华为云上的资源使用情况、业务的运行状况。将华为云Cloudeye服务接入prom......
  • 绘画新手入门素描基础技法,小白从零级到专业四级教学
    一、教程描述本套教程是关于素描绘画的,教程内容全面系统,讲解也是很专业的,不仅教你画好陶罐、苹果、人像、五官、玻璃制品等具体事物,同时也会介绍绘画起源与简史,艺术价值与意义,绘画思维与技法等相关知识。本套绘画教程,大小18.02G,共有102个文件。二、教程目录第01章-绘画起源与简史(共......
  • 如何使用 Helm 在 K8s 上集成 Prometheus 和 Grafana|Part 1
    本系列将分成三个部分,您将学习如何使用Helm在Kubernetes上集成Prometheus和Grafana,以及如何在Grafana上创建一个简单的控制面板。Prometheus和Grafana是Kubernetes最受欢迎的两种开源监控工具。学习如何使用Helm集成这两个工具,使您能够轻松监控Kubernetes集群并......