3. Metric 标签基础:Prometheus 标签模型、标签的键值对结构、标签在时间序列中的唯一性作用
3.1 Prometheus 标签模型概述
在 Prometheus 生态中,标签(Label)是附加在时间序列上的键值对元数据,用于描述指标的维度特征。标签是区分不同时间序列的核心手段,也是实现租户隔离、聚合查询、告警路由的基础单元。
一个完整的 Prometheus 时间序列由以下三部分唯一确定:
- Metric Name(指标名):如
http_requests_total,描述被测量对象。 - Label Set(标签集):一组键值对,如
{method="GET", endpoint="/api/v1", tenant="acme"}。 - Timestamp + Value:时间戳与对应的采样值。
核心原则:Metric Name + Label Set 共同构成时间序列的 身份标识(Identity)。只要标签集不同,即使指标名相同,也视为不同的时间序列。
3.2 标签的键值对结构
标签由 Label Key(标签键)和 Label Value(标签值)组成,遵循以下规则:
| 属性 | 规则 | 示例 |
|---|---|---|
| Label Key | 只能包含字母、数字、下划线,必须以字母或下划线开头 | tenant_id、__name__、method |
| Label Value | 任意 Unicode 字符串,可为空 | "acme"、"GET"、"" |
| 保留前缀 | 以 __(双下划线)开头的 Key 为系统保留 |
__name__、__scheme__、__address__ |
| 最大数量 | 每个时间序列建议不超过 20 个标签 | 超过会导致性能下降 |
标签键值对在序列化时通常使用花括号包裹,例如:
http_requests_total{method="POST", endpoint="/api/order", tenant="tenant_a", status="200"}
3.3 标签在时间序列中的唯一性作用
标签是时间序列的 唯一性标识符。以下 SVG 展示了两个看似相同但实际不同的时间序列:
3.4 标签基数与租户隔离的冲突点
标签在带来灵活性的同时,也引入了 基数爆炸(Cardinality Explosion) 风险。在租户隔离场景下,常见的标签治理冲突包括:
| 冲突类型 | 描述 | 示例 |
|---|---|---|
| 标签键冲突 | 不同团队使用相同 Key 表示不同含义 | 租户 A 用 env 表示“环境”,租户 B 用 env 表示“加密版本” |
| 标签值泛滥 | 高基数标签导致时间序列数量失控 | user_id、request_id、session_id 等唯一值标签 |
| 租户标签缺失 | 未携带租户标识,无法按租户隔离查询 | 指标只有 {method, endpoint},缺少 tenant 标签 |
| 标签命名不规范 | 大小写混用、特殊字符、命名风格不统一 | TenantID vs tenant_id vs tenantId |
⚠️ 租户隔离红线:所有上报的指标 必须 携带统一的租户标签(如
tenant_id),且该标签的值必须来自认证鉴权系统,禁止客户端自行伪造。缺少租户标签的指标应被拒绝或丢弃。
3.5 标签治理最佳实践
在租户隔离的 Metric 体系中,标签治理应遵循以下原则:
- 统一标签命名规范:使用小写字母 + 下划线,如
tenant_id、service_name、region。 - 限制标签基数:每个标签的取值数量建议不超过 1000,避免使用
user_id、ip等高基数标签。 - 强制租户标签:在采集侧或代理侧注入
tenant_id标签,确保每条时间序列都可归属到具体租户。 - 标签白名单机制:只允许预定义的标签键通过,拒绝未知标签。
- 标签值长度控制:标签值不宜过长,建议不超过 128 字符。
以下 SVG 展示了从指标采集到存储的标签治理流程:
💡 实践建议:在 Prometheus 的
relabel_configs 或代理层(如 OpenTelemetry Collector)中实现标签注入与校验,避免在应用代码中手动处理租户标签,降低耦合度。