概述

Prometheus 是云原生监控领域的事实标准,但它在长期数据存储和全局查询方面存在明显短板:本地存储默认只保留 15 天数据,单实例无法跨集群聚合查询,高可用方案也相对复杂。Thanos 作为 CNCF 孵化项目,通过将 Prometheus 数据上传到对象存储(如 S3、GCS、MinIO)实现了无限容量的长期存储,并通过分布式查询组件提供跨集群的全局视图。

将深入剖析 Thanos 的架构设计,并结合生产环境实战经验,详细讲解各组件的配置、部署和运维要点。

Thanos 解决了什么问题

在引入 Thanos 之前,我们首先需要理解 Prometheus 原生存储的局限性:

维度Prometheus 原生Thanos 增强
数据保留默认 15 天,受本地磁盘限制理论无限,依赖对象存储容量
高可用需要 Thanos Sidecar 或 remote_write 双写Sidecar + Query 天然支持
全局查询联邦方案,有限且易丢数据Query 组件聚合所有 Store API
降采样不支持Compactor 自动降采样,优化长周期查询
历史数据查询超出保留期即丢失可查询数月甚至数年前数据
跨集群视图需要额外联邦配置原生支持多集群统一查询

核心思路是:不改 Prometheus 本身,通过 Sidecar 旁路将数据上传到对象存储,再通过 Query 组件统一查询。这种设计保持了 Prometheus 的简单性,同时获得了企业级存储和查询能力。

核心架构与组件

整体架构

Thanos 的架构围绕"Sidecar 上传、Store 读取、Query 聚合"三个核心环节展开:

┌─────────────────────────────────────────────────────────┐
│                    对象存储 (S3/MinIO/GCS)                 │
│                                                          │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐              │
│  │ Block 1  │  │ Block 2  │  │ Block N  │              │
│  │ (2h raw) │  │ (5m down)│  │ (1h down)│              │
│  └──────────┘  └──────────┘  └──────────┘              │
│        ▲                                  ▲              │
│        │                                  │              │
│  ┌─────┴───────┐                  ┌──────┴──────┐       │
│  │  Sidecar    │                  │    Store    │       │
│  │  (上传Block) │                  │  (读取Block) │       │
│  └─────┬───────┘                  └──────┬──────┘       │
│        │                                  │              │
│  ┌─────┴───────┐                  ┌──────┴──────┐       │
│  │ Prometheus  │                  │   Compactor │       │
│  │  (本地TSDB) │                  │  (压缩+降采样)│       │
│  └─────────────┘                  └─────────────┘       │
│        │                                  │              │
│        └──────────┐    ┌──────────────────┘              │
│                   ▼    ▼                                  │
│              ┌──────────────┐                            │
│              │    Query     │  ◄── Grafana / PromQL     │
│              │  (全局查询)   │                            │
│              └──────┬───────┘                            │
│                     │                                    │
│              ┌──────┴───────┐                            │
│              │    Ruler     │  ──► Alertmanager         │
│              │ (全局告警评估) │                            │
│              └──────────────┘                            │
└─────────────────────────────────────────────────────────┘

组件职责

组件职责部署方式
Sidecar与 Prometheus 同 Pod 部署,将 TSDB Block 上传到对象存储,同时暴露 Store APIDaemonSet/Sidecar
Query聚合多个 Store API 后端的数据,执行 PromQL 查询,去重处理Deployment(多副本 HA)
Store Gateway从对象存储读取 Block 数据,暴露 Store API 给 QueryDeployment(多副本 HA)
Compactor压缩和降采样 Block 数据,执行保留策略单实例(StatefulSet)
Ruler评估告警规则,将告警发送给 AlertmanagerDeployment(多副本 HA)
Receiver通过 remote_write 接收 Prometheus 数据(可选,适用于 Sidecar 不便的场景)StatefulSet

参考 Thanos 官方架构文档 了解完整设计理念。

生产部署实践

前置准备:对象存储配置

以 MinIO(S3 兼容)为例,先准备 bucket 和访问凭证:

# 使用 mc 客户端创建 bucket
mc alias set thanos-minio http://minio:9000 thanos-admin thanos-password
mc mb thanos-minio/thanos-data
mc admin policy set thanos-minio readwrite user=thanos-admin

Thanos 对象存储配置文件 objstore.yml

