WEBKT

Prometheus Remote Storage 实战:Thanos、Mimir、VictoriaMetrics 选型与架构避坑指南

3 0 0 0

从磁盘告警说起:为什么必须 Offload 历史数据

凌晨三点的告警响起,Prometheus 所在节点的磁盘使用率突破 90%。你熟练地清理了旧数据,但心里清楚——这只是权宜之计。随着微服务规模膨胀,单节点 Prometheus 的本地 TSDB 已成为整个监控体系的阿喀琉斯之踵:

  • ** retention 瓶颈**:SSD 成本下,30 天以上的原始数据存储几乎不可承受
  • 查询爆炸:大时间范围查询瞬间吃满内存,触发 OOMKilled
  • 高可用困境:联邦集群架构复杂,全局视图查询延迟高

Remote Storage 方案通过 remote_write 接口将历史数据卸载到分布式后端,是解决上述痛点的标准路径。但面对 Thanos、Grafana Mimir、VictoriaMetrics 三大主流方案,如何设计一个既满足成本控制又保证查询体验的架构?

Remote Write 机制:不只是"数据搬运"

在选型之前,必须理解 remote_write 的工作机制,这直接决定了你的架构设计约束。

WAL 与异步发送

Prometheus 将抓取的样本先写入本地 Write-Ahead Log (WAL),remote_write 组件通过 Tail 方式读取 WAL,将数据转换为 Prometheus Remote Write 协议(基于 Snappy 压缩的 Protobuf)批量发送至远端。关键参数:

remote_write:
  - url: "http://mimir:9090/api/v1/push"
    queue_config:
      capacity: 10000          # 单分片队列深度
      max_samples_per_send: 2000
      batch_send_deadline: 5s  # 延迟敏感场景调低
      retry_on_rate_limit: true
    metadata_config:
      send: true               # 必须开启,否则丢 Metric 元数据

内存与网络权衡

高危认知误区:认为 remote_write 只是简单的网络转发。实际上,每个 remote_write 目标会独立维护一个内存队列(shard)。当网络抖动或后端压力过大时,队列积压会直接导致 Prometheus 内存占用飙升。生产环境建议:

  • 单 Prometheus 实例 remote_write 目标不超过 3 个(避免内存碎片化)
  • 启用 write_relabel_configs 提前过滤无用指标,减少 30%-50% 网络流量
  • 务必配置 max_retriesretry_on_rate_limit,防止雪崩

三大后端架构对决

Thanos:云原生生态的"瑞士军刀"

适用场景:已深度使用 Kubernetes,需要多集群联邦查询,团队具备一定运维能力。

架构要点
Thanos Sidecar 模式与 remote_write 模式是互斥的选型。对于历史数据 offload 场景,推荐 Thanos Receive 组件:

┌─────────────┐     remote_write      ┌─────────────────┐
│ Prometheus  │ ────────────────────> │ Thanos Receive  │ ◄── 多租户验证
└─────────────┘                       └────────┬────────┘
                                               │
                         ┌─────────────────────┼─────────────────────┐
                         ▼                     ▼                     ▼
                  ┌─────────────┐       ┌─────────────┐       ┌─────────────┐
                  │  Object     │       │  Store      │       │  Query      │
                  │  Storage    │<──────│  Gateway    │<──────│  Frontend   │
                  └─────────────┘       └─────────────┘       └─────────────┘

核心优势

  • 支持对象存储(S3/GCS/MinIO)作为冷存储,成本极低
  • 提供 Downsampling(降采样)能力,查询 30 天前数据自动切换至 5m/1h 分辨率
  • 兼容 Prometheus Query API,Grafana 数据源配置零迁移成本

实施陷阱

  • Thanos Receive 的多租户实现基于 HTTP HeaderTHANOS-TENANT),需要前端网关(如 Nginx/OpenTelemetry Collector)做租户隔离,直接暴露 Receive 端口存在数据污染风险
  • Compactor 组件是单点,处理 PB 级数据时需要 64GB+ 内存,建议独立节点部署

Grafana Mimir:托管体验的自托管方案

适用场景:Grafana Cloud 用户希望自建,或需要强多租户隔离的企业环境。

架构差异
Mimir 采用微服务架构,但提供 monolithic mode(单体模式)简化部署:

# mimir-values.yaml 关键配置
mimir:
  structuredConfig:
    limits:
      ingestion_rate: 100000
      max_global_series_per_user: 10000000
    blocks_storage:
      backend: s3
      s3:
        bucket_name: mimir-metrics
        endpoint: minio.monitoring.svc:9000
        access_key_id: ${ACCESS_KEY}
        secret_access_key: ${SECRET_KEY}

选型价值

  • 原生多租户:基于 X-Scope-OrgID Header,无需额外网关
  • 查询并行化:Query-Frontend 自动拆分大范围查询,避免单次请求压垮系统
  • 与 Grafana 深度集成:Ruler 告警状态可直接在 Grafana 面板查看

