Prometheus 多租写入 Thanos Receiver 配置

背景描述

当采集指标过多时,超过单个 prometheus 的处理能力,我们通常会采用多个 prometheus 实例分别采集一定的指标分片,然后通过 thanos 做聚合,对外提供统一查询服务。

本文通过简单的实验,演示 thanos 的分片数据采集与聚合查询能力,架构如下:
在这里插入图片描述

实验假设存在两个 prometheus 实例,分别采集不同的监控指标分片,prometheus 实例均通过 remote write 方式将数据写入 thanos receiver。receiver 采用多副本方式运行,并通过 hashring 方式实现将不同租户的数据写入不同的 receiver 实例,即 receiver 01 和 receiver 02 存储来自 prometheus foo 的监控指标数据,而 receiver 03 和 receiver 04 存储来自 prometheus bar 的监控指标数据,最后通过 thanos query 聚合多个 receiver 的数据,提供统一查询接口。

实验验证

本文基于 docker 方式启动 prometheus 以及 thanos,需要在机器上预装 docker。 Ubuntu 或 CentOS 环境,可以通过如下命令一件安装:

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

1. 部署 Prometheus 实例

# cat << EOF > prometheus-foo-conf.yaml
global:
 scrape_interval: 5s
 external_labels:
   cluster: foo
   replica: 0

scrape_configs:
 - job_name: 'prometheus'
   static_configs:
     - targets: ['127.0.0.1:9090']

remote_write:
- url: 'http://127.0.0.1:10908/api/v1/receive'
  headers:
   THANOS-TENANT: foo
EOF
# docker run -d --net=host --rm \
    -v $(pwd)/prometheus-foo-conf.yaml:/etc/prometheus/prometheus.yaml \
    -u root \
    --name prometheus-foo \
    quay.io/prometheus/prometheus:v2.27.0 \
    --config.file=/etc/prometheus/prometheus.yaml \
    --storage.tsdb.path=/prometheus \
    --web.listen-address=:9090 \
    --web.enable-lifecycle
# cat << EOF > prometheus-bar-conf.yaml
global:
 scrape_interval: 5s
 external_labels:
   cluster: bar
   replica: 0

scrape_configs:
 - job_name: 'prometheus'
   static_configs:
     - targets: ['127.0.0.1:9090']

remote_write:
- url: 'http://127.0.0.1:10908/api/v1/receive'
  headers:
   THANOS-TENANT: bar
EOF
# docker run -d --net=host --rm \
    -v $(pwd)/prometheus-bar-conf.yaml:/etc/prometheus/prometheus.yaml \
    -u root \
    --name prometheus-bar \
    quay.io/prometheus/prometheus:v2.27.0 \
    --config.file=/etc/prometheus/prometheus.yaml \
    --storage.tsdb.path=/prometheus \
    --web.listen-address=:9091 \
    --web.enable-lifecycle 

注意,我们在实验中通过给 prometheus 增加 cluster:foo 和 cluster:bar 的标签,来判断数据指标的来源,同时通过 remote_write 中的 headers 字段(THANOS-TENANT)区分不同的租户,以便 thanos receiver 分片存储。

2. 部署 Thanos Receiver 实例

