Thanos 架构剖析(五)历史数据怎么办

时间:2022-10-24 14:01:49

Thanos 架构剖析(五)历史数据怎么办

Thanos Compactor 组件是针对 Prometheus 2.x 存储引擎的生成的数据来进行压缩和降准的组件。

对于数据压缩来说,并行操作是存在一定安全风险的,所以 Thanos Compactor 组件需要单部实例署,一个对象存储的桶,一个组件。

Thanos Compactor 组件负责数据的降采样:

  • 对大于 40 小时的区块创建 5m 间隔的下采样(2d, 2w)
  • 为大于 10 天的区块创建 1h 间隔下采样(2w)

启动方式可以参考如下命令:

thanos compact --data-dir /tmp/thanos-compact --objstore.config-file=bucket.yml

bucket.yml 是对象存储的访问验证文件。

默认情况下,Thanos Compactor 组件只运行一次,运行结束就退出,这使得它可以作为 cronjob 执行。如果想要Thanos Compactor组件长期运行,可以使用 --wait--wait-interval=5m 参数。

Thanos 的 Compactor、Sidecar、Receive 和 Ruler 这些组件都对对象存储有写权限,只有 Compactor 组件对对象存储有删除权限,可以删除数据。

前边说过,Prometheus 在启动的时候都没有开启自身的数据压缩功能,所以上传到对象存储的原始数据都是未压缩的,这个时候 Thanos Compactor 会定期对这些数据块进行压缩。每个数据块含某个 Prometheus 实例 2 个小时的监控数据。

通常这些数据块都来自同一个 Prometheus 实例,来自单个 Prometheus 实例的数据块被称为 compaction group ,可以通过 external label 来进行区分数据块,具有相同标签的数据块来自于同一个 Prometheus 数据源,external labels 是在 Prometheus 启动的时候添加配置好的,所以在不同的 Prometheus 实例中,Block 上的标签必须是唯一和持久不变的,否则新增一个 external labels ,也会导致新数据块与旧的数据块被判定为 2 个数据源头。

  • 唯一性:一个 Prometheus 的 Label 必须和其他的 Prometheus 是不同的,这样 Thanos Compactor 才能区分不同的 Prometheus 实例。
  • 持久化:对于同一个 Prometheus 实例,Prometheus 的 Label必须保证在整个生命周期结束之前保持不变,这样即使这个 Prometheus 实例宕机, Thanos Compactor 也会继续对之前的数据进行处理,并且 Prometheus 实例恢复以后,新的数据和之前的数据是处于同一个数据源的。

原生的 Prometheus 单点实例并不会存储 external labels ,这些 label 会在上传到对象存储的时候由 Sidecar 添加到 Thanos 的元数据文件 meta.json 中。

需要注意的是,在单个对象存储中,只有一个 Thanos Compactor 可以对这个桶进行操作。因为不是所有的对象存储都对访问程序提供了安全的锁定机制,为了防止多个程序同时操作对象存储导致的数据重叠或者丢失,有必要通过其他手段保持数据的准确性。

在 Thanos 的未来版本中,一旦垂直压缩达到生产状态,这两个限制可能会被取消。不过,只要每个实例压缩单独的数据块,你就可以对一个 Bucket 运行多个compactor。通过这样的方式来扩展压缩过程。

垂直压缩

Thanos 和 Prometheus 支持垂直压缩,即将多个数据块压缩成一个数据块的过程。 在 Prometheus 中可以通过在配置文件中设置一个隐藏参数并将额外的数据块放在 Prometheus 的本地数据目录中来触发。额外的数据块可以与现有的块重叠。当 Prometheus 检测到这种情况时,它会进行垂直压实,将重叠的块压实成一个。这主要用于回填。

在 Thanos 中,逻辑类似,但规模更大,并使用 external labels 进行分组。

在这两个系统中,具有相同标签的系列被合并在一起。在 Prometheus 中,合并样本是幼稚的,它的工作原理是在完全相同的时间戳内重复删除样本。否则,样本将被合并并按时间戳排序。Thanos还支持一种新的基于惩罚的样本合并策略,在重复数据删除中对此进行了解释。

注意: Prometheus 和 Thanos 的默认行为是,如果发现任何重叠块,就会失败压缩。