type: S3
config:
  bucket: thanos-data
  endpoint: minio:9000
  region: ""
  access_key: thanos-admin
  secret_key: thanos-password
  insecure: true
  http_config:
    idle_conn_timeout: 90s
    response_header_timeout: 15s
    insecure_skip_verify: false
  trace:
    enable: false
  list_objects_version: "v2"

生产建议:access_key 和 secret_key 应通过 Kubernetes Secret 注入,不要明文写在 ConfigMap 中。上面示例仅用于演示。

Sidecar 部署

Sidecar 与 Prometheus 在同一 Pod 中运行,需要满足两个条件:

  1. Prometheus 启动时必须带 --storage.tsdb.min-block-duration=2h--storage.tsdb.max-block-duration=2h 参数
  2. Sidecar 需要 objstore.yml 配置来上传数据
# prometheus-with-thanos-sidecar.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: thanos-objstore-config
  labels:
    app.kubernetes.io/name: thanos
data:
  objstore.yml: |
    type: S3
    config:
      bucket: thanos-data
      endpoint: minio:9000
      access_key: thanos-admin
      secret_key: thanos-password
      insecure: true    
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: prometheus
  labels:
    app.kubernetes.io/name: prometheus
spec:
  serviceName: prometheus
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: prometheus
  template:
    metadata:
      labels:
        app.kubernetes.io/name: prometheus
        thanos-store: "true"
    spec:
      serviceAccountName: prometheus
      containers:
        - name: prometheus
          image: prom/prometheus:v2.55.0
          args:
            - "--config.file=/etc/prometheus/prometheus.yml"
            - "--storage.tsdb.path=/data"
            - "--storage.tsdb.retention.time=6h"
            - "--storage.tsdb.min-block-duration=2h"
            - "--storage.tsdb.max-block-duration=2h"
            - "--web.enable-lifecycle"
            - "--web.enable-admin-api"
          ports:
            - containerPort: 9090
              name: web
          volumeMounts:
            - name: config
              mountPath: /etc/prometheus
            - name: data
              mountPath: /data
        - name: thanos-sidecar
          image: thanosio/thanos:v0.37.0
          args:
            - "sidecar"
            - "--tsdb.path=/data"
            - "--prometheus.url=http://localhost:9090"
            - "--objstore.config-file=/etc/thanos/objstore.yml"
            - "--shipper.upload-compacted"
            - "--reloader.config-file=/etc/prometheus/prometheus.yml"
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          ports:
            - containerPort: 10902
              name: grpc
            - containerPort: 10901
              name: http
          volumeMounts:
            - name: data
              mountPath: /data
            - name: thanos-config
              mountPath: /etc/thanos
      volumes:
        - name: config
          configMap:
            name: prometheus-config
        - name: thanos-config
          configMap:
            name: thanos-objstore-config
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 50Gi

关键参数说明:

  • --storage.tsdb.retention.time=6h:本地只保留 6 小时数据,历史数据上传到对象存储后本地可清理
  • --storage.tsdb.min-block-duration=2h--max-block-duration=2h:确保 Block 大小固定为 2 小时,这是 Thanos 上传的前提
  • --shipper.upload-compacted:允许上传已压缩的 Block
  • --web.enable-admin-api:Sidecar 需要调用 Prometheus Admin API 来获取 Block 信息

Query 组件部署

Query 是 Thanos 的查询入口,负责从多个后端 Store API 收集数据并执行 PromQL:

# thanos-query.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: thanos-query
  labels:
    app.kubernetes.io/name: thanos-query
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: thanos-query
  template:
    metadata:
      labels:
        app.kubernetes.io/name: thanos-query
    spec:
      containers:
        - name: thanos-query
          image: thanosio/thanos:v0.37.0
          args:
            - "query"
            - "--grpc-address=0.0.0.0:10901"
            - "--http-address=0.0.0.0:10902"
            - "--log.level=info"
            - "--query.replica-label=prometheus_replica"
            - "--query.mode=distributed"
            - "--query.auto-downsampling"
            # 指向所有 Sidecar 的 Store API
            - "--store=dnssrv+_grpc._tcp.prometheus.default.svc.cluster.local"
            # 指向 Store Gateway
            - "--store=thanos-store-gateway:10901"
            # 指向 Ruler
            - "--store=thanos-ruler:10901"
          ports:
            - containerPort: 10902
              name: http
            - containerPort: 10901
              name: grpc
          resources:
            requests:
              cpu: 500m
              memory: 1Gi
            limits:
              cpu: 2
              memory: 4Gi
          livenessProbe:
            httpGet:
              path: /-/healthy
              port: http
          readinessProbe:
            httpGet:
              path: /-/ready
              port: http

