Cortex算得上支持prometheus的持久化存储的元老了,很早就加入到CNCF基金会,目前已经处于孵化状态了。但是发展却一直不温不火,反而thanos后来居上。细想其中的原因,其架构的复杂性无疑是一个重要的原因。下面是其chunk 存储模式的架构图:

涉及到组件十几个,其chunk 模式,依赖两种存储,部署和维护困难。

从瑜亮之争到双赢

cortex和thanos 作为Prometheus持久化的两种方案,简直就是瑜亮之争。各自有各自的优势,不过貌似thanos发展更好一些。

目前两种解决方案正在相互学习,逐步弥补自己的短处。有趣的是这两个方案,直接引用了对方的代码来补强功能。

对于thanos, 其变化体现在下面两个方面:

  • 在写路径上,引入了receive组件,逐步替换掉sidecar。
  • 在读路径上,引入了query-frontend 组件,用于split 大查询和缓存某些查询结果。

对于cortex,其变化体现在引入block存储模式,简化了其架构模式。

实际上,在存储上,cortex向thanos学习更多一些。在读路径上,thanos向cortex学习更多一些。

下面我们详细介绍一下cortex的block 存储引擎模式。

Block 存储引擎

块存储是基于Prometheus TSDB的Cortex存储引擎:它将每个租户的时间序列存储到自己的TSDB中,然后将其序列写到磁盘上的块中(默认为2h块范围周期)。每个块由块文件(包含多个序列的时间戳-值对)和索引组成,该索引将metrcis名称和labels索引到块文件中的时间序列。

块存储支持的后端是:

  • 亚马逊S3
  • 谷歌云存储
  • Microsoft Azure存储
  • 本地文件系统(仅单节点)

相信阿里云和腾讯云的对象存储也会很快支持。

架构

运行Cortex块存储时,Cortex架构不会发生重大变化,因此常规体系结构文档也适用于块存储。但是,运行块存储时还有两个其他的Cortex服务:

可以看出compactor和store-gateway组件,明显学习了thanos。

store-gateway负责查询chunk,并在查询时由查询器使用。选择块存储模式时,需要store-gateway。
compactor负责将较小的块合并和重复数据删除为较大的块,以减少给定租户的长期存储中存储的块数量,并更有效地查询它们。compactor是可选的,但是在生产环境必不可少。

写路径

Ingestersdistributors接收进来的sample。每个推送请求都属于一个租户,而ingester会将接收到的sample附加到存储在本地磁盘上的特定的每个租户TSDB。接收到的sample都保存在内存中,并写入到预写日志(WAL)中,并用于在内存突然终止的情况下恢复内存中的序列。一旦每个租户收到第一个sample,就会在每个租户中延迟创建每个租户的TSDB。

创建新的TSDB块时,内存中的sample会定期刷新到磁盘,并且WAL会被截断,默认情况下,每2个小时会发生一次。然后,每个新创建的块都将上载到长期存储中,并保留在初始状态,直到配置的-blocks-storage.tsdb.retention-period到期为止,以便给予queriersstore-gateways足够的时间来发现新块存储并下载其索引头。

为了有效地使用WAL并能够在突然终止Inester后恢复内存中的序列,WAL需要存储到一个永久磁盘,该磁盘在发生Inester失败(例如AWS EBS卷或GCP)的情况下仍可以生存在云端运行时使用永久磁盘)。例如,如果您在Kubernetes中运行Cortex集群,则可以将StatefulSet与持久化批量声明一起使用。文件系统上存储WAL的位置与存储本地TSDB块(从头压缩)的位置相同,并且无法解耦。

Distributor series 分片和复制

Distributor 完成的series分片和复制不会根据存储引擎而改变。
请务必注意,由于复制因子为N(通常为3),因此与块存储不同的是,由于复制因子N,每个时间序列均存储N个ingesters。由于每个实例都将其自己的块写入长期存储,因此这导致存储利用率是块存储的N倍。 Compactor通过将来自多个ingesters的块合并为一个块,并删除重复的sample来解决此问题。

读路径

Queriersstore-gateways 定期在存储桶上进行迭代,以发现最近由ingesters上传的块。 对于每个发现的块,Queriers 仅下载块的meta.json文件(包含一些元数据,包括该块中sample的最小和最大时间戳),而 store-gateways 下载meta.json以及索引头,这是一个store-gateways在查询时用于查找序列的块索引的一小部分。 Queriers使用块元数据来计算在查询时需要查询的块列表,并从保存所需块的store-gateways实例中获取匹配序列。

总结

不过由于cortex 发展比较早,其组件更丰富。也是未来thanos的发展方向。例如cortex 封装了alertmanager,使其也支持多租户。

到底谁是赢家,不太好说。不过最终成功的那个解决方案,身上一定存满了另一个的影子。


iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。