前言
上次,我们介绍了如何使用联邦集群做出数据统一展示的效果. 但是官方原本的集群模式却有一些棘手的问题.
比如:数据去重
那我们这次就介绍一下Thanos 这款CNCF孵化的组件.
What is Thanos ?
开胃小菜, 简单尝试
一个简单的Thanos架构

- 我们拥有一个
eu1集群
- 我们拥有两个节点的集群
us1,他们的配置相同,只是为了高可用
Prometheus
我们为EU Prometheus 配置 prometheus0_eu1.yml
1 2 3 4 5 6 7 8 9 10 11
| global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: eu1 replica: 0
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['127.0.0.1:9090']
|
为剩下两个配置
prometheus0_us1.yml
1 2 3 4 5 6 7 8 9 10 11
| global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: us1 replica: 0
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['127.0.0.1:9091','127.0.0.1:9092']
|
prometheus1_us1.yml
1 2 3 4 5 6 7 8 9 10 11
| global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: us1 replica: 1
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['127.0.0.1:9091','127.0.0.1:9092']
|
创建数据目录
1
| mkdir -p prometheus0_eu1_data prometheus0_us1_data prometheus1_us1_data
|
运行”EU1”
1 2 3 4 5 6 7 8 9 10 11
| docker run -d --net=host --rm \ -v $(pwd)/prometheus0_eu1.yml:/etc/prometheus/prometheus.yml \ -v $(pwd)/prometheus0_eu1_data:/prometheus \ -u root \ --name prometheus-0-eu1 \ quay.io/prometheus/prometheus:v2.14.0 \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/prometheus \ --web.listen-address=:9090 \ --web.enable-lifecycle \ --web.enable-admin-api && echo "Prometheus EU1 started!"
|
运行”US1”
1 2 3 4 5 6 7 8 9 10 11
| docker run -d --net=host --rm \ -v $(pwd)/prometheus0_us1.yml:/etc/prometheus/prometheus.yml \ -v $(pwd)/prometheus0_us1_data:/prometheus \ -u root \ --name prometheus-0-us1 \ quay.io/prometheus/prometheus:v2.14.0 \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/prometheus \ --web.listen-address=:9091 \ --web.enable-lifecycle \ --web.enable-admin-api && echo "Prometheus 0 US1 started!"
|
1 2 3 4 5 6 7 8 9 10 11
| docker run -d --net=host --rm \ -v $(pwd)/prometheus1_us1.yml:/etc/prometheus/prometheus.yml \ -v $(pwd)/prometheus1_us1_data:/prometheus \ -u root \ --name prometheus-1-us1 \ quay.io/prometheus/prometheus:v2.14.0 \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/prometheus \ --web.listen-address=:9092 \ --web.enable-lifecycle \ --web.enable-admin-api && echo "Prometheus 1 US1 started!"
|
Thanos Sidecars
顾名思义,Sidecar正如它的名字一样,他需要与Prometheus 一起部署. sidecar 具有多个功能
- 它可以将Prometheus的数据暴露出去,允许其他组件进行访问
- 它能监视配置文件的修改,并通知Prometheus动态的重启加载
安装
为了让Thanos有效地查询Prometheus数据,让我们在上一步中部署的每个Prometheus实例上安装sidecar,如下所示:

针对于前两个功能,我们需要配置sidecar对prometheus的 API 和 配置文件访问, 以便我们可以访问Prometheus的指标和实时重载Prometheus的配置.
为”EU1” Prometheus 添加 Sidecar
1 2 3 4 5 6 7 8 9 10
| docker run -d --net=host --rm \ -v $(pwd)/prometheus0_eu1.yml:/etc/prometheus/prometheus.yml \ --name prometheus-0-sidecar-eu1 \ -u root \ quay.io/thanos/thanos:v0.17.0 \ sidecar \ --http-address 0.0.0.0:19090 \ --grpc-address 0.0.0.0:19190 \ --reloader.config-file /etc/prometheus/prometheus.yml \ --prometheus.url http:
|
为 “US1” 添加
1 2 3 4 5 6 7 8 9 10
| docker run -d --net=host --rm \ -v $(pwd)/prometheus0_us1.yml:/etc/prometheus/prometheus.yml \ --name prometheus-0-sidecar-us1 \ -u root \ quay.io/thanos/thanos:v0.17.0 \ sidecar \ --http-address 0.0.0.0:19091 \ --grpc-address 0.0.0.0:19191 \ --reloader.config-file /etc/prometheus/prometheus.yml \ --prometheus.url http:
|
1 2 3 4 5 6 7 8 9 10
| docker run -d --net=host --rm \ -v $(pwd)/prometheus1_us1.yml:/etc/prometheus/prometheus.yml \ --name prometheus-1-sidecar-us1 \ -u root \ quay.io/thanos/thanos:v0.17.0 \ sidecar \ --http-address 0.0.0.0:19092 \ --grpc-address 0.0.0.0:19192 \ --reloader.config-file /etc/prometheus/prometheus.yml \ --prometheus.url http:
|
检查
让我们检查sidecar是否运行成功。
让我们修改配置文件,并查看prometheus是否可以动态更新配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: eu1 replica: 0
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['127.0.0.1:9090'] - job_name: 'sidecar' static_configs: - targets: ['127.0.0.1:19090']
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: us1 replica: 0
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['127.0.0.1:9091','127.0.0.1:9092'] - job_name: 'sidecar' static_configs: - targets: ['127.0.0.1:19091','127.0.0.1:19092']
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: us1 replica: 1
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['127.0.0.1:9091','127.0.0.1:9092'] - job_name: 'sidecar' static_configs: - targets: ['127.0.0.1:19091','127.0.0.1:19092']
|
当然, 如果使用vim 以及其他编辑器修改的, 容器内的配置文件并不会生效,因为编辑器在编辑的时候会新建一个隐藏文件来报错用户编辑的数据,当用户保存的时候,就覆盖文件。
而Docker挂载文件是硬链接, 所以容器内的更改是不会生效的。
当然, 如果我们挂载配置文件目录,或者使用k8s的configmap挂载,就不会出现这样的问题。
手动重启
1
| docker restart prometheus-0-eu1 prometheus-0-us1 prometheus-1-us1
|
Thanos Querier
我们已经安装了 prome集群 并且已经部署好了sidecar, 那么我们如何在同一的地方去查询这些数据呢?
这时候就需要 querier 了

部署 Querier
其中 --store 需要我们确保指向的是sidecar的gRPC 地址
1 2 3 4 5 6 7 8 9
| docker run -d --net=host --rm \ --name querier \ quay.io/thanos/thanos:v0.17.0 \ query \ --http-address 0.0.0.0:29090 \ --query.replica-label replica \ --store 127.0.0.1:19190 \ --store 127.0.0.1:19191 \ --store 127.0.0.1:19192 && echo "Started Thanos Querier"
|
我们访问 0.0.0.0:29090

让我们查询一个指标
prometheus_config_last_reload_successful

我们可以看到,查询出来的数据被去重了.
我们取消 deduplication

