如何解决Prometheus的数据回填问题

news2024/12/29 19:12:27

去年10月底的时候,我们的监控系统因为一个偶然的问题,出乎意料地发生了重大的故障,这次故障暴露了当前监控系统存在的一下重大隐患。

故障背景及现象

我们的监控系统基于Thanos构建,基本架构如下(箭头表示数据流向):

分布在各个区域的prometheus负责指标采集并通过远程写将数据发送给运维中心部署的Thanos套件,Thanos套件负责将指标数据持久化进对象存储并提供统一视图及统一告警能力。

某一次因为网络问题,A区域的prometheus与Thanos之间的发生了长时间中断,当网络重新连接时,A区域大量涌入的数据造成Thanos的distributor与receive组件反复崩溃重启CrashLoopBackOff,引发所有区域的prometheus远程写失败,整个系统处于瘫痪状态。

此时,prometheus端大量发生如下报错:

ts=2022-10-30T16:12:58.897Z caller=dedupe.go:112 component=remote level=error remote_name=da5e4a url=* msg="non-recoverable error" count=3 exemplarCount=0 
err="server returned HTTP status 409 Conflict: 2 errors: forwarding request to endpoint thanos-prod-receive-2.thanos-prod-receive-headless.thanos-prod.svc.cluster.local:10901: rpc error: code = AlreadyExists desc = store locally for endpoint thanos-prod-receive-2.thanos-prod-receive-headless.thanos-prod.svc.cluster.local:10901: conflict; forwarding request to endpoint thanos-prod-receive-0.thanos-prod-receive-headless.thanos-prod.svc.cluster.local:10901: rpc error: code = AlreadyExists desc = store locally for endpoint thanos-prod-receive-0.thanos-prod-receive-headless.thanos-prod.svc.cluster.local:10901: conflict"

Thanos receive大量发生如下报错:

level=warn ts=2022-10-30T16:12:58.492368127Z caller=writer.go:184 component=receive component=receive-writer tenant=default-tenant 
msg="Error on ingesting samples that are too old or are too far into the future" numDropped=3

问题分析

该问题的产生源于如下两个事实和两条限制。

两个事实:

  1. prometheus的remote write失败时具有重传机制,remote write并发数会根据数据量及传输情况自动调整;

  1. Thanos基于prometheus源代码构建,receive组件的本地tsdb与prometheus的tsdb具有相同的特性;

旧版Prometheus的TSDB具有如下两条写入限制:

  1. 同一序列:无法摄入时序早于当前最新样本的样本,称为out of order samples;

  1. 所有序列:无法摄入时序早于当前最新样本1h的样本,称为too old samples(假定storage.tsdb.min-block-duration为默认值2h);

限制1容易理解,可以认为是旧版“时序”数据库TSDB的特点,即数据必须按时间顺序写入。限制2原理可以通过这幅图来表达:

图中每个方块代表含有不同序列组成的数据块(block),虚线表示暂存于内存中尚未刷新到磁盘中的数据,实线表示已经刷新到磁盘的数据。当storage.tsdb.min-block-duration为默认值2h,TSDB并不会在内存中数据时间跨度达到2h时立即落盘,而是再等待1h才会落盘,防止数据切分处产生问题。而数据块一旦落盘后,就不可写入,因为存在限制2。

这两条限制在一些应用场景下会造成较为严重的问题,例如:

  • 在多Prometheus的场景下,如果某个Prometheus因网络故障与Thanos断开连接超过一个小时,而这段时间内其他Prometheus的样本是被Thanos成功摄入的,那么当该Prometheus 网络恢复正常并试图重新推送旧样本时,这些样本将被Thanos拒绝,指标将永久丢失;

  • 使用消息队列(如kafka)的复杂指标传递架构可能会由于拥塞、随机分片或数据预处理产生延迟,进而导致指标无法写入而丢失;

  • 一些指标生产者可能需要聚合过去数小时的数据,然后发送带有旧时间戳的聚合结果,这样的聚合结果无法被TSDB接收;

  • 通过长时间断开网络来节省电量的物联网设备无法可靠地推送指标;

故障回溯

