4. Metrics 隔离架构:Prometheus 多租户方案(Thanos Receiver、Cortex 架构),租户数据分片与路由原理

在可观测性体系中,Metrics(指标)数据具有高基数、高写入频率、对存储与查询延迟敏感的特点。当多个租户共享同一套 Prometheus 兼容存储时,必须解决数据隔离、写入路由与查询权限三大核心问题。本章深入剖析业界主流的两种多租户方案——Thanos Receiver 与 Cortex,并揭示其背后的租户数据分片与路由机制。

4.1 多租户 Metrics 隔离的核心挑战

与日志(Logs)和链路(Traces)不同,Metrics 的隔离不能仅依赖标签过滤,因为 Prometheus 的存储模型天然缺乏租户边界。下表总结了 Metrics 多租户面临的主要挑战:

挑战维度 具体问题 影响
写入隔离 多个租户的指标数据可能写入同一 TSDB 块,导致数据混杂 无法按租户独立管理生命周期与保留策略
查询隔离 查询请求可能跨租户扫描数据,造成数据泄露或性能干扰 违反安全合规要求,查询延迟不可控
资源争抢 高基数租户的写入可能阻塞其他租户的查询 服务质量(QoS)无法保障
基数爆炸 单个租户的标签组合过多,导致存储与内存压力扩散 全局性能退化,难以定位问题源头
架构选择原则: 对于中小规模(< 100 个租户,每秒 < 50 万样本),推荐使用 Thanos Receiver 的“按租户分桶”模式;对于超大规模(> 1000 个租户,每秒 > 500 万样本),Cortex 的“哈希环 + 分布式分片”架构更具扩展性。

4.2 Thanos Receiver 多租户方案

Thanos Receiver 是 Thanos 组件中负责接收 Remote Write 请求的模块。其多租户实现基于请求路径中的租户标识提取与存储桶隔离,架构相对轻量。

4.2.1 租户识别与路由

Thanos Receiver 通过 HTTP Header 或 URL Path 提取租户 ID(Tenant ID),并将其作为数据写入与查询的上下文标识。

  • Header 方式: 客户端在 Remote Write 请求中携带 THANOS-TENANT 或 X-Scope-OrgID 头。
  • Path 方式: 请求路径形如 /api/v1/receive/{tenant_id}。
  • 路由逻辑: Receiver 根据租户 ID 将数据写入对应的本地 TSDB 实例或对象存储前缀。

4.2.2 存储隔离模型

Thanos Receiver 的存储隔离采用“每个租户一个独立存储桶前缀”的策略。其数据流如下:

┌─────────────┐     Remote Write (Header: tenant=A)     ┌──────────────────┐
│  Prometheus  │ ──────────────────────────────────────> │  Thanos Receiver │
│  (租户 A)    │                                         │  (多租户入口)     │
└─────────────┘                                         └────────┬─────────┘
                                                                  │
                                                                  ▼
                                                    ┌─────────────────────────┐
                                                    │  本地 TSDB (按租户分桶)   │
                                                    │  ├── tenant_A/          │
                                                    │  ├── tenant_B/          │
                                                    │  └── tenant_C/          │
                                                    └────────┬────────────────┘
                                                             │ 上传
                                                             ▼
                                                    ┌─────────────────────────┐
                                                    │  对象存储 (S3/GCS)       │
                                                    │  ├── tenant_A/           │
                                                    │  ├── tenant_B/           │
                                                    │  └── tenant_C/           │
                                                    └─────────────────────────┘
关键特性: Thanos Receiver 的租户隔离是“软隔离”——数据在物理上按前缀分开,但查询时仍需要 Store Gateway 根据租户 ID 过滤。如果 Store Gateway 未配置租户感知,仍可能跨租户扫描。

4.2.3 查询时的租户过滤

Thanos Querier 在查询时通过 --store 参数指定 Store API 端点,并传递租户 ID。Store Gateway 根据租户 ID 只读取对应前缀的 TSDB 块,实现查询隔离。

4.3 Cortex 多租户架构

Cortex 是专为多租户设计的 Prometheus 兼容系统,其架构将写入、存储、查询完全解耦,并通过哈希环(Hash Ring)实现租户数据的分片与路由。

4.3.1 核心组件与职责

