记一次Prometheus监控下的“内存飙升”事件

2023-11-17

  • 问题描述

  • 尝试定位问题

  • 错误的表达式

  • 重叠的时间序列

  • Prometheus的高可用机制

  • 联邦集群

  • 修改PromQL表达式

  • 结语

本文将介绍一次在使用Prometheus过程中由于表达式错误引发的问题、以及解决过程。

问题描述

项目上的API用Prometheus+Grafana两件套进行监控、告警和可视化,然后大家发现有一个API经常在某段时间突然内存占用飙升,持续约5分钟,之后又恢复正常状态,与此同时CPU占用却出现了突然下降的情况。内存占用见下图:
图片
因为我们设置的告警界限是80%,所以每次出现这种情况,就会触发告警,值周的小伙伴就得查日志、分析请求错误、尝试定位问题原因,但一顿操作猛如虎…,每次都是无疾而终,久而久之,大家已经麻木了,类似的问题只要一出现就直接“朕已阅”(Acknowledged),反正过不了5分钟后,内存占用恢复正常,告警就自己消失了。
直到有一天,项目上一个大佬实在看不下去了,下定决心一定要把问题的元凶给揪出来,没过多久,他成功地找到了问题的原因,容我慢慢道来,没错!我只是个打(水)酱(博)油(客)的。

尝试定位问题

首先介绍下API的运行环境:相关的API运行在Docker容器中,然后被Kubernetes托管。此外为了实现调用链的追踪,还集成了一款容器化的追踪工具Jeager,它运行在独立的容器中,但需要与API容器处于同一个Kubernetes的Pod中。
内存飙升可能的原因有哪些呢,内存泄漏?访问量过大导致请求阻塞?程序运行错误?
首先排除内存泄漏,因为内存约5分钟后恢复正常,如果发生内存泄漏,它不会这么快速而自发地释放内存;
那是不是因为访问量过大导致请求阻塞呢,在Grafana显示API内存飙升的时间段,请求量却很平稳,并没有明显的变化;
程序运行错误?也不是,因为查看对应时间段的日志,没有任何错误发生。
奇了怪了,到底是为什么呢,大多数人到这一步就放弃了,毕竟该做的都做了,实在是找不到原因也没办法,但为了找到真相,一定不能在这儿止步。
图片

错误的表达式

可能的原因都被一一排除了,还有什么值得怀疑的地方呢,内存占用率是在Grafana用PromQL计算的,有没有可能是这把尺子有问题呢,细细一检查还果真是!
计算内存占用率的表达式是这样的:

sum(
    container_memory_working_set_bytes{…} 
    / 
    container_spec_memory_limit_bytes{…} 
) by (pod_name) * 100


简单来说就是分两步:

  1. 计算容器的内存占有率:内存占用/内存配额

  2. 求和,将POD中所有容器的内存占用率相加。

用下图举例:
图片
一个POD包含API容器和Jeager容器,直接叫它们C1 C2容器,假设C1容器的内存占用率为:80/100*100=80%,C2容器的内存占用率为:90/200*100=45%,那么用上面的表达式计算得出的内存占用率为80%+45%=125%,已经超过了100%,这显然是一个不可能的数字。只是实际情况没有这么极端,从开头第一幅图来看,这个数字是100%左右,给人一种刚刚到极限的感觉。

重叠的时间序列

PromQL表达式确实有问题,但怎么会导致内存占用率的计算结果飙升呢?表达式有问题影响的是所有时间段的计算结果,任何时候的内存占用率值都是错误的,还得继续找找飙升的时间段有什么特征。
如果查看单个容器的内存使用量,会发现这个容器的时间序列(Time Serie)非常奇怪,首先一个容器的时间序列应该只有一条才对,但这里出现了两条;而且这两条时间序列发生了重叠,重叠的时间段刚好是内存飙升的时间段。
图片

前面已知错误表达式计算内存占用率的过程,错误的表达式,碰到重叠的时间序列,因为它会将POD中所有容器的内存占用率相加,所以在时间序列发生重叠时,内存占用率会翻倍!这就出现了内存占用率的突然上升,等时间序列不再重叠时,内存占用率看起来又恢复到正常水平。

看来错误的表达式+重叠的时间序列才是导致问题发生的原因。还需要继续查找导致重叠的原因。

Prometheus的高可用机制