使用垂直压缩有一定的风险,比如:你意外地上传了具有相同外部标签、但由完全不同的Prometheus 为完全不同的应用程序生成的数据块,那么一些指标可能会重叠并可能合并在一起,从而使部分数据无法使用成为了脏数据,如果将多个区块中的不相交的数据合并在一起,目前还没有简单的方法将它们拆分回来。

垂直压缩默认是不开启的,可以使用 --compact.enable-vertical-compaction 参数来打开垂直压缩。

如果您想对重复数据删除用例进行“虚拟”分组,请使用 --deduplication.replica-label=LABEL 设置一个或多个标签在块加载期间被忽略。

比如有如下的数据

external_labels: {cluster="eu1", replica="1", receive="true", environment="production"}
external_labels: {cluster="eu1", replica="2", receive="true", environment="production"}
external_labels: {cluster="us1", replica="1", receive="true", environment="production"}
external_labels: {cluster="us1", replica="1", receive="true", environment="staging"}

那么通过设置 --deduplication.replica-label=replica ,那么最终的数据是:

external_labels: {cluster="eu1", receive="true", environment="production"} (两条数据变成了 1 条)
external_labels: {cluster="us1", receive="true", environment="production"}
external_labels: {cluster="us1", receive="true", environment="staging"}

数据保留

缺省情况下,对象存储的数据是没有过期时间的,这意味着里边的数据可以一直存储下去,Thanos 的数据长期存储就是基于这个特性,但是长期存储并不意味这要一直存储到天荒地老,在实际生产换中,我们还是需要对数据的留存期限做一定的限制的,这个限制可以通过 Thanos 的 3 个参数实现,--retention.resolution-raw --retention.resolution-5m--retention.resolution-1h

超过数据留存其他的数据会在压缩和降准后删除,如果失败了永远不会被组件删除,只能手动删除。

降准

降准是一个重写序列的过程,以减少整体分辨率的样本,而不在更长的时间范围失去精度。 关于thanos降采样工作原理的

Thanos Compactor 使用原始的未经过降准的数据块作为依据,创建一个新的降准过的数据块,降准过的数据块会议 AggrChunk 的形式出现在存储级。

message AggrChunk {
    int64 min_time = 1;
    int64 max_time = 2;

    Chunk raw     = 3;
    Chunk count   = 4;
    Chunk sum     = 5;
    Chunk min     = 6;
    Chunk max     = 7;
    Chunk counter = 8;
}

这意味着,对于每个 Series 我们以给定的间隔收集不同的聚合间隔 5m 或 1h (取决于分辨率)。这允许我们在不获取太多原始监控数据的情况下,保持大持续时间范围查询的精度。

降低采样:关于分辨率和留存率的注意事项

分辨率是图表上两个数据点之间的距离。比如

  • Raw - 与数据源获取监控指标的间隔相同
  • 5m - 每 5 分钟一个数据点
  • 1h - 每 1 小时一个数据点

请记住,数据降准的最初目标不是节省磁盘或对象存储空间。事实上,降准并不会为你节省任何空间,相反,它会为每个原始数据块增加2个新的数据块,这些新增的数据块的大小与原始块相比可能会略小也有可能相等。降准后的数据块是经过各种聚合的,这意味着,如果选择存储所有的分辨率,那么降准这个操作会使存储空间变大,可能会是之前的 3 倍大小。

数据降准的目标是为大范围时间(如月或年)的范围查询提供一个获得快速结果的机会。换句话说,如果你设置原始数据的留存时间比 5m 的降准数据留存时间短(--retention.resolution-raw 的值比--retention.resolution-5m--retention.resolution-1h小),那么会遇到一个问题,当你想查看细节的时候,细节丢失了,你看不到了。

简单来说,原始数据是细节,所以考虑 --retention.resolution-raw--retention.resolution-5m--retention.resolution-1h

这 3 个值的怎么设置的时候,如果你的需求是需要看到一年前某个时间段的详细数据,那么需要保留原始数据和 5m 的降准数据,你需要解决长期存储带来的巨大的存储成本,如果你只需要看到最近的详细数据,一年前的情况有一个大概的趋势就可以,那么保留 1h 的降准数据长期存放,其他数据短期即可,这样可以兼顾数据长期存储和存储的成本。

如果不需要对原始数据进行降准,可以使用参数 --downsampling.disable 关闭。

--retention.resolution-raw--retention.resolution-5m--retention.resolution-1h 参数不设置或者设置为 0 ,意味着数据永久保留。