组件 职责 多租户相关设计
Distributor 接收 Remote Write,验证租户 ID,复制数据并转发 基于租户 ID 的速率限制与认证
Ingester 内存中暂存最近数据,定期刷写到存储 每个租户独立的时间序列分片
Store Gateway 从对象存储读取历史数据块 按租户 ID 过滤块索引
Querier 合并 Ingester 与 Store Gateway 的查询结果 传递租户上下文,执行租户级聚合
Compactor 合并与压缩对象存储中的 TSDB 块 按租户独立执行压缩,避免跨租户数据混合

4.3.2 租户数据分片与路由原理

Cortex 使用一致性哈希环将租户的数据分片到多个 Ingester 实例上。其核心流程如下:

  1. 分片键计算: Distributor 对每个时间序列的 租户 ID + 指标名 + 标签集合 计算哈希值。
  2. 哈希环定位: 根据哈希值在一致性哈希环上找到负责该分片的 Ingester 实例(通常为 3 个副本)。
  3. 写入复制: Distributor 将样本数据并行写入所有副本 Ingester,确保高可用。
  4. 查询路由: Querier 根据查询的时间范围,向所有 Ingester 和 Store Gateway 发起请求,并在结果端按租户 ID 过滤。
注意: Cortex 的分片粒度是“时间序列”而非“租户”。这意味着一个租户的数据可能分布在多个 Ingester 上,但同一个时间序列的所有样本始终路由到同一组 Ingester。这种设计在租户内数据倾斜时可能导致热点,需要配合 Ingester 自动分片再均衡 机制缓解。

4.3.3 租户数据分片与路由架构图

Cortex 多租户数据分片与路由架构 Cortex 多租户数据分片与路由架构 租户 A 写入 租户 B 写入 Distributor 哈希分片 + 复制 一致性哈希环 I1 I2 I3 对象存储 tenant_A/ tenant_B/ Store Gateway 按租户 ID 过滤 Querier 合并 + 租户过滤 查询请求 (携带租户 ID) 分片路由关键点 • 哈希键:tenant+metric+labels • 副本数:3(默认) • 查询:全扫描 + 租户过滤

4.4 租户数据分片与路由原理对比

Thanos Receiver 与 Cortex 在分片与路由策略上有本质差异,下表从多个维度进行对比:

维度 Thanos Receiver Cortex
分片粒度 按租户 ID 分桶(粗粒度) 按时间序列哈希分片(细粒度)
路由依据 HTTP Header / Path 中的租户 ID 一致性哈希环 + 租户 ID + 标签哈希
数据分布 一个租户的数据集中在同一 Receiver 实例 一个租户的数据分散到多个 Ingester 实例
副本策略 Receiver 自身高可用(主备或负载均衡) Ingester 间复制(通常 3 副本)
查询隔离 Store Gateway 按前缀过滤 Querier 按租户 ID 过滤 + 索引过滤
热点风险 大租户可能导致单 Receiver 过载 高基数序列可能导致单 Ingester 热点
扩展性 水平扩展 Receiver 实例,但租户迁移复杂 天然支持水平扩展,分片自动再均衡

4.5 实践建议与避坑指南

选型建议:
  • 如果团队已有 Thanos 生态,且租户数量 < 50,优先使用 Thanos Receiver + 租户前缀隔离,运维成本低。
  • 如果预期租户数量快速增长或存在超大规模场景,直接选择 Cortex 或基于 Cortex 的 Grafana Mimir,其分片与路由机制更成熟。
  • 无论选择哪种方案,务必在 Distributor/Receiver 层配置租户级速率限制,防止单个租户的突发流量打垮全局。
常见陷阱:
  1. 租户 ID 泄露: 在 Thanos 中,如果 Store Gateway 未配置 --tenant-id 过滤,查询可能返回所有租户的数据。务必在 Querier 与 Store Gateway 之间传递租户上下文。
  2. 分片不均匀: Cortex 的哈希分片在租户内标签分布极度倾斜时(如某个指标有 1 亿个唯一标签组合),会导致单个 Ingester 内存暴涨。建议配合 Ingester 内存限制 与 自动分片再均衡 使用。
  3. 对象存储的租户前缀冲突: 在 Thanos 中,如果两个租户的 ID 相同但属于不同集群,对象存储前缀会冲突。建议使用 {cluster_id}/{tenant_id} 作为前缀。

4.6 小结

Metrics 的多租户隔离核心在于写入时的数据分片与查询时的上下文传递。Thanos Receiver 提供了轻量级的“按租户分桶”方案,适合中小规模;Cortex 则通过一致性哈希环实现了细粒度的分布式分片,适合超大规模场景。理解两者的分片与路由原理,是构建生产级 Metrics 多租户系统的关键。