了解了上述一些技术背景后,现在我们来回溯本次故障发生的过程。

  1. Prometheus A网络恢复后,开始重传中断期间发送失败的数据,且由于数据量较大,Prometheus自动增大了远程写的并发数;

  1. 由于数据too old,Thanos拒绝了这些数据,并返回4XX报错;

  1. Prometheus A接收到4XX报错,认为发送失败但远端并无问题,所以再次重传;

  1. 上述过程反复重复,造成Thanos distributor及receive大量报错并发生拥塞,liveness健康检查失败,并造成pod反复重启;

  1. 由于Thanos distributor及receive的反复崩溃重启,造成中心的Thanos系统无法正常接收各个区域Prometheus的远程写,因为所有区域的Prometheus均进行了重写,Thanos端压力进一步增加,引起雪崩;

Prometheus端的反复重写造成的系统网络流量、内存、CPU负载的急剧升高,引发的OOM问题,也是本次故障的重要表征:

故障的临时解决方案

为了解决尽快解决这个问题,当时采取了两个不恰当的临时措施:

  1. 关闭Thanos receive distributor前的负载均衡端口,拒绝所有Prometheus的数据写入,然后恢复Thanos系统的正常运行;

  1. 重启所有区域的Prometheus pod(因为各区域的Prometheus均部署于k8s并使用emptyDir作为数据目录,因此重启pod相当于丢弃了本地所有的历史数据,从而避免大量历史数据的反复重写),然后重新开启Thanos receive distributor的负载均衡端口;

造成的后果是丢失了部分历史数据。

故障的长期解决方案

得益于Prometheus与Thanos社区的高活跃,事后我在Prometheus 2.39.0版本的发布日志中找到了该问题的长期解决方案:

[FEATURE] experimental TSDB: Add support for ingesting out-of-order samples. This is configured via out_of_order_time_window field in the config file; check config file docs for more info. #11075

相关的提交见:https://github.com/prometheus/prometheus/pull/11075,其中的设计文档对该问题的解决进行了详细释义。

Thanos社区也迅速跟进,在提交https://github.com/thanos-io/thanos/pull/5839中为receive组件增加了对乱序数据的支持,并于今天1月最新发布的v0.30.0版本中正式上线该特性。

因此针对Prometheus数据回填问题的长期解决方案可以从以下几个方面入手:

Thanos端的优化

升级Thanos至v0.30.1版本及以上,并为receive模块增加如下三个启动参数,启用乱序数据支持:

#If true, shipper will skip failed block uploads in the given iteration and retry later. 
#This means that some newer blocks might be uploaded sooner than older block. 
#This can trigger compaction without those blocks and as a result will create an overlap situation. 
#Set it to true if you have vertical compaction enabled and wish to upload blocks as soon as possible without caring about order.
--shipper.allow-out-of-order-uploads
#Allow overlapping blocks, which in turn enables vertical compaction and vertical query merge.#Does not do anything, enabled all the time.
--tsdb.allow-overlapping-blocks
#[EXPERIMENTAL] Configures the allowed time window for ingestion of out-of-order samples. 
#Disabled (0s) by default. Please note if you enable this option and you use compactor, make sure you have the --enable-vertical-compaction flag enabled, otherwise you might risk compactor halt.
--tsdb.out-of-order.time-window=7d

为compactor模块增加如下启动参数,启用垂直压缩:

--compact.enable-vertical-compaction

Prometheus端的优化

Prometheus端通过配置远程写的queue_config,限制异常时Prometheus的发送速率,减轻Thanos端的压力,以下参数根据实际情况选配,建议优先配置max_shards限制数据发送的并发量,其余参数可使用默认值。

# Configures the queue used to write to remote storage.
queue_config:
  # Number of samples to buffer per shard before we block reading of more
  # samples from the WAL. It is recommended to have enough capacity in each
  # shard to buffer several requests to keep throughput up while processing
  # occasional slow remote requests.
  capacity: 2500
  # Maximum number of shards, i.e. amount of concurrency.
  max_shards: 5
  # Minimum number of shards, i.e. amount of concurrency.
  min_shards: 1
  # Maximum number of samples per send.
  max_samples_per_send: 500
  # Maximum time a sample will wait in buffer.
  batch_send_deadline: 5s
  # Initial retry delay. Gets doubled for every retry.
  min_backoff: 30ms
  # Maximum retry delay.
  max_backoff: 5s

