关注分享主机优惠活动
国内外VPS云服务器

容器监控实践-Prometheus存储机制

总结:为了解决单节点存储的局限性,我们没有自行实现集群存储。 相反,我们提供了远程读写接口,并允许用户选择合适的时间序列数据库以实现可扩展性。 这实际上根本不关心另一端是什么样的时间序列数据库,如果您愿意,您可以创建自己的数据库。

概述

Prometheus提供本地存储,即tsdb时序数据库。 本地存储为Prometheus提供了简单高效的使用体验。 从prometheus 2.0开始,数据压缩功能也有了显着的提升。 单个节点即可满足大部分用户的监控需求。

但是本地存储也限制了Prometheus的扩展性,并引入了数据持久化等一系列问题。 为了解决单节点存储的局限性,prometheus本身并没有实现集群存储。 相反,它提供了远程读写接口,并允许用户选择合适的时序数据库来实现Prometheus的可扩展性。

Prometheus 1.x 版本的 TSDB(V2 存储引擎)基于 LevelDB,并使用与 Facebook Gorilla 相同的压缩算法,可以将 16 字节数据点压缩到平均 1.37 字节。

Prometheus 2.x版本引入了新的V3存储引擎,提高了写入和查询性能。

以下所有内容基于prometheus2.7版本

本地存储存储原理

Prometheus 2.按时间分块保存。 每个块由一个目录组成,该目录包含一个或多个块文件(用于存储时间序列数据)、元数据文件和索引文件(用于通过度量名称和标签在块文件中定位时间序列数据)。

最后写入的数据存储在内存块中,并在2小时后写入磁盘。 为了防止程序崩溃导致数据丢失,WAL(write[k一旦启动,4]ahead-log)机制通过写入日志(WAL)来恢复数据来实现重放。

当数据被删除时,删除的条目会记录在单独的逻辑删除文件中,而不是立即从块文件中删除。

将所有样本数据以时间窗口的形式存储,大大提高了Prometheus的查询效率。 如果要查询某个时间段内的所有样本数据,只需选择属于该范围内的块即可。 查询一下数据就可以了。

这些两小时的块在后台被压缩成更大的块。 数据被压缩并合并到上层块文件中,然后删除下层块文件。 这与leveldb、rocksdb等LSM树的思想是一致的。

这些设计与Gorilla非常相似,所以Prometheus大致相当于一个缓存的TSDB。 本地存储的特点决定了它不能用于长期数据存储,只能用于短期窗口内的时序数据存储和查询,且可用性不高(有可能因宕机而导致历史数据丢失) )。 有)。 难以辨认)。

当内存中的块数据没有写入磁盘时,wal文件主要存储在块目录中:

./data/01BKGV7JBM69T2G1BGBGM6KB12./data/01BKGV7JBM69T2G1BGBGM6KB12/meta.json。 /data /01BKGV7JBM69T2G1BGBGM6KB12/wal/000002./data/01BKGV7JBM69T2G1BGBGM6KB12/wal/000001

删除持久块目录下的wal文件,时间序列数据保存在chunk文件中。 Index 用于索引 wal 文件中时间序列的位置。

./data/01BKGV7JC0RY8A6MACW02A2PJD./data/01BKGV7JC0RY8A6MA0RY 8A6MACW02A2PJD/tombstones

存储配置

对于本地存储,prometheus主要提供了几个配置项:

--storage.tsdb.path:保存数据的目录。 默认为数据/。 如果要挂载外部存储,可以指定此目录。

--storage.tsdb.retention.time:数据过期清理时间。 默认值为 15 天。

--storage.tsdb .retention.size:实验性的,声明不包括wal文件的数据块最大大小,如512MB

-- storage.tsdb .retention:已被放弃。 使用存储代替。 tsdb.retention.time

Prometheus 将所有当前使用的块保留在内存中。 此外,最近使用的块保存在内存中,并且可以通过 storage.local.memory-chunks 标志设置最大内存。

监控当前使用的内存量:

prometheus_local_storage_memory_chunks

