写点什么

Thanos 架构剖析(二)统一的查询入口

作者:耳东@Erdong
  • 2021 年 12 月 15 日
  • 本文字数:3945 字

    阅读完需:约 13 分钟

Thanos 架构剖析(二)统一的查询入口

本文收录于 云原生监控高可用集群 Thanos 架构剖析 | 内容合集 ,如有需要请查阅。


Thanos Query

Thanos 的 Query 组件实现了 Prometheus 的 HTTP v1 API,可以像 Prometheus 的 Graph 一样,通过 PromQL 查询 Thanos 集群中的数据。


简而言之,Thanos Query 从底层的 Store API 收集查询所需的数据,执行查询操作并返回结果,而且 Query 组件是可以无状态和水平扩展的。


Thanos Query 组件的启动非常简单 ,比如:


thanos query \    --http-address     "0.0.0.0:9090" \    --store            "<store-api>:<grpc-port>" \    --store            "<store-api2>:<grpc-port>"
复制代码


  • --http-address :组件启动后对外提供服务的地址和端口

  • --store :Thanos 提供数据查询的 IP 地址和 gRPC 端口,一般是 Sidecar 和 Store 的地址和端口。


Thanos Query 启动后的页面如下,和 Prometheus 的原生界面非常接近。


Thanos Query 作为入口,后边是任何实现了 gRPC StoreAPI 的组件,我们可以从任意数量的不同存储聚合数据,比如:


  • Prometheus ,使用 Sidecar 作为代理从 Prometheus 获取数据

  • 对象存储,使用 Store 组件为对象存储代理请求可以获取对象存储中的监控数据

  • 全局的告警规则和记录规则,比如使用 Thanos Rule 组件

  • Receiver 组件的数据,Prometheus 可以通过远程写功能将数据吐给 Receiver,Query 可以从 Receiver 组件获取这些数据

  • 其他的 Query 组件

  • 其他非 Prometheus 的系统,比如 OpenTSDB。


因为 Thanos Query 的这种设计,我们可以在一个地方,查询所有的内容,包括 Prometheus 的数据、告警规则、记录规则,这些来源不同的指标也可以进行汇总。

HA 集群运行时重复数据删除

Prometheus 一个是有状态的服务,通过运行多个 Prometheus 实例使用过同一个数据库来实现高可用是不可能的。另外如果简单的负载均衡来实现高可用,当出现程序崩溃后,监控数据还在上传,会导致 2 个数据库的不一致,这也是不可行的。


Thanos 为 Prometheus 提供的高可用方案是,单独启动两个 Prometheus 实例同时去拉取监控数据,Thanos Query 会从 2 个实例中获取数据,然后对数据进行去重,如果存在空白,那么就保留。这样整个 Thanos Query 对用户是透明的,2 个 Prometheus 实例对用户是无感的,Query 在前边做了代理。对于数据来说,2 个 Prometheus 只要有一个有数据,用户就能查到数据。我们也可以启动 3 个或者更多的实例来保证监控的高可用。

指标查询工作流

总体来说,Thanos Query 组件暴露的 Query API 保证兼容 Prometheus 2.x 版本的 API。图片显示了 Query 对每个 Prometheus 查询请求所做的工作。


重复数据删除

Thanos 查询层可以删除从高可用性数据源(如 Prometheus)收集的时间序列数据,但是必须为整个集群选择一个固定的单个或多个副本标签,然后可以在启动时传递给查询节点。


两个或多个只通过给定的 replica label 区分的序列将合并为一个时间序列。这也隐藏了单个数据源集合中的差距。


下面是一个单副本标签的例子,


Prometheus + sidecar “A”: cluster=1,env=2,replica=A

Prometheus + sidecar “B”: cluster=1,env=2,replica=B

Prometheus + sidecar “A” in different cluster: cluster=2,env=2,replica=A


我们可以配置 Query 组件的启动参数如下:


thanos query \    --http-address        "0.0.0.0:9090" \    --query.replica-label "replica" \    --store               "<store-api>:<grpc-port>" \    --store               "<store-api2>:<grpc-port>" \
复制代码


使用 --query.replica-label "replica" 参数可以打开删除重复数据,这样可以过滤多个 Prometheus 实例采集同一份监控数据带来的数据重复。


我们来看一个例子,我们查询 up{job="prometheus",env="2"} 指标的时候会查到 2 个结果 :


up{job="prometheus",env="2",cluster="1"} 1up{job="prometheus",env="2",cluster="2"} 1
复制代码


如果不使用 --query.replica-label "replica" 参数关闭重复数据删除,我们会得到 3 个结果,


up{job="prometheus",env="2",cluster="1",replica="A"} 1up{job="prometheus",env="2",cluster="1",replica="B"} 1up{job="prometheus",env="2",cluster="2",replica="A"} 1
复制代码


在这个例子中,使用多个 replica label 会得到相同的输出:


  • Prometheus + sidecar “A”:cluster=1,env=2,replica=A,replicaX=A

  • Prometheus + sidecar “B”:cluster=1,env=2,replica=B,replicaX=B

  • Prometheus + sidecar “A” in different cluster:cluster=2,env=2,replica=A,replicaX=A


thanos query \    --http-address        "0.0.0.0:9090" \    --query.replica-label "replica" \    --query.replica-label "replicaX" \    --store               "<store-api>:<grpc-port>" \    --store               "<store-api2>:<grpc-port>" \
复制代码


这个逻辑也可以通过 Query API 上的参数来控制。

Thanos Query Frontend