在重叠的图片中,两条时间序列的label中,id是相同,但还有个replica的label,它们的值是不同的。这个不同的replica label实际上来自Prometheus的高可用机制。
Prometheus通常采用pull模式采集数据,Prometheus Server定期从exportor拉取数据,但如果Prometheus Server出故障,数据采集就会中断。为了减少监控系统的故障率,可以构建Prometheus的高可用集群。如下图:
图片
Cluster A和Cluster B分别监控两个不同的服务,但使用了多个Prometheus Server,如Cluster A, Prometheus -A1和Prometheus -A2组成集群同时从一个exportor采集监控数据,这样就算其中一个挂了,监控数据仍然可以被正常采集。这种结构也叫HA Pair。
HA Pair的配置举例:

global:
  ...
  external_labels:
    ...
    prometheus_replica: replica-1

scrape_configs:
    ...
    static_configs:
      - targets: ['host.docker.internal:5009']

只需在prometheus.yml中增加prometheus_replica: _replica-1/replica-2_这样的配置。
但HA Pair作为集群,自然也少不了一种Leader的选择机制,正常情况下会随机选择一个Server作为Leader,只有Leader采集的数据才会被储存到时序数据库中,如果Leader Server不可用,则会从备份Server中选择一个新的Leader Server。
图片
这就是上图一个容器对应了两条时间序列的原因,一开始使用的是replica_0 的数据,后来发生了leader的切换,便转而使用replica_2 的数据。
切换就切换,但为什么会两条时间序列会重叠呢?这又涉及到另外的机制:联邦集群(Federate)。

联邦集群

Prometheus除了可以直接采集被监控目标的数据,还可以组成分层结构,以便于在监控目标太多时实现分组采集,一个Prometheus Server负责一组的采集,最终汇总到顶层的Prometheus Server。
类似这样的结构:
图片
这就是所谓的联邦集群,它的配置举例如下:

scrape_configs:
  - job_name: 'federate'
    scrape_interval: 15s
    honor_labels: true
    metrics_path: '/federate'
    static_configs:
      - targets:
        - 'host.docker.internal:9090'
        - 'host.docker.internal:9091'

端口9090、9091是两个Prometheus Server的地址,从被监控目标采集数据,这份配置文件启动的Prometheus Server则位于顶层,进一步从9090、9091采集数据,可以看到它有一处比较特殊的配置metrics_path: '/federate',表示从两个子Server采集数据时要访问的地址。
联邦集群可以灵活地适应系统规模的变化,但它也有一个缺点,就是相对与直接采集,数据会有延迟,尤其是在目标挂掉的时候,顶层的Server无法及时地感知到。
在上述情况下,从目标挂掉的那一刻开始,子Server采集的时间序列已经没有新数据进来了,但顶层Server仍然会从子Server继续采集数据,直到5分钟后,如果仍然没有新的数据采集进来,才会认为被监控目标对应的时间序列已中断。

回头再来看前面的两条时间序列,就比较清晰了:
图片
监控系统使用了联邦集群的架构,而且底层的子Server引入了HA Pair以保证高可用,一开始replica_0负责从被监控目标采集数据,对应绿色的曲线,但时间点T1 replica_0由于未知的原因突然挂了,在大约2分钟后,即时间点T2,HA Pair机制选出了新的Leader: replica_2,它开始接替replica_0继续采集数据,对应黄色的曲线。但由于联邦集群的局限,replica_0对应的时间序列并没有立即消失,而是维持了5分钟,直到时间点T3,在这5分钟之间,由于没有采集到新的数据,就一直显示最后一次的结果,于是绿色曲线的最后5分钟是水平的直线。
所以在T2和T3之间两条曲线出现了重叠,刚好计算内存占用率的PromQL表达式错误地进行了相加地操作,导致在重叠的时间段计算结果出现了翻倍,表现出飙升之后又迅速恢复的假象。

修改PromQL表达式

知道了问题出现的来龙去脉后,开始尝试修复问题,曲线重叠是HA Pair和联邦集群的机制共同导致的结果,我们无法干预,于是从PromQL表达式入手。

  1. 修改为计算POD的内存占用,因为根据pod_name聚合后,就自动消除了replica label造成的差异:
sum(container_memory_working_set_bytes{…} by (pod_name)) 
  / 