process_resident_memory_bytes

监控当前使用的存储指标:

监控当前使用的存储指标。 p>

prometheus_local_storage_memory_series:当前时间序列持有的内存块数量

prometheus_local_storage_memory_chunks:内存中当前持久化块的数量

prometheus_local_storage_chunks_to_persist:当前仍需要持久化到磁盘的内存块的数量

prometheus_local_storage_persistence_urgency_score:紧急程度评分

存储prometheus 2.0 升级

Prometheus 2.0 于 2017 年-11-08 发布,主要是由于存储引擎的优化。

整体性能提升:

20% - CPU 使用率相比 Prometheus 1.8 降低了 40%

Prometheus 1.8 与磁盘空间使用率相比有所降低到 33% - 50%

查询较少,平均负载磁盘 I/O 为 <1%

在 Kubernetes 集群等动态环境中,prometheus 数据平面通常看起来像这样

垂直维度代表所有存储的序列

水平维度代表样本传播的时间。

示例:

 requests_total{path=“/status”,method=“GET”,instance=“10.0.0.1:80”}requests_total{path=“/status”,method=“POST”,instance=“10.0 .0.3:80”} requests_total{path="/", method="GET", instance="10.0.0.2:80"}

Prometheus 定期收集所有系列的新数据点。 意味着它必须垂直书写在时间线的右端。 然而,在查询时,您可能想要访问平面上的任意区域。矩形(各种标签条件)

因此需要索引来高效地从大量数据中找到查询序列。

Prometheus 1.x 存储层可以很好地处理垂直写入模式,但随着扩展,索引可能会出现问题,因此 2.0 版本重新设计了存储引擎和索引。 主要改进是:

样本压缩

现有存储层的样本压缩特性在Prometheus早期版本中发挥了重要作用。 单个原始数据点占用16字节的存储空间。 但是,当 Prometheus 每秒收集数十万个数据点时,您的硬盘很快就会被填满。

但是,同一系列的样本非常相似,因此使用此类样本(相同标签)可以进行有效的压缩。 批量压缩内存中许多样本的一系列块,将每个数据点压缩到平均 1.37 字节的存储空间。

这种压缩方案效果很好,并且在新的版本 2 存储层设计中得到了维护。 具体压缩算法请参见:Facebook的“Gorilla”论文

分时

新的存储层对块进行分割。 每个块都包含一切。 一段时间内的序列。 每个块充当一个独立的数据库。

这样,对于每个查询,只检查请求时间范围内的块子集,自然减少了查询执行时间。

这种布局还使得删除旧数据变得非常容易(这在 1.x 存储设计中是一项耗时的操作)。 然而,在2.x中,如果一个块的时间范围完全低于设定的保留边界,则该块可能会被永久丢弃。

索引

典型的 Prometheus 查询使用指标和标签作为关键字,非常全面且完整。 由于自定义字符,您无法使用常规 SQL 数据库。 Prometheus的存储层使用倒排索引的概念进行全文搜索,将每个时间序列视为一个小文档。 以及公制和实验室el 对应文档中的一个单词。

例如,requests_total{path="/status",method="GET",instance="10.0.0.1:80"} 是一个包含以下单词的文档:

__name__= "requests_total"

path="/status"

method="GET"

instance="10.0.0.1 :80"

基准测试

与 1.x 版本相比,CPU、内存和查询效率有了显着改进。

具体测试结果参考:https://dzone.com/articles/pr...

灾难恢复

数据库损坏是问题所在如果您认为是这个原因,你可以配置你的数据库存储。 .local.dirtyflag 设置。 启动服务器并强制其从崩溃中恢复。

如果问题仍然存在,或者您想删除现有数据库,您可以通过删除存储目录的内容来轻松启动数据库。

1.停止服务:停止prometheus。

p>