参看:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write

其余优化项

增加Prometheus离线告警,尽可能避免边缘Prometheus的长时间离线;

为可能的异常情况预留较为充足的CPU、内存资源,避免长时间高位运行;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/170694.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker安装Mysql8.0主从复制

1使用portainer快速创建mysql 2.mysql-master version: 3.3 services:mysql-app:image: mysql:8.0container_name: mysqlrestart: alwaysports:- 3307:3306environment:MYSQL_ROOT_PASSWORD: 123456 # root用户的密码MYSQL_ROOT_HOST: % # 访问权限# MYSQL_USER: test …

[leetcode]刷题--关于位运算的几道题

&#xff08;1&#xff09;位运算的本质&#xff0c;其实是对二进制补码储存形式的修改。 位运算常见的运算符为 <<左移n个位置&#xff08;算数移位&#xff0c;符号位不变&#xff09; >>右移动n个位置&#xff08;采用直接丢弃末尾数字的方法&#xff0c;符号…

Android Raphael使用(专治native 内存泄漏)

1.前期准备 在项目根目录build.gradle中,添加仓库地址&#xff1a; allprojects {repositories {maven { url https://jitpack.io }} }2.案例实践 构建一个新的Library Module&#xff0c;其中build.gradle中添加依赖&#xff1a; dependencies {implementation com.github…

gitlab-runner搭建CI/CD

1. 背景 每次发布代码&#xff0c;需要连接服务器更新代码&#xff0c;进行部署&#xff0c;比较繁琐&#xff0c;浪费时间。方案有jenkins或gitlab-runner。由于代码仓库是gitlab并且只需要自动部署&#xff0c;不需要其他额外功能&#xff0c;这里选择使用gitlab-runner。 …

【React】三.React组件基础学习

目录 React组件介绍 React组件的两种创建方式 使用函数创建组件 函数组件 渲染函数组件 示例 使用类创建组件 抽离为独立的JS文件 步骤 问题记录 React事件处理 事件绑定 记录问题 事件对象 有状态组件和无状态组件 无状态组件&#xff08;木偶组件&#xff09;…

XSS(Cross Site Scripting)攻击简介

环境 Ubuntu 22.04IntelliJ IDEA 2022.1.3JDK 17.0.3.1Spring Boot 3.0.1Firefox 108.0.2 问题和分析 在IntelliJ IDEA中创建Spring Boot项目 test0116 &#xff0c;并选中 Spring Web 依赖。 在 src/main/java 下创建 MyController.java 如下&#xff1a; package com.ex…

Redis缓冲区不会还有人不知道吧?

1 简介 缓冲区&#xff0c;用一块内存空间暂时存放命令数据&#xff0c;以免因 数据和命令的处理速度&#xff1c;发送速度而导致数据丢失和性能问题。但缓冲区的内存空间有限&#xff0c;若持续&#xff1a; 往里写数据速度&#xff1e;从里读数据速度会导致缓冲区需越来越…

ATGM332D-5N卫星导航模块介绍

ATGM332D-5N卫星导航模块简介ATGM332D-5N系列模块是12X16 尺寸的高性能BDS/GNSS 全星座定位导航模块系列的总称。该系列模块产品都是基于中科微第四代低功耗GNSS SOC单芯片—AT6558&#xff0c;支持多种卫星导航系统&#xff0c;包括中国的BDS&#xff08;北斗卫星导航系统&…

BFS的入门与应用

目录 一、前言 二、BFS原理 二、BFS与最短路径 1、最短路径问题用BFS 2、迷宫&#xff08;2019年省赛&#xff0c;填空题&#xff0c;lanqiaoOJ题号602&#xff09; &#xff08;1&#xff09;字典序最小的最短路径 &#xff08;2&#xff09;输出路径的两种方法 三、B…

拉伯证券|今年首批游戏版号发放,机构看好春节行业景气度恢复

2023年第一批游戏版号发放。 昨日晚间&#xff0c;国家新闻出版署发布1月国产网络游戏审批信息&#xff0c;共88款游戏获批&#xff0c;其我国内各大游戏龙头均有所收成&#xff0c;包含腾讯《黎明觉悟&#xff1a;活力》、网易《逆水寒》&#xff08;移动版&#xff09;、完美…