sum(container_spec_memory_limit_bytes{…}  by (pod_name))
* 100

  1. 使用max聚合函数,找到内存占用最大的容器,也可以达到去重的效果,但这样做的前提是Pod中只有一个容器,或者我们关心的这个容器的内存占用一直大于其它容器。
max(
  container_memory_working_set_bytes{…} 
  / 
  container_spec_memory_limit_bytes{…} 
) by (pod_name) * 100


结语

“错误的表达式+重叠的时间序列”共同造成了内存飙升的假象,为了找出时间序列重叠的原因,我们了解到了Prometheus的联邦集群、高可用机制,以及这些特性的局限和特点;而针对错误的表达式的修改,则需要兼顾去除重叠时间序列的影响,为此可以通过合理使用PromQL的sum/max聚合函数来达到去重的目的。

参考资料

  • https://prometheus.io/docs/prometheus/latest/federation/#federation

  • https://github.com/timescale/promscale/blob/master/docs/high-availability/prometheus-HA.md

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

记一次Prometheus监控下的“内存飙升”事件 的相关文章

  • 数据采集才是MES系统的核心内容

    一 数据采集在MES管理系统中的应用 1 设备数据采集 MES管理系统通过与生产设备的连接 可以实时采集设备运行状态 产量 质量等相关数据 这有助于企业及时掌握设备运行状况 优化设备资源配置 提高设备利用率 2 工艺数据采集 MES管理系统
  • 如何利用CHAT做简单的总结体会?

    问CHAT 在测试过程中使用appium python自动化的优点和体会 CHAT回复 使用 Appium 配合 Python 进行自动化测试主要有以下几点优点 1 跨平台性 Appium 支持 iOS 和 Android 平台的应用自动化
  • SRC漏洞挖掘经验+技巧篇

    一 漏洞挖掘的前期 信息收集 虽然是前期 但是却是我认为最重要的一部分 很多人挖洞的时候说不知道如何入手 其实挖洞就是信息收集 常规owasp top 10 逻辑漏洞 重要的可能就是思路猥琐一点 这些漏洞的测试方法本身不是特别复杂 一般混迹
  • Python自动化操作:简单、有趣、高效!解放你的工作流程!

    今天跟大家分享一套自动化操作流程解决方案 基于 Python语言 涉及 pyautogui pyperclip pythoncom win32com 依赖包 安装命令为 pip install pyautogui pip install p
  • Jenkins 插件下载速度慢、安装失败了!我教你怎么解决!

    Jenkins部署完毕 如果不安装插件的话 那它就是一个光杆司令 啥事也做不了 所以首先要登陆管理员账号然后点击系统管理再点击右边的插件管理安装CI CD必要插件 但是问题来了 jenkins下载插件速度非常慢 而且经常提示下载插件失败 真
  • 基于java的物业管理系统设计与实现

    基于java的物业管理系统设计与实现 I 引言 A 研究背景和动机 物业管理系统是指对物业进行管理和服务的系统 该系统需要具备对物业信息 人员信息 财务信息等进行管理的能力 基于Java的物业管理系统设计与实现的研究背景和动机主要体现在以下
  • 服务器VPS是什么意思?一文了解其含义与重要性

    在今天的数字时代 服务器扮演着至关重要的角色 它们是网站 应用程序和在线业务的基石 但是 你是否听说过VPS 本文将深入探讨什么是服务器VPS 以及为什么它在今天的互联网世界中如此重要 什么是服务器VPS 服务器的基本概念 在我们深入探讨V
  • GitLab CI 实现项目A更新代码自动触发项目B更新错误码文档

    一 CI CD简介 CI CD 是持续集成 Continuous Integration 和持续交付 持续部署 Continuous Delivery Continuous Deployment 的缩写 是一种软件开发和交付的最佳实践 这两
  • 我可以找到最后一次值更改的时间戳吗

    给定一个时间序列 是否可以找到最后一个值变化的时间戳 例如 一个 cron 作业每晚运行 它首先运行 rsync 作业 然后计算目标目录的大小 实际的指标值并不是那么重要 但我想验证它实际上每天晚上都会发生变化 是否可以创建一个返回标量值以
  • 服务器中E5和I9的区别是什么,如何选择合适的配置

    随着科技的进步 服务器处理器的性能在不断攀升 其中 Intel的E5和I9系列处理器在业界具有广泛的影响力 而当我们在选择服务器的时候会有各种各样的配置让我们眼花缭乱不知道该怎么去选择 下面我跟大家分享一下E5跟I9有什么区别 方便我们在选
  • 2023下半年软考「单独划线」合格标准公布

    中国计算机技术职业资格网发布了 关于2023年度下半年计算机软件资格考试单独划线地区合格标准的通告 2023下半年软考单独划线地区合格标准各科目均为42分 01 官方通告 关于2023年度下半年计算机软件资格考试单独划线地区合格标准的通告
  • 网工内推 | 上市公司同程、科达,五险一金,年终奖,最高12k*15薪

    01 同程旅行 招聘岗位 网络工程师 职责描述 1 负责职场 门店网络规划 建设 维护 2 负责网络安全及访问控制 上网行为管理和VPN设备的日常运维 3 负责内部相关网络自动化和系统化建设 4 优化与提升网络运行质量 制定应急预案 人员培
  • 带有正则表达式的标签-普罗米修斯

    我正在尝试使用正则表达式添加新标签 名称实例是pr na01 na02 A我试图只得到pr na01 所以我这样做了 source labels meta ec2 tag Name regex target label test repla
  • 如何在 Spring Boot 应用程序中禁用执行器的拦截器调用

    我正在尝试在基于微服务的 spring boot 应用程序中实现 Prometheus 该应用程序部署在 weblogic 服务器上 作为 POC 的一部分 我已将配置包含在一场战争中 为了启用它 我设置了以下配置 应用程序属性 manag
  • Alertmanager,不同的警报规则有不同的间隔

    我正在使用alertmanager来获取prometheus指标的警报 我对不同的指标有不同的警报规则 是否可以为每个警报规则设置不同的时间间隔 例如对于metric1 我有rule1 我需要每天检查此规则间隔 对于 metric2 我有规
  • Prometheus Docker 无法以 `Template: (dynamic): parse: template: :10: undefined variable "$labels"` 启动

    我正在尝试在 Nomad 上运行 Prometheus 一切看起来都很好 但是当我添加带有模板的警报规则时annotations它失败 这是一个简单的警报规则 groups name alertmanager rules rules ale
  • 为什么prometheus Operator无法启动

    我正在尝试在全新的 k8s 集群中使用操作符创建 prometheus 我使用以下文件 我正在创建一个命名空间监控 应用这个文件 就可以正常工作了 apiVersion apps v1beta2 kind Deployment metada
  • 如何配置 prometheus-operator 从 Kubernetes 上的 cAdvisor 收集?

    我在用普罗米修斯操作员 https github com coreos prometheus operator管理一个普罗米修斯 https prometheus io 部署在我的库伯内斯 https kubernetes io 簇 该设置
  • prometheus 节点实例列表

    是否可以使用 prometheus 获取节点实例列表 我有一个节点导出器 但我没有看到这样的指标 我们应该添加一个新的运算符吗 您可以使用kube 状态指标 https github com kubernetes kube state me
  • 将 Apache Camel 执行器指标发送到 Prometheus

    我正在尝试转发 添加 Actuator Camel 指标 actuator camelroutes 将交换 交易数量等指标 发送到 Prometheus Actuator 端点 有没有办法让我配置 Camel 将这些指标添加到 Promet

