写点什么

Prometheus backfilling 功速体验

用户头像
_why先生
关注
发布于: 2020 年 12 月 13 日
Prometheus backfilling 功速体验

了解 Prometheus 的同学都知道,回写(backfill)这个功能出现在最新的 Roadmap 中,它属于一个比较重要的功能。


为什么需要 backfilling?


  • 创建新的 record rules 可以填充老数据。

  • 方便数据迁移,避免从其它系统迁移到 Prometheus 而丢失老数据。

  • 快速构建模拟数据,方便调试 PromQL。


前几天看到 #8084 这个 PR 合并到了主分支,它实现的是 openmetrics 格式文本文件导入的版本,下面我们一起看看它的用法。

编译最新版本


由于相关功能还没正式发版,所以这里直接编译最新的 master 分支,得到的 Prometheus 和 Promtool 版本如下:


$ ./prometheus --versionprometheus, version 2.23.0 (branch: master, revision: e13f4a5f6e93c51b0238e2b7095e575e905ad758)    build user:       songjiayang@ZBMAC-90549ae81    build date:       20201209-22:31:13    go version:       go1.14.6    platform:         darwin/amd64
$ ./promtool --versionpromtool, version 2.23.0 (branch: master, revision: e13f4a5f6e93c51b0238e2b7095e575e905ad758) build user: songjiayang@ZBMAC-90549ae81 build date: 20201209-22:31:13 go version: go1.14.6 platform: darwin/amd64
复制代码


新版 promtool 增加了 tsdb create-blocks-from openmetrics 命令,使用说明如下:


tsdb create-blocks-from openmetrics <input file> [<output directory>]    Import samples from OpenMetrics input and produce TSDB blocks. Please refer to the storage docs for more details.
复制代码

构建测试数据


新建一个叫做 backfilling.txt 的测试文件,内容如下:


# HELP http_requests_total The total number of HTTP requests.# TYPE http_requests_total counterhttp_requests_total{code="200"} 1021 1607491300.989http_requests_total{code="200"} 1022 1607491330http_requests_total{code="200"} 1026 1607491360http_requests_total{code="200"} 1029 1607491390.989http_requests_total{code="200"} 1030 1607491420.989http_requests_total{code="200"} 1032 1607491450http_requests_total{code="200"} 1033 1607491480http_requests_total{code="200"} 1038 1607491510http_requests_total{code="400"} 2 1607491300.989http_requests_total{code="400"} 2 1607491330http_requests_total{code="400"} 3 1607491390.989http_requests_total{code="400"} 3 1607491420.989http_requests_total{code="400"} 3 1607491450http_requests_total{code="400"} 4 1607491360.989http_requests_total{code="400"} 4 1607491480.989http_requests_total{code="400"} 5 1607491510# EOF
复制代码


这个文本内容属于 OpenMetrics 格式,看上去和 Prometheus 的很像,但它有以下特点:


  • 包含 Prometheus metric 文本格式的内容,例如 HELPTYPE 关键字以及命名等。

  • 每行时序数据最后添加一个时间戳列,类型为 float,整数部分为秒,小数 3 位为毫秒。

  • 必须以显示 # EOF 表示内容结束,不然会报类似 getting min and max timestamp: next: expected next entry after timestamp, got "EOF" 的错误。


以上测试数据包含了一个 __name__ 为 http_requests_total ,类型为 counter、labelset 为 {code="200"} | {code="400"} 的时序数据,导入数据时间范围为 1607491300 ~ 1607491510。


启动 Prometheus 并导入数据


刚启动 Prometheus 时,data 目录内容如下:


$ tree data
data├── chunks_head├── lock├── queries.active└── wal ├── 00000000 └── 00000001
2 directories, 4 files
复制代码


第 1 次执行导入命令:


$ ./promtool tsdb create-blocks-from openmetrics backfilling.txt BLOCK ULID                  MIN TIME                       MAX TIME                       DURATION   NUM SAMPLES  NUM CHUNKS  NUM SERIES  SIZE01ES5PNA15GJ9TSKBYX4Y850BW  2020-12-09 05:21:40 +0000 UTC  2020-12-09 05:25:10 +0000 UTC  3m30.001s  15           2           2           769B
$ tree datadata├── 01ES5PNA15GJ9TSKBYX4Y850BW│   ├── chunks│   │   └── 000001│   ├── index│   ├── meta.json│   └── tombstones├── chunks_head├── lock├── queries.active└── wal ├── 00000000 └── 00000001
4 directories, 8 files
复制代码


当第 1 次执行完导入命令后,data 目录新增了一个叫做 01ES5PNA15GJ9TSKBYX4Y850BW block,说明我们的数据已经成功导入。等待大约 1 分钟,Prometheus log 没有任何变化,到 Prometheus 的 graph 执行对应查询也没有查询到刚导入的数据。



第 2 次执行导入命令,此时又新增了一个名为 01ES5PYJ29D6YK75E4V3E72WFB 的 block,等待大约 1 分钟(tsdb compation 默认时间间隔),可以看到 Prometheus log 中新增了如下内容:


level=warn ts=2020-12-10T06:56:32.485Z caller=compact.go:686 component=tsdb msg="Found overlapping blocks during compaction" ulid=01ES5PZRP848J7AC8PNME78Y2Zlevel=info ts=2020-12-10T06:56:33.130Z caller=compact.go:448 component=tsdb msg="compact blocks" count=2 mint=1607491300989 maxt=1607491510990 ulid=01ES5PZRP848J7AC8PNME78Y2Z sources="[01ES5PXXFEKKMDYJEDFJ57JPZ3 01ES5PYJ29D6YK75E4V3E72WFB]" duration=674.437236mslevel=info ts=2020-12-10T06:56:33.155Z caller=db.go:1197 component=tsdb msg="Deleting obsolete block" block=01ES5PYJ29D6YK75E4V3E72WFBlevel=info ts=2020-12-10T06:56:33.166Z caller=db.go:1197 component=tsdb msg="Deleting obsolete block" block=01ES5PXXFEKKMDYJEDFJ57JPZ3
复制代码


日志内容表明,当第 2 次执行完导入命令后,产生了有时间重叠的多个 block,Prometheus 启动压实,压实完成后会产生一个新的 block,并且被 Prometheus 感知到,故此时相同查询可以得到导入数据。



关于这一点,我觉得是一个 bug,理论新增的 block 无论是否有时间重叠都应该被查询到,立马给官方提了一个 issue #8268,欢迎大家关注。

总结


今天我们手动编译了最新版本的 prometheus 和 promtool,然后通过最新的 promtool 的 tsdb create-blocks-from openmetrics 命令成功导入了历史数据,需要注意的是导入数据的 openmetrics 格式文件需要显示添加 # EOF


当导入成功后,如果新增的 block 的时间范围和已经存在的 block 时间没有重叠,prometheus 不会执行压实任务,从而新导入的数据不会被 prometheus 感知到。目前可以通过手动多次运行导入命令的方式来解决,对此我提交了一个相应的 issue,希望这个 bug 在不久的将来会被修复。


参考资料:



更多云原生可观性一手资料,请关注微信公众号 "cloudnativemetric" 或扫描二维码。


发布于: 2020 年 12 月 13 日阅读数: 65
用户头像

_why先生

关注

学习是从了解到使用再到输出的过程 2018.04.27 加入

做 1000 件事不如把 1 件事做到极致,喜欢从量变到质变的过程。

评论

发布
暂无评论
Prometheus backfilling 功速体验