我们发现,数据从3条变成了5条. 出现了2条重复数据
那么! querier 是如何进行去重的呢?
答案就在我们启动参数中 --query.replica-label replica
此选项指定了 replica 标签
意思就是说, 如果遇到其他标签内容相同,但是唯独replica标签不同的数据,则判断为重复数据,从而去重
比如:
us1 集群因为部署了两个副本,所以数据有这样的两条
1 2
| cluster="us1",instance="127.0.0.1:9092",job="prometheus",replica="0" cluster="us1",instance="127.0.0.1:9092",job="prometheus",replica="1"
|
我们可以看到, 除了replica标签完全一样,那么这条数据去重重复的标签以后只剩下一个标签
这个时候,querier 就判定这个为重复数据
那假如说标签是这样呢?
1 2
| cluster="us1",instance="127.0.0.1:9092",job="prometheus",replica="0",bbb='d' cluster="us1",instance="127.0.0.1:9092",job="prometheus",replica="1",ccc='d'
|
去重以后
1 2
| replica="0",bbb='d' replica="1",ccc='d'
|
因为去重以后除了replica还剩下bbb,ccc标签,所以这条数据并不算重复
紧追不舍,初尝战果
上一个小节,我们简单的尝试了Thanos在多地域多副本Prometheus架构下的使用. Thanos通过sidecar的方式,无侵入的接管Prometheus的查询接口,并在内部通过label的方式实现了多副本去重的功能.
但是,我们发现,Thanos也只是单纯的从Prometheus查询数据.只是个工具人罢了. 而Prometheus还是需要将数据本地保留下来.那我们有没有方法将Prometheus本地数据缩短保留时间,并且以一种低成本的方式保留更长久的监控数据呢?
那么在这一节, 我们要研究一下,如何将监控数据持久的保留下来。
生成监控数据
要模仿长久的数据,肯定要生成一点数据,当然,我们在本地测试肯定是没有这么多的数据的,那怎么办,当然是借助工具生成一些拉。
1
| mkdir -p /root/prom-eu1 && docker run -i quay.io/thanos/thanosbench:v0.2.0-rc.1 block plan -p continuous-365d-tiny --labels 'cluster="eu1"' --max-time=6h | docker run -v /root/prom-eu1:/prom-eu1 -i quay.io/thanos/thanosbench:v0.2.0-rc.1 block gen --output.dir prom-eu1
|
查看生成的数据
创建配置文件prometheus0_eu1.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| global: scrape_interval: 5s external_labels: cluster: eu1 replica: 0 tenant: team-eu # 这个不是必须的,但是为了后续扩展多租户,要预先保留
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['127.0.0.1:9090'] - job_name: 'sidecar' static_configs: - targets: ['127.0.0.1:19090'] - job_name: 'minio' metrics_path: /minio/prometheus/metrics static_configs: - targets: ['127.0.0.1:9000'] - job_name: 'querier' static_configs: - targets: ['127.0.0.1:9091'] - job_name: 'store_gateway' static_configs: - targets: ['127.0.0.1:19092']
|
启动容器
有几个点需要注意一下
-v /root/prom-eu1:/prometheus --storage.tsdb.path=/prometheus 这里将我们生成的数据挂载到容器中
--storage.tsdb.retention.time=1000d 我们修改了Prome默认数据保留的时间,默认是15天,但是我们的数据有一年.
--storage.tsdb.max-block-duration=2h --storage.tsdb.min-block-duration=2h 这两个参数设置为相同,则禁用Prometheus的压缩功能.我们需要把这个功能禁用,因为后续我们Thanos会帮我们压缩.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| docker run -d --net=host --rm \ -v $(pwd)/prometheus0_eu1.yml:/etc/prometheus/prometheus.yml \ -v /root/prom-eu1:/prometheus \ -u root \ --name prometheus-0-eu1 \ quay.io/prometheus/prometheus:v2.20.0 \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.retention.time=1000d \ --storage.tsdb.path=/prometheus \ --storage.tsdb.max-block-duration=2h \ --storage.tsdb.min-block-duration=2h \ --web.listen-address=:9090 \ --web.enable-lifecycle \ --web.enable-admin-api
|
验证

不出所料,我们可以看到1年的数据
启动 Thanos Sidecar & Querier
1 2 3 4 5 6 7 8
| docker run -d --net=host --rm \ --name prometheus-0-eu1-sidecar \ -u root \ quay.io/thanos/thanos:v0.16.0 \ sidecar \ --http-address 0.0.0.0:19090 \ --grpc-address 0.0.0.0:19190 \ --prometheus.url http://127.0.0.1:9090
|
我们需要将--store 指向 sidecar的 gRPC地址!!
1 2 3 4 5 6 7
| docker run -d quay.io/thanos/thanos:v0.16.0 \ query \
|
验证
访问:0.0.0.0:9091