随机推荐

  • Composite:组合模式

    将对象组合成树形结构以表示 部分 整体 的层次结构 组合模式使得用户对单个对象和组合对象的使用具有一致性 处理树中的每个节点时 其实不用考虑他是叶子节点还是根节点 即模糊了简单元素和复杂元素的概念 客户端可以像处理简单元素一样来处理复杂元素
  • BP神经网络识别手写数字项目解析及代码

    这两天在学习人工神经网络 用传统神经网络结构做了一个识别手写数字的小项目作为练手 点滴收获与思考 想跟大家分享一下 欢迎指教 共同进步 平常说的BP神经网络指传统的人工神经网络 相比于卷积神经网络 CNN 来说要简单些 人工神经网络具有复杂
  • 结构体中的函数指针

    C语言中的类 大家知道C 是面向对象的语言 有很多优良特性 而在C语言中 我们也可以用结构体类似的实现面向对象 成员函数 既然说了用结构体类似的实现某种类 结构体中的变量就可以看做类的变量 实现类的成员函数就要用到函数指针了 一般的函数指针
  • Siebel EAI- Web Service 常见错误汇总

    由于项目原因部分代码被模糊处理 有些问题待补充 欢迎指出错误 很多试探着理解的 研究的不够深入 问题1 Error invoking service XXX Service method XXXXX at step Invoke WebSe
  • C# 文件与Base64的相互转换

    一 转换工具 1 在线图片转Base64编码 2 BeJson在线JSON校验格式化工具 3 Base64在线加密 解密 二 Base64转文件代码 这个案例是 将已经获取到的Base64字符串 转换成文件 保存到服务器的某个文件路径下面
  • linux下rdkafka编译,Linux下librdkafka编译安装使用学习

    Kafka分为服务端和客户端 服务端集群一般称为brokers 客户端分为生产者 producer 和消费者 consumer 开发者通常用客户端从kafka生产消息或消费消息 不同的语言使用不同的客户端 具体信息参见这个页面 https
  • nginx配置非80端口

    user nobody worker processes 2 events worker connections 1024 http include mime types default type application octet str
  • leetcode刷题python之有效的括号

    class Solution def isValid self s str gt bool dict stack for i in s if i in dict top stack pop if stack else if dict i t
  • 微信小程序:消息提示框(wx.showToast)和 交互提示框(wx.showModal)

    摘要 有时需要提示框来提醒我们相应信息 以及交互提示框来让我们是否继续进行操作 一 消息提示框 1 参数介绍 消息提示框只有提示作用 不能交互 函数是wx showToast 下面列出几个主要且常用参数 2 代码 wx showToast
  • 如何把IE浏览器快速变成灰色来哀悼在汶川地震中遇难的同胞们!

    如何把IE浏览器快速变成灰色来哀悼在汶川地震中遇难的同胞们 把IE浏览器快速变成灰色只要作以下二点即可 第一点 在html页面中 在body中加入下面语句 第二点 在css控制表中 加入下面语句 html filter progid DXI
  • c++11中四种类型转换

    1 static cast 功能 完成编译器认可的隐式类型转换 格式type1 a type2 b staic cast
  • HiveQL中如何排查数据倾斜问题

    如果某个key下记录数远超其他key 在join或group的时候可能会导致某个reduce任务特别慢 本文分析下join的场景 本例子SQL如下 查询每个appid打开的次数 需要排除掉作弊的imei 说明 表cheat imei 750
  • Basic Level 1016 部分A+B (15分)

    题目 正整数 A A A的 D A D A DA 为1位整数 部分 定义为由 A
  • Unity进阶--声音管理器学习笔记

    文章目录 声音管理器 using System Collections using System Collections Generic using UnityEngine public class AudioManager MyrSing
  • 自定义注解及应用场景

    自定义注解及应用场景 深圳蜗牛学苑 课程目标 理解自定义注解概念 掌握自定义注解语法 自定义注解场景中的使用 熟练掌握自定义注解 AOP的使用方式 一 自定义注解 我们回顾一下方法的重写 会发现有 Override 我们把它称为重写的注解
  • 【2】样本不均衡问题及其解决办法

    5 损失函数 在机器学习中 可以通过修改模型中的 class weight 参数 从而调节不均衡样本的惩罚权重 5 1 LogisticRegression 逻辑回归模型 代码 lr l2 LogisticRegression penalt
  • Windows内核--子系统(3.5)

    到底什么是子系统 子系统是用户层概念 在Windows内核之上 如果想要执行类UNIX应用程序 就是POSIX子系统 如果要类似OS 2环境 就是OS 2子系统 如何能模拟出不同子系统呢 一般需要子系统用户态应用程序和相关DLL支援 对于W
  • AI模型推理(4)—— 认识ServingRuntime

    参考 Serving Runtimes KServe Documentation Website 模型推理服务化 如何基于Triton开发自己的推理引擎 知乎 GitHub triton inference server server Th
  • overleaf常见使用操作

    overleaf常见使用操作 数学符号的使用 图片的插入 表格的插入 参考文献 总结 数学符号的使用 链接 最全overleaf在线编辑数学公式以及遇到错误的解决方法 这里主要记一下集合的使用 并集 A cup B D D 1
  • 记一次Prometheus监控下的“内存飙升”事件

    问题描述 尝试定位问题 错误的表达式 重叠的时间序列 Prometheus的高可用机制 联邦集群 修改PromQL表达式 结语 本文将介绍一次在使用Prometheus过程中由于表达式错误引发的问题 以及解决过程 问题描述 项目上的API用