4. Metrics 隔离架构:Prometheus 多租户方案(Thanos Receiver、Cortex 架构),租户数据分片与路由原理
在可观测性体系中,Metrics(指标)数据具有高基数、高写入频率、对存储与查询延迟敏感的特点。当多个租户共享同一套 Prometheus 兼容存储时,必须解决数据隔离、写入路由与查询权限三大核心问题。本章深入剖析业界主流的两种多租户方案——Thanos Receiver 与 Cortex,并揭示其背后的租户数据分片与路由机制。
4.1 多租户 Metrics 隔离的核心挑战
与日志(Logs)和链路(Traces)不同,Metrics 的隔离不能仅依赖标签过滤,因为 Prometheus 的存储模型天然缺乏租户边界。下表总结了 Metrics 多租户面临的主要挑战:
| 挑战维度 | 具体问题 | 影响 |
|---|---|---|
| 写入隔离 | 多个租户的指标数据可能写入同一 TSDB 块,导致数据混杂 | 无法按租户独立管理生命周期与保留策略 |
| 查询隔离 | 查询请求可能跨租户扫描数据,造成数据泄露或性能干扰 | 违反安全合规要求,查询延迟不可控 |
| 资源争抢 | 高基数租户的写入可能阻塞其他租户的查询 | 服务质量(QoS)无法保障 |
| 基数爆炸 | 单个租户的标签组合过多,导致存储与内存压力扩散 | 全局性能退化,难以定位问题源头 |
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/ │
└─────────────────────────┘
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 实例上。其核心流程如下:
- 分片键计算: Distributor 对每个时间序列的
租户 ID + 指标名 + 标签集合计算哈希值。 - 哈希环定位: 根据哈希值在一致性哈希环上找到负责该分片的 Ingester 实例(通常为 3 个副本)。
- 写入复制: Distributor 将样本数据并行写入所有副本 Ingester,确保高可用。
- 查询路由: Querier 根据查询的时间范围,向所有 Ingester 和 Store Gateway 发起请求,并在结果端按租户 ID 过滤。
4.3.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 层配置租户级速率限制,防止单个租户的突发流量打垮全局。
- 租户 ID 泄露: 在 Thanos 中,如果 Store Gateway 未配置
--tenant-id过滤,查询可能返回所有租户的数据。务必在 Querier 与 Store Gateway 之间传递租户上下文。 - 分片不均匀: Cortex 的哈希分片在租户内标签分布极度倾斜时(如某个指标有 1 亿个唯一标签组合),会导致单个 Ingester 内存暴涨。建议配合 Ingester 内存限制 与 自动分片再均衡 使用。
- 对象存储的租户前缀冲突: 在 Thanos 中,如果两个租户的 ID 相同但属于不同集群,对象存储前缀会冲突。建议使用
{cluster_id}/{tenant_id}作为前缀。
4.6 小结
Metrics 的多租户隔离核心在于写入时的数据分片与查询时的上下文传递。Thanos Receiver 提供了轻量级的“按租户分桶”方案,适合中小规模;Cortex 则通过一致性哈希环实现了细粒度的分布式分片,适合超大规模场景。理解两者的分片与路由原理,是构建生产级 Metrics 多租户系统的关键。