# cat << EOF > hashring.json
[
    {
        "hashring": "foo",
        "endpoints": ["127.0.0.1:10907","127.0.0.1:10910"],
        "tenants": ["foo"]
    },
    {
        "hashring": "bar",
        "endpoints": ["127.0.0.1:10913","127.0.0.1:10916"],
        "tenants": ["bar"]
    }
]
EOF
# docker run -d --rm \
     --net=host \
     -v $(pwd)/hashring.json:/data/hashring.json \
     --name receive-01 \
     quay.io/thanos/thanos:v0.25.0 \
     receive \
     --tsdb.path "/receive/data" \
     --grpc-address 127.0.0.1:10907 \
     --receive.local-endpoint 127.0.0.1:10907 \
     --receive.hashrings-file=/data/hashring.json \
     --receive.replication-factor 2 \
     --label "receive_cluster=\"thanos\"" \
     --http-address 127.0.0.1:10909 \
     --remote-write.address 127.0.0.1:10908
 # docker run -d --rm \
     --net=host \
     -v $(pwd)/hashring.json:/data/hashring.json \
     --name receive-02 \
     quay.io/thanos/thanos:v0.25.0 \
     receive \
     --tsdb.path "/receive/data" \
     --grpc-address 127.0.0.1:10910 \
     --receive.local-endpoint 127.0.0.1:10910 \
     --receive.hashrings-file=/data/hashring.json \
     --receive.replication-factor 2 \
     --label "receive_cluster=\"thanos\"" \
     --http-address 127.0.0.1:10912 \
     --remote-write.address 127.0.0.1:10911
 # docker run -d --rm \
     --net=host \
     -v $(pwd)/hashring.json:/data/hashring.json \
     --name receive-03 \
     quay.io/thanos/thanos:v0.25.0 \
     receive \
     --tsdb.path "/receive/data" \
     --grpc-address 127.0.0.1:10913 \
     --receive.local-endpoint 127.0.0.1:10913 \
     --receive.hashrings-file=/data/hashring.json \
     --receive.replication-factor 2 \
     --label "receive_cluster=\"thanos\"" \
     --http-address 127.0.0.1:10915 \
     --remote-write.address 127.0.0.1:10914
  # docker run -d --rm \
     --net=host \
     -v $(pwd)/hashring.json:/data/hashring.json \
     --name receive-04 \
     quay.io/thanos/thanos:v0.25.0 \
     receive \
     --tsdb.path "/receive/data" \
     --grpc-address 127.0.0.1:10916 \
     --receive.local-endpoint 127.0.0.1:10916 \
     --receive.hashrings-file=/data/hashring.json \
     --receive.replication-factor 2 \
     --label "receive_cluster=\"thanos\"" \
     --http-address 127.0.0.1:10918 \
     --remote-write.address 127.0.0.1:10917

注意:所有 thanos receiver 使用的是同一份 hashring 配置,因此能够互相发现对端地址,根据租户标识实现 request 转发。每个 receiver 必须配置 --receive.local-endpoint 参数,并保证与 hashring 内配置的地址一致,才能正确实现 peer 间的互相发现。假如忘记给某个 receiver 配置该参数,会发生 context deadline exceeded 异常:

caller=handler.go:351 component=receive component=receive-handler msg="failed to handle request" err="context deadline exceeded"

3. 部署 Thanos Query 实例

3.1 仅连接 thanos receiver 01
# docker run -d --rm \
    --net=host \
    --name query \
    quay.io/thanos/thanos:v0.25.0 \
    query \
    --http-address "0.0.0.0:39090" \
    --store "127.0.0.1:10907"

仅能查看到 foo 的指标,证明已经按照租户分片存储了。
在这里插入图片描述

注意,–store 也可以指定 receiver 02 的地址,效果不变,因为我们设置了 --receive.replication-factor 2 副本复制。

3.2 仅连接 thanos receiver 03
# docker rm -f query
# docker run -d --rm \
    --net=host \
    --name query \
    quay.io/thanos/thanos:v0.25.0 \
    query \
    --http-address "0.0.0.0:39090" \
    --store "127.0.0.1:10913"

同理,仅能查看到 bar 的指标
在这里插入图片描述
注意,–store 也可以指定 receiver 04 的地址,效果不变,因为我们设置了 --receive.replication-factor 2 副本复制。

3.3 同时连接所有 receiver
# docker rm -f query
# docker run -d --rm \
    --net=host \
    --name query \
    quay.io/thanos/thanos:v0.25.0 \
    query \
    --http-address "0.0.0.0:39090" \
    --store "127.0.0.1:10907" \
    --store "127.0.0.1:10910" \
    --store "127.0.0.1:10913" \
    --store "127.0.0.1:10916"

可以看到,查询出的是最终聚合的指标(同时包含 foo 和 bar 两个 prometheus 实例采集的数据)

在这里插入图片描述

小结

当采集数据量过大时,我们可以将 prometheus 实例水平扩展,每个实例负责部分指标的采集工作(例如每个 prometheus 负责一个小集群的数据采集),然后使用 thanos 聚合来自不同 prometheus 的数据。thanos receiver 本身可以水平扩展,而且支持对 prometheus 数据写请求根据租户信息进行哈希,即负载均衡到不同的 receiver 上处理和存储,极大提升了系统的监控承载能力。而且 thanos query 支持聚合查询,提供了和 prometheus 原生的一致的查询接口,能够轻松实现 prometheus 的平滑扩展。

猜你喜欢

转载自blog.csdn.net/shida_csdn/article/details/123286254