性能基准(基于 100K samples/sec 写入压力):

  • 内存占用:Mimir(8GB)< Thanos Receive(12GB)< VM(6GB)
  • 查询 P99 延迟:VM(15ms)< Mimir(45ms)< Thanos(80ms,无降采样时)

VictoriaMetrics:性能怪兽与极简运维

适用场景:追求极致资源效率,或中小团队缺乏专职 SRE。

单节点架构的魔力
VictoriaMetrics 的单节点版本(vmstorage + vminsert + vmselect 合并)可在 8C16G 机器上处理 1000万+ 活跃时间线,这是 Thanos 和 Mimir 分布式架构难以企及的资源效率。

remote_write 特殊优化
VM 实现了本地缓存机制,当后端暂时不可用时,数据会暂存本地磁盘而非内存,避免 Prometheus OOM:

# 在 Prometheus 端配置 vmagent 替代原生 remote_write(可选但推荐)
# vmagent 提供更高效的聚合与重试机制
remote_write:
  - url: "http://vminsert:8480/insert/0/prometheus/api/v1/write"
    # VM 支持 VictoriaMetrics 原生协议,比 Prometheus remote_write 节省 40% 带宽

限制与妥协

  • 多租户支持较弱(需通过 URL 路径区分,如 /insert/tenant_01/...
  • 生态工具链不如 Thanos 丰富(如缺少类似 Thanos Ruler 的灵活告警评估)

生产架构设计模式

模式一:双写热备(Hot-Standby)

当需要 99.99% 可用性时,采用双后端写入:

remote_write:
  - url: "http://mimir-primary/api/v1/push"
    name: "mimir-primary"
    queue_config:
      max_samples_per_send: 5000
  - url: "http://victoriametrics-backup/api/v1/write"
    name: "vm-backup"
    write_relabel_configs:
      # 仅备份关键业务指标,降低成本
      - source_labels: [__name__]
        regex: "(up|node_cpu_seconds_total|container_memory_usage_bytes)"
        action: keep

关键点:Grafana 数据源配置 Failover,主集群超时自动切换至备集群。

模式二:分层存储(Tiered Storage)

近实时数据(0-7d):保留在 Prometheus 本地,保证告警计算延迟 < 5s
中期数据(7d-30d):写入 Mimir/VM,用于日常排障查询
历史数据(30d+):Thanos 对象存储,用于容量规划与合规审计

实施方式:Prometheus 设置 --storage.tsdb.retention.time=7d,同时 remote_write 全量推送;查询时通过 Grafana 的 Mixed 数据源合并展示。

模式三:边缘汇聚(Edge Aggregation)

多地域部署场景,边缘 Prometheus 先写入本地 VM 单节点(降低跨地域带宽),中心 Thanos Query 通过 StoreAPI 联邦查询各地域 VM 的 vmselect 组件。

避坑清单:那些血与泪的教训

  1. 指标基数爆炸(Cardinality Explosion)
    未经优化的 remote_write 会将所有 label 组合推送至后端。曾遇到某服务将 user_id 作为 label 导致每秒新增 10 万时间线,压垮 Mimir。务必在 Prometheus 端配置 metric_relabel_configs 丢弃高基数 label。

  2. 时间戳乱序(Out-of-Order)
    某些 exporter(如自定义脚本)可能产生乱序数据。Thanos Receive 默认拒绝乱序样本,需开启 --tsdb.out-of-order.time-window=5m;VM 则原生支持乱序写入,更适合边缘场景。

  3. 网络分区下的数据黑洞
    当 Prometheus 与后端网络中断超过 queue_config.max_samples_per_send * capacity,数据将永久丢失。建议启用 WAL 保留(Prometheus v2.25+ 支持 wal_truncate_frequency 调整),或部署 vmagent 作为中间层提供磁盘缓冲。

  4. 查询结果不一致
    Remote Storage 与本地 Prometheus 存在复制延迟(通常 5-30s)。Grafana 面板同时查询两者时,会出现"曲线断裂"。解决方案:统一查询入口,全部走 Thanos Query/Mimir Query-Frontend,不再直接查询本地 Prometheus。

选型决策树

  • 团队规模 < 5 人,无专职 SRE → VictoriaMetrics 单节点,最快落地
  • 已使用 Grafana Cloud,追求生态一致性 → Mimir,享受无缝集成
  • 多集群联邦查询,需要对象存储降成本 → Thanos,长期可扩展性最佳
  • 混合云环境,边缘节点众多 → VictoriaMetrics(边缘)+ Thanos(中心)组合架构

监控体系的远程化改造不是简单的配置切换,而是存储架构的重构。建议先在非核心集群试点,验证数据完整性(使用 promtool query 对比本地与远端指标计数)后,再逐步切生产流量。记住:最好的架构是团队能Hold住的架构,而非功能最全的那个。

云原生架构师 PrometheusThanos云原生监控

评论点评