数据治理:数据治理之道-组织机制-敏捷的治理组织

参考《一本书讲透数据治理》、《数据治理》等 组织机制&#xff1a;敏捷的治理组织 数据、组织、软件平台&#xff0c;是企业数字化转型面临的三座大山 数据&#xff1a;数据是企业数字化转型的根本驱动力之一&#xff0c;数字化转型中的企业必须做好数据治理与应用&#xff…

8Manage:分散的软件正在扼杀公司的生产力

在企业领域&#xff0c;数字化不仅仅是指工具能力&#xff0c;而是指用户如何很好地应用他们的知识来做决策&#xff0c;培养关系&#xff0c;建立声誉&#xff0c;以及动员同事、团队。几十年来&#xff0c;企业已经部署了生产力、搜索和协作平台&#xff0c;以提高员工和业务…

使用 tslib 库

tslib 是专门为触摸屏设备所开发的 Linux 应用层函数库&#xff0c;并且是开源。tslib 为触摸屏驱动和应用层之间的适配层&#xff0c; 它把应用程序中读取触摸屏 struct input_event 类型数据&#xff08;这是输入设备上报给应用层的原始数据&#xff09;并进行解析的操作过程…

ceres学习笔记(三)

学习了example中pose_graph_3d的部分&#xff0c;记录一下学习过程。 前言&#xff1a; 翻译一下readme里面的内容&#xff1a; ... 该示例还说明了如何将 Eigen 的几何模块与 Ceres 的自动微分功能结合使用。 为了表示方向&#xff0c;我们将使用 Eigen 的四元数&#xff…

测试开发 | Pytest 结合 Allure 生成测试报告

本文节选自霍格沃玆测试学院测试开发内部教材&#xff0c;进阶学习文末加群&#xff01; 测试报告在项目中是至关重要的角色&#xff0c;一个好的测试报告&#xff1a; 可以体现测试人员的工作量&#xff1b; 开发人员可以从测试报告中了解缺陷的情况&#xff1b; 测试经理可…

锂电产业如何利用视觉检测系统降本增效?

导语&#xff1a;机器视觉检测已在锂电池生产的各个环节中&#xff0c;为产品产量与质量提供可靠保障。维视智造作为锂电池视觉检测系统提供商&#xff0c;为企业提供专业、系统、稳定的锂电行业解决方案&#xff0c;可保证0漏检&#xff0c;确保安全生产&#xff0c;全面提升生…

炫酷 RGB 之.NET nanoFramework 点灯大师

前面介绍了 .NET nanoFramework 入门&#xff0c;本文继续以微雪的 ESP32-S2-Pico 为例介绍 .NET nanoFramework 的开发&#xff1a;控制 ESP32 板载 RGB 灯 和 外接 RGB 灯。内容包含 状态灯的意义、WS2812 、HSV、PWM 等相关知识。 文章目录1. 背景2. 状态灯的意义3. 板载 LE…

萌新如何使用printf函数?

&#x1f40e;作者的话 如果你搜索输入输出函数&#xff0c;那么你会看到输入输出流、Turbo标准库、标准输出端、stdout什么什么乱七八糟的&#xff0c;作为一个萌新&#xff0c;哪懂这些&#xff1f; 本文介绍萌新在前期的学习中&#xff0c;常用的输入输出函数及其功能~ 跳跃…

ROS2机器人编程简述humble-第二章-Controlling the Iterative Execution .3.1

2.3 ANALYZING THE BR2 BASICS PACKAGE 这一节内容有些多……前一篇&#xff1a;ROS2机器人编程简述humble-第二章-DEVELOPING THE FIRST NODE .2里面只有节点&#xff0c;没有任何实际功能。logger.cpp代码如下所示&#xff1a;#include "rclcpp/rclcpp.hpp"using n…

微信小程序分享的图片被裁切了。怎么让他不裁剪正常比例5:4显示

现在的效果 希望的效果 最主要的是下面的这个函数。把图片转成了5:4的临时图片 cutShareImg(doctorImg:string ){let thatthis;return new Promise((resolve) > {wx.getImageInfo({src: doctorImg, // 这里填写网络图片路径 success: (res) > {var data resconsole.l…