去重关键--query.replica-label=prometheus_replica 告诉 Query 组件用哪个标签来识别同一数据的多个副本。如果两个 Prometheus 实例采集了相同指标,Query 会自动去重。

Store Gateway 部署

Store Gateway 充当对象存储的读取代理,让 Query 能查询到已上传的历史数据:

# thanos-store-gateway.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: thanos-store-gateway
  labels:
    app.kubernetes.io/name: thanos-store-gateway
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: thanos-store-gateway
  template:
    metadata:
      labels:
        app.kubernetes.io/name: thanos-store-gateway
    spec:
      containers:
        - name: thanos-store-gateway
          image: thanosio/thanos:v0.37.0
          args:
            - "store"
            - "--data-dir=/data"
            - "--grpc-address=0.0.0.0:10901"
            - "--http-address=0.0.0.0:10902"
            - "--objstore.config-file=/etc/thanos/objstore.yml"
            - "--cache-index-header"
          ports:
            - containerPort: 10902
              name: http
            - containerPort: 10901
              name: grpc
          volumeMounts:
            - name: data
              mountPath: /data
            - name: thanos-config
              mountPath: /etc/thanos
          resources:
            requests:
              cpu: 200m
              memory: 512Mi
            limits:
              cpu: 1
              memory: 2Gi
      volumes:
        - name: thanos-config
          configMap:
            name: thanos-objstore-config
        - name: data
          emptyDir: {}

Compactor 部署

Compactor 负责三件事:压缩 Block、执行降采样、执行保留策略。它是单实例部署,不能多副本:

# thanos-compactor.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: thanos-compactor
  labels:
    app.kubernetes.io/name: thanos-compactor
spec:
  serviceName: thanos-compactor
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: thanos-compactor
  template:
    metadata:
      labels:
        app.kubernetes.io/name: thanos-compactor
    spec:
      containers:
        - name: thanos-compactor
          image: thanosio/thanos:v0.37.0
          args:
            - "compact"
            - "--data-dir=/data"
            - "--objstore.config-file=/etc/thanos/objstore.yml"
            - "--compact.concurrency=4"
            - "--retention.resolution-raw=90d"
            - "--retention.resolution-5m=180d"
            - "--retention.resolution-1h=365d"
            - "--wait"
          ports:
            - containerPort: 10902
              name: http
          volumeMounts:
            - name: data
              mountPath: /data
            - name: thanos-config
              mountPath: /etc/thanos
          resources:
            requests:
              cpu: 200m
              memory: 512Mi
            limits:
              cpu: 1
              memory: 2Gi
      volumes:
        - name: thanos-config
          configMap:
            name: thanos-objstore-config
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Gi

保留策略是 Compactor 最关键的配置:

数据精度保留时长适用场景
Raw(原始)90 天短期精确查询、告警评估
5min 降采样180 天中期趋势分析
1h 降采样365 天长期容量规划、年度报告

降采样的原理是将 2 小时原始 Block 聚合为 5 分钟或 1 小时粒度的 Block,大幅减少数据量。例如 2 小时的原始数据可能有几百 MB,降采样到 1h 粒度后只有几 KB。

Ruler 部署

Ruler 允许在 Thanos 中定义和评估告警规则,规则评估基于全局数据而非单个 Prometheus 实例:

# thanos-ruler.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: thanos-ruler
  labels:
    app.kubernetes.io/name: thanos-ruler
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: thanos-ruler
  template:
    metadata:
      labels:
        app.kubernetes.io/name: thanos-ruler
    spec:
      containers:
        - name: thanos-ruler
          image: thanosio/thanos:v0.37.0
          args:
            - "rule"
            - "--grpc-address=0.0.0.0:10901"
            - "--http-address=0.0.0.0:10902"
            - "--data-dir=/data"
            - "--rule-file=/etc/thanos/rules/*.yaml"
            - "--alertmanagers.url=http://alertmanager:9093"
            - "--query=thanos-query:10902"
            - "--label=ruler_cluster=\"prod\""
            - "--label=replica=\"$(POD_NAME)\""
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          ports:
            - containerPort: 10902
              name: http
            - containerPort: 10901
              name: grpc
          volumeMounts:
            - name: rules
              mountPath: /etc/thanos/rules
            - name: data
              mountPath: /data
          resources:
            requests:
              cpu: 200m
              memory: 512Mi
            limits:
              cpu: 1
              memory: 2Gi
      volumes:
        - name: rules
          configMap:
            name: thanos-rules
        - name: data
          emptyDir: {}