Thanos Query Frontend 组件通过 thanos query-frontend 命令实现了一个可以放在 Thanos Query 前面的服务,以改进读取路径。它基于 Cortex Query Frontend 组件,所以你可以找到一些 Cortex 常见的特性,如查询拆分和结果缓存。


Thanos Query Frontend 是无状态和水平扩展的,可以使用下列命令来启动 Thanos Query Frontend


thanos query-frontend \    --http-address     "0.0.0.0:9090" \    --query-frontend.downstream-url="<thanos-querier>:<querier-http-port>"
复制代码


目前,只有范围查询 `/api/v1/query_range` 接口的 api 调用实际上是通过 Query Frontend 处理的。所有其他的 API 调用直接进入下游 Thanos Query 来查询,这意味着只有范围查询被分割和缓存,开发者已经将即时查询加到计划列表中,后续也会支持。

查询拆分

Thanos Query Frontend 根据配置的 --query-range.split-interval 将一个长查询拆分为多个短查询。--query-range.split-interval 默认值是 24h ,当查询 24 小时内的指标时不进行拆分,当查询超过 24 小时的指标时,会对查询语句进行拆分来减小查询压力。当启用缓存时,它应该大于 0。使用查询拆分功能有 3 个好处:


1、它可以保证 Query 和其他组件的稳定性,防止大型查询对 Query 造成 OOM,导致程序崩溃;

2、可以更好的并行查询;

3、可以提供更好的查询负载。

重试机制

Thanos Query Frontend 支持重试机制,可以在 HTTP 查询请求失败时进行重试,通过使用参数 --query-range.max-retries-per-request 限制最大重试次数,这个一般建议重试 1 次到 2 次就可以了,不建议超过 3 次,太多的重试会导致 Thanos Query 组件的压力变大。另外就是如果针对查询语句有错误或者其他问题,尽快失败,暴露问题,而不是一次一次的重试。

Cache 缓存

Thanos Query Frontend 支持缓存查询结果,并在后续查询中重用它们。如果缓存的结果不完整,Query Frontend 会计算所需的子查询,并在下游 Query 上并行的执行这些。Query Frontend 可以选择将查询与其步长参数对齐,以提高查询结果的可缓存性。目前,支持内存缓存(fifo 缓存) 、memcached 和 Redis。

内存缓存

type: IN-MEMORYconfig:  max_size: ""  max_size_items: 0  validity: 0s
复制代码


max_size: 在内存中缓存的最大尺寸,单位可以是 KB、MB、GB。


如果 max_size 和 max_size_items 都没有设置,就不会创建缓存。


如果只设置 max_size 或 max_size_items 中的任意一个,则对其他字段没有限制。

memcached 缓存

type: MEMCACHEDconfig:  addresses: []  timeout: 0s  max_idle_connections: 0  max_async_concurrency: 0  max_async_buffer_size: 0  max_get_multi_concurrency: 0  max_item_size: 0  max_get_multi_batch_size: 0  dns_provider_update_interval: 0s  auto_discovery: false
复制代码


expiration :指定 memcached 缓存有效时间。如果设置为 0,则使用默认的 24 小时过期时间。


默认的 memcached 配置是:


type: MEMCACHEDconfig:  addresses: [your-memcached-addresses]  timeout: 500ms  max_idle_connections: 100  max_item_size: 1MiB  max_async_concurrency: 10  max_async_buffer_size: 10000  max_get_multi_concurrency: 100  max_get_multi_batch_size: 0  dns_provider_update_interval: 10s  expiration: 24h
复制代码

Redis 缓存

默认的 Redis 配置如下:


type: REDISconfig:  addr: ""  username: ""  password: ""  db: 0  dial_timeout: 5s  read_timeout: 3s  write_timeout: 3s  pool_size: 100  min_idle_conns: 10  idle_timeout: 5m0s  max_conn_age: 0s  max_get_multi_concurrency: 100  get_multi_batch_size: 100  max_set_multi_concurrency: 100  set_multi_batch_size: 100  expiration: 24h0m0s
复制代码


expiration :指定 Redis 缓存有效时间。如果设置为 0,则使用默认的 24 小时过期时间。

慢查日志

Thanos Query Frontend 支持使用 --query-frontend.log-queries-longer-than 参数去通过日志记录查询时长超过某个范围的查询语句。这个功能有 2 个作用,第一个是在 Query 被查挂的时候,查找出现问题的原因,第二个功能是定期查找耗时长的语句,对这些语句优化或者制定规范,这样来提高查询效率。

一些推荐的配置

Thanos Query Frontend 的 HTTP Client 可以配置 --query-frontend.downstream-tripper-config--query-frontend.downstream-tripper-config-file.


如果使用负载均衡指向后端主机,那么建议 max_idle_conns_per_host 参数值最少为 100 ,否则 Query Frontend 无法利用 HTTP 活动链接,延迟将会升高 10% ~ 20% 。默认情况下,Go HTTP client 会在每个机器上保留 2 个空闲链接。


小结

本文主要描述 Thanos Query 和 Thanos Query Frontend 两个和查询直接相关的组件,实际生产使用中,可以根据情况选择,按需配置。

发布于: 7 小时前阅读数: 15
用户头像

耳东@Erdong

关注

还未添加个人签名 2020.05.24 加入

主要研究分享运维技术,专注于监控、CICD、操作系统、云原生领域,公众号【耳东学堂】,知识星球同名,坚持原创,希望能和大家在运维路上结伴而行 邮箱:erdong@mail.erdong.site

评论

发布
暂无评论
Thanos 架构剖析(二)统一的查询入口