2.删除数据目录:rm -r /*

3.启动服务:start prometheus

Remote存储

Prometheus默认有自己的存储,保留期为15天。 但本地存储也意味着Prometheus无法持久化数据、无法存储大量历史数据、无法弹性伸缩。
为了保证Prometheus的简单性,Prometheus并没有从自己的集群角度来解决这些问题。 相反,定义了两个接口:remote_write/remote_read来抛出数据并自行处理。

Prometheus中的Remote_storage实际上是一个适配器。 关于适配器您根本不关心 r 的另一端有什么样的时间序列数据库,如果您愿意,您可以编写自己的适配器。

示例:存储方式为:Prometheus —- 发送数据 —- > Remote_storage_adapter —- 存储数据 —-> influxdb。

Prometheus通过两种方式实现与其他远程存储系统的对接:

Prometheus 以标准格式将指标写入远程存储。

Prometheus 使用标准格式的远程 URL

远程读取

远程读取过程在用户发起时使用远程 URL查询请求,Promthues向配置了remote_read的URL发起查询请求(matchers、ranges),适配器根据请求条件从第三方存储服务中检索响应数据。 同时将数据转化为Prometheus原始样本数据返回到Prometheus Server。

获取样本数据后,Promthues 使用 PromQL 在本地处理样本数据。

远程写入

用户可以在Promtheus配置文件中指定远程写入URL地址。 设置此配置项后,Prometheus 通过 HTTP 发送样本数据。 到适配器。 用户可以连接到适配器内的任何外部服务。 外部服务可以采取任何形式,例如实际的存储系统、公共云存储服务或消息队列。

配置

配置非常简单。 只需设置相应的地址即可。

remote_write: - url: "http://localhost:9201 /write"remote_read: - URL: "http://localhost:9201/read"

社区支持

社区目前正在实施以下远程存储解决方案:

AppOptics:写入

Chronix:写入

Cortex:读写

CrateDB:读写

Elasticsearch:写入

Gnocchi:写入

Graphite:写入

InfluxDB:读取和写入

OpenTSDB:写入

PostgreSQL/TimescaleDB:读取和写入

SignalFx:写入

可以使用InfluxDB进行全读写。使用多个prometheus服务器同时远程读写,为InfluxDB创建完整的速度生态系统

容量规划

正常情况下,Prometheus中存储的每个样本大约为1-2字节,如果需要规划Prometheus Server的本地磁盘空间,可以使用以下公式计算:

磁盘大小 = 保留时间 * 每秒采集的样本数 * 样本大小

保留时间(retention_time_seconds)和样本大小(bytes_per_sample)保持不变,以减少本地磁盘空间需求。减少每秒采集的样本数 (ingested_samples_per_second)。

有两种方法可以实现此目的:减少时间序列的数量,或增加采集的样本数的时间间隔。

当考虑到 Prometheus 压缩时间序列时,减少时间序列数量的效果变得更加明显。b>

远程读写解决Promtheus中的数据持久化问题。 使其具有弹性可扩展性。 此外,它还支持联邦集群模式,解决了水平扩展和网络分区的问题(例如将A+B+C区域的监控数据整合到D区域)。 以下 Promthues 高可用性文章详细介绍了配置联合集群: 。

附件:kubecon2018上谈论Prometheus 2.0的帅哥

还有专门介绍Prometheus的书籍:Prometheus: Up & Running(等等) 600页....)

我在中国找不到有卖的,但我确实找到了一份英文PDF。 今天它仍然被翻译和理解。 新内容将在本系列博客中持续同步。

。 。 。 我找到了另一本书:https://www.prometheusbook.com/

参考文献:

https://prometheus.io/docs/pr。 ..

https://coreos.com/blog/prome...

https://dzone.com/articles/pr...

https://www.linuxidc.com/Linu...

http://ylzheng.com/2018/03/06...

https://www .cnblogs.com/vovli...

https://files-cdn.cnblogs.com...

https://www.bookstack.cn/ 阅读...

本文是关于容器监控实践的系列文章。 请参阅container-monitor-book

了解完整内容。

未经允许不得转载:主机频道 » 容器监控实践-Prometheus存储机制

评论 抢沙发

评论前必须登录!