告警规则文件示例 rules/global-alerts.yaml

groups:
  - name: thanos-component-health
    rules:
      - alert: ThanosSidecarDown
        expr: up{job="thanos-sidecar"} == 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Thanos Sidecar 不可用"
          description: "Prometheus {{ $labels.instance }} 的 Sidecar 已离线超过 5 分钟"

      - alert: ThanosCompactHalted
        expr: thanos_compactor_halted == 1
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Thanos Compactor 已暂停"
          description: "Compactor 组件处于 halted 状态,数据压缩和降采样已停止"

      - alert: ThanosQueryHighErrorRate
        expr: |
          sum(rate(thanos_query_concurrent_selects_gate_queries_in_flight[5m])) by (job)
          / sum(rate(thanos_query_range_requested_timespan_seconds_sum[5m])) by (job)
          > 0.05          
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Thanos Query 错误率过高"
          description: "Query 组件 {{ $labels.job }} 的查询错误率超过 5%"

高可用设计

Query 高可用

Query 组件本身是无状态的,只需多副本部署即可。前面通过 Kubernetes Service 自动负载均衡:

apiVersion: v1
kind: Service
metadata:
  name: thanos-query
spec:
  selector:
    app.kubernetes.io/name: thanos-query
  ports:
    - name: http
      port: 10902
      targetPort: 10902
    - name: grpc
      port: 10901
      targetPort: 10901

配合 Grafana 使用时,将 Grafana 的 Prometheus 数据源指向 http://thanos-query:10902 即可。

Prometheus 高可用

Prometheus 高可用的核心思路是:部署两个完全相同的 Prometheus 实例(通过 prometheus_replica 标签区分),它们采集相同的目标。Thanos Query 通过 --query.replica-label 自动去重:

# Prometheus 1
- "--storage.tsdb.retention.time=6h"
- "--storage.tsdb.min-block-duration=2h"
- "--storage.tsdb.max-block-duration=2h"
# 外部标签用于区分副本
external_labels:
  prometheus_replica: "prometheus-1"
  cluster: "prod-cluster"
# Prometheus 2
external_labels:
  prometheus_replica: "prometheus-2"
  cluster: "prod-cluster"

重要external_labels 中的 prometheus_replica 必须与 Query 的 --query.replica-label 参数一致。否则去重不会生效,查询结果会出现重复数据。

对象存储一致性

对象存储是 Thanos 的单点依赖。确保:

  1. MinIO 集群至少 4 节点,使用纠删码模式,容忍单节点故障
  2. 定期备份 bucket,防止误删
  3. 监控对象存储健康状态,Thanos Sidecar 上传失败会记录在 thanos_shipper_last_upload_success_timestamp_seconds 指标中

性能调优

查询性能优化

Thanos 查询性能受多个因素影响,以下是一些关键调优点:

# Query 调优参数
- "--query.timeout=2m"          # 单次查询超时
- "--query.max-concurrent=20"   # 最大并发查询数
- "--query.max-concurrent-select=4"  # 每个查询最大并发 Store API 调用
- "--query.auto-downsampling"   # 自动降采样
- "--query.replica-label=prometheus_replica"
- "--query.default-evaluation-interval=30s"

--query.auto-downsampling 是一个重要特性:当查询时间跨度较长时,Query 会自动选择合适的降采样数据,而非原始数据:

查询时间跨度自动选择精度
< 40 小时Raw(原始数据)
40h ~ 10 天5min 降采样
> 10 天1h 降采样

这能显著减少查询数据量和响应时间。例如查询 30 天的 CPU 使用率趋势,使用 1h 降采样数据只需要原始数据量的 1/720。

Store Gateway 缓存

Store Gateway 的索引头缓存对查询性能至关重要:

# 启用索引头缓存
- "--cache-index-header"
- "--store.caching-bucket.enabled=true"
- "--store.caching-bucket.max-size=1GB"

Compactor 性能

Compactor 处理大量 Block 时可能成为瓶颈:

# 提高并发
- "--compact.concurrency=4"
# Compactor 数据目录需要足够空间
# 建议至少 100GB SSD

监控 Compactor 的关键指标:

# 压缩任务耗时
thanos_compact_iterations_total

# 对象存储操作延迟
rate(thanos_objstore_bucket_operations_duration_seconds_sum[5m])
/ rate(thanos_objstore_bucket_operations_duration_seconds_count[5m])

