本地存储和远程存储
使用本地存储可以降低Prometheus部署和管理的复杂度同时减少高可用(HA)带来的复杂性。 在默认情况下,用户只需要部署多套Prometheus,采集相同的Targets即可实现基本的HA。
当然本地存储也带来了一些不好的地方,首先就是数据持久化的问题,特别是在像Kubernetes这样的动态集群环境下,如果Promthues的实例被重新调度,那所有历史监控数据都会丢失。 其次本地存储也意味着Prometheus不适合保存大量历史数据(一般Prometheus推荐只保留几周或者几个月的数据)。最后本地存储也导致Prometheus无法进行弹性扩展。
为了适应这方面的需求,Prometheus提供了remote_write和remote_read的特性,支持将数据存储到远端和从远端读取数据。通过将监控样本采集和数据存储分离,解决Prometheus的持久化问题。
除了本地存储方面的问题,由于Prometheus基于Pull模型,当有大量的Target需要采样本时,单一Prometheus实例在数据抓取时可能会出现一些性能问题,联邦集群的特性可以让Prometheus将样本采集任务划分到不同的Prometheus实例中,并且通过一个统一的中心节点进行聚合,从而可以使Prometheuse可以根据规模进行扩展。
本地存储
Prometheus 2.x 采用自定义的存储格式将样本数据保存在本地磁盘当中。如下所示,按照两个小时为一个时间窗口,将两小时内产生的数据存储在一个块(Block)中,每一个块中包含该时间窗口内的所有样本数据(chunks),元数据文件(meta.json)以及索引文件(index)。
而在当前时间窗口内正在收集的样本数据,Prometheus则会直接将数据保存在内容当中。为了确保此期间如果Prometheus发生崩溃或者重启时能够恢复数据,Prometheus启动时会以写入日志(WAL)的方式来实现重播,从而恢复数据。此期间如果通过API删除时间序列,删除记录也会保存在单独的逻辑文件当中(tombstone)。
内存中的block数据未写入磁盘时,block目录下面主要保存wal文件:
./data/01BKGV7JBM69T2G1BGBGM6KB12
./data/01BKGV7JBM69T2G1BGBGM6KB12/meta.json
./data/01BKGV7JBM69T2G1BGBGM6KB12/wal/000002
./data/01BKGV7JBM69T2G1BGBGM6KB12/wal/000001
持久化的block目录下wal文件被删除,timeseries数据保存在chunk文件里。index用于索引timeseries在wal文件里的位置。
./data/01BKGV7JC0RY8A6MACW02A2PJD
./data/01BKGV7JC0RY8A6MACW02A2PJD/meta.json
./data/01BKGV7JC0RY8A6MACW02A2PJD/index
./data/01BKGV7JC0RY8A6MACW02A2PJD/chunks
./data/01BKGV7JC0RY8A6MACW02A2PJD/chunks/000001
./data/01BKGV7JC0RY8A6MACW02A2PJD/tombstones
通过时间窗口的形式保存所有的样本数据,可以明显提高Prometheus的查询效率,当查询一段时间范围内的所有样本数据时,只需要简单的从落在该范围内的块中查询数据即可。
存储配置
对于本地存储,prometheus提供了一些配置项,主要包括:
--storage.tsdb.path: 存储数据的目录,默认为data/,如果要挂外部存储,可以指定该目录
--storage.tsdb.retention.time: 数据过期清理时间,默认保存15天
--storage.tsdb.retention.size: 声明数据块的最大值,不包括wal文件,如512MB
Prometheus有着非常高效的时间序列数据存储方法,每个采样数据仅仅占用3.5byte左右空间,上百万条时间序列,30秒间隔,保留60天,大概花了200多G(引用官方PPT)。
1KB Chunks
在Prometheus的世界中,无论是内存还是磁盘,它都是以1KB单位分成块来操作的。(新出的Prometheus 2.0对存储底层做了很大改动,专门针对SSD的写放大进行了优化,提高SSD的读写性能和读写次数等。)
整体流程是 抓取数据 -> 写到head chunk,写满1KB,就再生成新的块,完成的块,是不可再变更的 -> 根据配置文件的设置,有一部份chunk会被保留在内存里,按照LRU算法,定期将块写进磁盘文件内。
注意: 一条时间序列,保存到一个磁盘文件内。
时间序列的保留维护
在Prometheus的启动选项中,有一项storage.local.retention可以设置数据自动保留多长时间,例如24h,表示数据超过24小时内的将会自动清除,类似于zabbix的housekeeping功能。storage.local.series-file-shrink-ratio可以按一定的比例保留数据。
远程存储
Prometheus的本地存储设计可以减少其自身运维和管理的复杂度,同时能够满足大部分用户监控规模的需求。但是本地存储也意味着Prometheus无法持久化数据,无法存储大量历史数据,同时也无法灵活扩展和迁移。
为了保持Prometheus的简单性,Prometheus并没有尝试在自身中解决以上问题,而是通过定义两个标准接口(remote_write/remote_read),让用户可以基于这两个接口将数据保存到任意第三方的存储服务中,这种方式在Promthues中称为远程存储(Remote Storage)。
Remote Write
用户可以在Prometheus配置文件中指定Remote Write(远程写)的URL地址,比如指向influxdb中,也可指向消息队列等。
remote_write 主要用于可写远程存储配置,主要包含以下参数:
url: 访问地址
remote_timeout: 请求超时时间
write_relabel_configs: 标签重置配置, 拉取到的数据,经过重置处理后,发送给远程存储
<remote_write>
write_relabel_configs将重新标签应用于样本,然后再将其发送到远程端点。在外部标签之后应用写重新标记。这可以用来限制发送哪些样本。
Remote Read
Promthues的Remote Read(远程读)的流程当中,当用户发起查询请求后(也就是说Remote Read只在数据查询时有效),Promthues将向remote_read中配置的URL发起查询请求,接收Promthues的原始样本数据。
当获取到样本数据后,Promthues在本地使用PromQL对样本数据进行二次处理。
remote_read 主要用于可读远程存储配置,主要包含以下参数:
url: 访问地址
remote_timeout: 请求超时时间
社区中支持prometheus远程读写的方案
AppOptics: write
Chronix: write
Cortex: read and write
CrateDB: read and write
Elasticsearch: write
Gnocchi: write
Graphite: write
InfluxDB: read and write
OpenTSDB: write
PostgreSQL/TimescaleDB: read and write
SignalFx: write
clickhouse: read and write
Demo: InfluxDB
CREATE DATABASE "prometheus"
remote_write:
remote_read:
或
remote_write:
remote_read:
查看influxdb:
> select * from up
name: up
time __name__ instance job value
---- -------- -------- --- -----
1569564952174000000 up localhost:9090 prometheus 1
1569564967174000000 up localhost:9090 prometheus 1
1569564982174000000 up localhost:9090 prometheus 1
1569564997174000000 up localhost:9090 prometheus 1
1569565012174000000 up localhost:9090 prometheus 1
1569565027174000000 up localhost:9090 prometheus 1
1569565042174000000 up localhost:9090 prometheus 1
Influxdb的cli中查询结果time列格式显示设置
1.直接执行 influx -precision rfc3339
2.或者登录到influx cli之后
precision rfc3339