我们现在可以通过querier的UI面板访问我们一年的数据
设置对象存储: Minio
1 2 3 4 5 6
| mkdir /root/minio && \ docker run -d --rm --name minio \ -v /root/minio:/data \ -p 9000:9000 -e "MINIO_ACCESS_KEY=momo" -e "MINIO_SECRET_KEY=melovemomo" \ minio/minio:RELEASE.2019-01-31T00-31-19Z \ server /data
|
创建thanos bucket
1
| mkdir /root/minio/thanos
|
验证
打开浏览器:http:127.0.0.1:9000
Access Key = momo Secret Key=melovemomo
设置对象存储为Sidecar的后端存储
bucket_storage.yaml
1 2 3 4 5 6 7 8
| type: S3 config: bucket: "thanos" endpoint: "127.0.0.1:9000" insecure: true signature_version2: true access_key: "momo" secret_key: "melovemomo"
|
现在我们重新配置,所以停止容器
1
| docker stop prometheus-0-eu1-sidecar
|
- 通过
--tsdb.path /prometheus 指定Prometheus的数据位置
- 指定后端存储的配置文件
--objstore.config-file /etc/thanos/minio-bucket.yaml
- 如果我们需要迁移已经存在的数据.(我们当然需要迁移)则使用
--shipper.upload-compacted
万事俱备,让我们开始吧!!
1 2 3 4 5 6 7 8 9 10 11 12 13
| docker run -d --net=host --rm \ -v $(pwd)/bucket_storage.yaml:/etc/thanos/minio-bucket.yaml \ -v /root/prom-eu1:/prometheus \ --name prometheus-0-eu1-sidecar \ -u root \ quay.io/thanos/thanos:v0.16.0 \ sidecar \ --tsdb.path /prometheus \ --objstore.config-file /etc/thanos/minio-bucket.yaml \ --shipper.upload-compacted \ --http-address 0.0.0.0:19090 \ --grpc-address 0.0.0.0:19190 \ --prometheus.url http:
|
验证
太棒了!我们所有的数据都备份到了桶中

Store GateWay
我们创建了存储桶,并且设置了后端的存储. 但是我们如何去查询Prometheus已经删除的历史数据呢?
这个时候就需要 Store GateWay 登场了.
这个组件的作用,只是一个API网关,负责向不同后端存储发出查询功能.所以本地并不需要很多的空间.
启动
1 2 3 4 5 6 7 8
| docker run -d --net=host --rm \ -v $(pwd)/bucket_storage.yaml:/etc/thanos/minio-bucket.yaml \ --name store-gateway \ quay.io/thanos/thanos:v0.16.0 \ store \ --objstore.config-file /etc/thanos/minio-bucket.yaml \ --http-address 0.0.0.0:19091 \ --grpc-address 0.0.0.0:19191
|
如何查询到存储数据?
我们需要重新对querier进行一些设置.
因为它目前还没有跟我们的store gateway有联系
1 2 3 4 5 6 7 8 9
| docker stop querier && \ docker run -d --net=host --rm \ --name querier \ quay.io/thanos/thanos:v0.16.0 \ query \ --http-address 0.0.0.0:9091 \ --query.replica-label replica \ --store 127.0.0.1:19190 \ --store 127.0.0.1:19191
|
我们设置了querier的store参数
分别为两个,第一个是查询源数据,获取实时数据, 另一个是查询存储桶,获取之前的日志.
那么就会有同学要问了, 如果是多个sidecar同时上传相同的数据,那OSS存储中的数据也会重复吗?
哈哈,答案是: 数据当然会重复
不过小伙伴不用担心, 因为重复数据是不可避免的.我们在上面也知道,querier组件在查询的时候会根据标签去重.
当然,不少小伙伴还在想,存储中的数据重复怎么办?这不是浪费吗?这时候我们就需要引出我们下一个组件
Thanos Compactor
Thanos Compactor
此组件将会对TSDB块数据对象存储执行,压缩,保留,删除, 以及downsampling操作
同时,他会负责数据的下采样,让查询范围大的数据更快. 在40小时后执行5m的下采样,在10天后执行1h的下采样。
启动
默认只会执行一次,使用--wait --wait-interval 30s 来让他每30s循环执行
1 2 3 4 5 6 7 8 9
| docker run -d --net=host --rm \ -v $(pwd)/bucket_storage.yaml:/etc/thanos/minio-bucket.yaml \ --name thanos-compact \ quay.io/thanos/thanos:v0.16.0 \ compact \ --wait --wait-interval 30s \ --consistency-delay 0s \ --objstore.config-file /etc/thanos/minio-bucket.yaml \ --http-address 0.0.0.0:19095
|
通过 连接查询状态 http://127.0.0.1:19095/new/loaded
到此,我们就解决了如何持久保存监控数据的问题.并且Prometheus也可以以一种几乎无状态的方式运行.