# 降采样产生的 Block 数量
increase(thanos_compact_downsample_total[1h])

监控 Thanos 自身

关键指标

指标含义告警阈值建议
thanos_shipper_last_upload_success_timestamp_seconds最后一次成功上传时间超过 4 小时未上传
thanos_compactor_haltedCompactor 是否暂停== 1 时告警
thanos_query_concurrent_selects_gate_queries_in_flight正在执行的查询数持续接近 max-concurrent
thanos_objstore_bucket_operations_failures_total对象存储操作失败数持续增长
thanos_store_grpc_client_connections_inuseStore API 连接数突然降为 0
thanos_ruler_evaluation_failures_totalRuler 评估失败数持续增长

Thanos 自监控 Dashboard

推荐使用 Thanos 官方提供的 Grafana Dashboard 模板,ID 为 14388(Thanos Overview)和 14389(Thanos Receive)。

在 Grafana 中导入后,确保数据源指向 Thanos Query 组件。核心面板包括:

  1. 组件健康状态:各组件的 up 状态
  2. 上传延迟:Sidecar 上传 Block 的延迟趋势
  3. 查询延迟分布:P50/P95/P99 查询延迟
  4. 对象存储操作:读写延迟和错误率
  5. Compactor 运行状态:压缩和降采样进度

常见问题排查

Sidecar 上传失败

# 检查 Sidecar 日志
kubectl logs -l app.kubernetes.io/name=prometheus -c thanos-sidecar | grep -i "upload\|error"

# 检查对象存储连通性
kubectl exec -it prometheus-0 -c thanos-sidecar -- \
  thanos tools bucket verify \
  --objstore.config-file=/etc/thanos/objstore.yml

# 查看 Block 上传状态
kubectl exec -it prometheus-0 -c thanos-sidecar -- \
  thanos tools bucket inspect \
  --objstore.config-file=/etc/thanos/objstore.yml \
  --output=json

常见原因:

现象可能原因解决方案
上传报 403凭证权限不足检查 S3/MinIO 访问策略
Block 一直不上传Prometheus Block 未完成 2h 持续期检查 TSDB Block 配置
上传超时网络带宽不足增加 timeout 或优化网络
对象存储 bucket 满了存储配额限制扩容或调整保留策略

查询慢

# 查看 Query 的 Store API 连接状态
curl -s http://thanos-query:10902/api/v1/status/stores | jq .

# 分析慢查询
curl -s 'http://thanos-query:10902/api/v1/query?query=up' | jq .stats

优化方向:

  1. 启用 --query.auto-downsampling,长跨度查询使用降采样数据
  2. 增加 Store Gateway 副本数,分散读取压力
  3. 优化 PromQL 查询,避免高基数标签和全量 rate() 计算
  4. 检查对象存储读写延迟,必要时升级存储性能

Compactor 卡住

Compactor 卡住会导致数据不被压缩和降采样,最终影响查询性能:

# 检查 Compactor 状态
curl -s http://thanos-compactor:10902/api/v1/status/config | jq .

# 查看 Block 状态
kubectl exec thanos-compactor-0 -- \
  thanos tools bucket inspect \
  --objstore.config-file=/etc/thanos/objstore.yml

常见原因和解决:

  1. 磁盘空间不足:Compactor 需要临时空间来下载和压缩 Block。增加 PVC 容量或清理 --data-dir
  2. Block 损坏:使用 thanos tools bucket verify 检查并修复损坏的 Block
  3. 并发冲突:多副本 Compactor 同时操作。确保 Compactor 只有一个实例运行

多集群监控方案

Thanos 的一个重要场景是跨多个 Kubernetes 集群的统一监控。推荐架构:

集群 A                          集群 B
┌─────────────────────┐        ┌─────────────────────┐
│ Prometheus + Sidecar│        │ Prometheus + Sidecar│
│         │           │        │         │           │
│    ┌────▼────┐      │        │    ┌────▼────┐      │
│    │ Sidecar │──────┼────────┼───►│ Sidecar │      │
│    └─────────┘      │        │    └─────────┘      │
└─────────┬───────────┘        └─────────┬───────────┘
          │                              │
          ▼                              ▼
   ┌──────────────────────────────────────────┐
   │          对象存储 (S3/MinIO)              │
   └──────────────────┬───────────────────────┘
              ┌───────┴───────┐
              │ Store Gateway │
              └───────┬───────┘
              ┌───────┴───────┐
              │     Query     │ ◄── Grafana
              └───────┬───────┘
              ┌───────┴───────┐
              │     Ruler     │ ──► Alertmanager
              └───────────────┘

每个集群需要唯一的 external_labels,确保 Query 能区分数据来源:

# 集群 A 的 Prometheus
external_labels:
  cluster: "cluster-a"
  prometheus_replica: "prometheus-1"

# 集群 B 的 Prometheus
external_labels:
  cluster: "cluster-b"
  prometheus_replica: "prometheus-1"

在 Grafana 中可以通过 $cluster 变量切换查看不同集群的数据:

# 按集群查看 CPU 使用率
sum(rate(node_cpu_seconds_total{mode!="idle", cluster="$cluster"}[5m])) by (instance)

# 跨集群对比
sum(rate(node_cpu_seconds_total{mode!="idle"}[5m])) by (cluster)

成本优化

对象存储成本

Thanos 的主要成本来自对象存储。优化策略:

策略效果实施
调整保留策略减少 30-50% 存储量合理设置 raw/5m/1h 保留时长
采集间隔调大减少数据量从 15s 调整为 30s 或 60s
过滤无用指标减少数据量使用 metric_relabel_configs
生命周期策略自动降级存储配置 S3 Lifecycle 规则

计算资源成本

组件最低资源推荐资源扩展方式
Sidecar100m CPU / 128Mi200m / 512Mi每 Prometheus 一个
Query500m / 1Gi2 CPU / 4Gi多副本负载均衡
Store Gateway200m / 512Mi1 CPU / 2Gi多副本分散读取
Compactor200m / 512Mi1 CPU / 2Gi单实例
Ruler200m / 512Mi1 CPU / 2Gi多副本+去重

与其他方案对比

特性ThanosCortexVictoriaMetrics
架构模型Sidecar 旁路上传remote_write 中心化remote_write 中心化
对 Prometheus 改动无需改动需配置 remote_write需配置 remote_write
对象存储必须可选可选
全局查询原生支持原生支持原生支持
降采样Compactor 自动手动配置自动
多租户通过标签隔离原生支持原生支持
部署复杂度中等
社区活跃度CNCF 孵化CNCF 孵化独立项目

选择建议:

  • Thanos:适合已有 Prometheus 部署、不想改动采集方式、需要跨集群全局查询的场景
  • Cortex/Mimir:适合需要多租户、remote_write 中心化的 SaaS 场景
  • VictoriaMetrics:适合追求高性能和低资源消耗、可接受厂商锁定的场景

总结

Thanos 通过 Sidecar + 对象存储 + 分布式查询的架构,优雅地解决了 Prometheus 长期存储和全局查询的问题,同时保持了对 Prometheus 的零侵入。在生产部署中,需要重点关注以下几点:

  1. 对象存储是基石:确保 S3/MinIO 的高可用性和数据一致性,这是整个 Thanos 体系的单点依赖
  2. 合理设置保留策略:Raw 数据保留 90 天满足日常告警和排障需求,5min 和 1h 降采样数据分别保留 180 天和 365 天用于趋势分析
  3. 高可用从 Prometheus 开始:双副本 Prometheus + replica 标签 + Query 去重,是高可用的基础
  4. 监控 Thanos 自身:上传失败、Compactor 暂停、查询超时等问题都需要及时发现
  5. 成本可控:通过保留策略、采集间隔优化和指标过滤,将对象存储成本控制在合理范围内

Thanos 的设计哲学是"每个组件只做一件事,并做好它",这种 UNIX 风格的模块化设计使得每个组件可以独立部署、扩展和运维,非常适合大规模生产环境。

参考资源

参考资料与致谢

本文在撰写过程中参考了以下资料,感谢原作者的贡献:

  1. Prometheus TSDB 格式 — Prometheus 官方,参考了Prometheus TSDB 格式相关内容
  2. Google SRE Book — Monitoring Distributed Systems — Google SRE 团队,参考了Google SRE Book — Monitoring Distributed Systems相关内容
  3. Thanos 官方文档 — Thanos 项目,参考了Thanos 官方文档相关内容
  4. Thanos Bucket Inspector 工具 — Thanos 项目,参考了Thanos Bucket Inspector 工具相关内容
  5. Thanos 存储 API 设计 — Thanos 项目,参考了Thanos 存储 API 设计相关内容
  6. Thanos 官方架构文档 — Thanos 项目,参考了Thanos 官方架构文档相关内容