标签与标签选择器 #
一、标签概述 #
1.1 什么是标签 #
text
标签定义:
┌─────────────────────────────────────────────┐
│ 标签是键值对,用于区分同一指标的不同维度 │
└─────────────────────────────────────────────┘
示例:
http_requests_total{method="GET", status="200", instance="localhost:8080"}
解析:
┌─────────────────────────────────────────────┐
│ 指标名称:http_requests_total │
├─────────────────────────────────────────────┤
│ 标签: │
│ method="GET" │
│ status="200" │
│ instance="localhost:8080" │
├─────────────────────────────────────────────┤
│ 标签组合唯一标识一个时间序列 │
└─────────────────────────────────────────────┘
不同的标签值 = 不同的时间序列:
http_requests_total{method="GET", status="200"} # 时间序列1
http_requests_total{method="GET", status="404"} # 时间序列2
http_requests_total{method="POST", status="200"} # 时间序列3
1.2 标签类型 #
text
标签分类:
┌─────────────────────────────────────────────┐
│ 1. 应用标签 │
├─────────────────────────────────────────────┤
│ • 由应用程序定义 │
│ • 反映业务逻辑 │
│ • 示例:method, status, endpoint │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ 2. 目标标签 │
├─────────────────────────────────────────────┤
│ • 由Prometheus配置添加 │
│ • 标识数据来源 │
│ • 示例:job, instance │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ 3. 内部标签 │
├─────────────────────────────────────────────┤
│ • 以__开头 │
│ • 用于内部处理 │
│ • 不会存储到TSDB │
│ • 示例:__address__, __scheme__ │
└─────────────────────────────────────────────┘
1.3 标签命名规范 #
text
标签命名规范:
┌─────────────────────────────────────────────┐
│ 命名规则 │
├─────────────────────────────────────────────┤
│ • 键名匹配正则:[a-zA-Z_][a-zA-Z0-9_]* │
│ • 使用snake_case命名 │
│ • 应该有明确含义 │
│ • 避免使用保留名称 │
└─────────────────────────────────────────────┘
好的命名:
method # HTTP方法
status # HTTP状态码
endpoint # API端点
service # 服务名称
environment # 环境
不好的命名:
m # 太短,含义不清
httpMethod # 不推荐驼峰
method_1 # 数字后缀无意义
__custom # 不要使用__前缀
保留名称:
__name__ # 指标名称
__address__ # 目标地址
__scheme__ # 协议方案
__metrics_path__ # 指标路径
二、标签选择器 #
2.1 基本语法 #
text
标签选择器语法:
┌─────────────────────────────────────────────┐
│ 匹配类型 │
├─────────────────────────────────────────────┤
│ = 精确匹配 │
│ != 不匹配 │
│ =~ 正则匹配 │
│ !~ 正则不匹配 │
└─────────────────────────────────────────────┘
示例:
# 精确匹配
http_requests_total{method="GET"}
# 不匹配
http_requests_total{method!="POST"}
# 正则匹配
http_requests_total{method=~"GET|POST"}
# 正则不匹配
http_requests_total{method!~"DELETE|PUT"}
# 多条件组合(AND关系)
http_requests_total{method="GET", status="200"}
# 匹配所有(空选择器)
http_requests_total{}
2.2 精确匹配 #
promql
# 等于匹配
http_requests_total{method="GET"}
# 不等于匹配
http_requests_total{method!="POST"}
# 多标签精确匹配
http_requests_total{method="GET", status="200"}
# 匹配指标名称
{__name__="http_requests_total"}
# 匹配job
http_requests_total{job="api-server"}
2.3 正则匹配 #
promql
# 正则匹配
http_requests_total{method=~"GET|POST|PUT"}
# 正则不匹配
http_requests_total{method!~"DELETE|PATCH"}
# 匹配以/api开头的endpoint
http_requests_total{endpoint=~"/api/.*"}
# 匹配状态码2xx
http_requests_total{status=~"2.."}
# 匹配多个实例
http_requests_total{instance=~"node[1-3]:.*"}
# 组合正则
http_requests_total{method=~"GET|POST", status=~"2.."}
2.4 选择器组合 #
promql
# 多条件AND(逗号分隔)
http_requests_total{method="GET", status="200"}
# 使用集合操作实现OR
# 方法1:使用正则
http_requests_total{method=~"GET|POST"}
# 方法2:使用or操作符
http_requests_total{method="GET"} or http_requests_total{method="POST"}
# 复杂组合
http_requests_total{method="GET", status=~"2.."} or
http_requests_total{method="POST", status="201"}
# 排除特定标签值
http_requests_total{method="GET", status!="404"}
三、常用标签 #
3.1 目标标签 #
text
目标标签说明:
┌─────────────────────────────────────────────┐
│ job │
├─────────────────────────────────────────────┤
│ • 采集任务名称 │
│ • 在scrape_configs中定义 │
│ • 标识数据来源类型 │
│ │
│ 示例: │
│ job="node-exporter" │
│ job="prometheus" │
│ job="mysql-exporter" │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ instance │
├─────────────────────────────────────────────┤
│ • 目标实例地址 │
│ • 格式:host:port │
│ • 标识具体实例 │
│ │
│ 示例: │
│ instance="localhost:9090" │
│ instance="192.168.1.100:9100" │
└─────────────────────────────────────────────┘
3.2 内部标签 #
text
内部标签说明:
┌─────────────────────────────────────────────┐
│ __address__ │
├─────────────────────────────────────────────┤
│ • 目标地址 │
│ • 格式:host:port │
│ • 用于构造请求URL │
│ • 可被relabel修改 │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ __scheme__ │
├─────────────────────────────────────────────┤
│ • 协议方案 │
│ • 值:http 或 https │
│ • 默认:http │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ __metrics_path__ │
├─────────────────────────────────────────────┤
│ • 指标路径 │
│ • 默认:/metrics │
│ • 可被relabel修改 │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ __param_<name> │
├─────────────────────────────────────────────┤
│ • URL参数 │
│ • 用于传递查询参数 │
│ • 示例:__param_format="prometheus" │
└─────────────────────────────────────────────┘
四、标签操作 #
4.1 relabel_configs #
yaml
# relabel_configs:采集前的标签处理
scrape_configs:
- job_name: 'node-exporter'
kubernetes_sd_configs:
- role: pod
relabel_configs:
# 只采集有特定标签的Pod
- source_labels: [__meta_kubernetes_pod_label_app]
regex: 'node-exporter'
action: keep
# 设置instance标签
- source_labels: [__meta_kubernetes_pod_ip]
target_label: instance
replacement: '$1:9100'
# 添加环境标签
- target_label: environment
replacement: 'production'
# 删除不需要的标签
- action: labeldrop
regex: '__meta_kubernetes_pod_label_.+'
4.2 metric_relabel_configs #
yaml
# metric_relabel_configs:采集后的标签处理
scrape_configs:
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100']
metric_relabel_configs:
# 只保留特定指标
- source_labels: [__name__]
regex: 'node_(cpu|memory|disk|network).*'
action: keep
# 删除go运行时指标
- source_labels: [__name__]
regex: 'go_.*'
action: drop
# 修改标签值
- source_labels: [mountpoint]
regex: '/var/lib/docker/(.+)'
target_label: docker_volume
replacement: '$1'
# 提取标签
- source_labels: [__name__]
regex: 'node_(.*)_seconds_total'
target_label: metric_type
replacement: '$1'
4.3 常用relabel操作 #
yaml
# 常用relabel操作示例
relabel_configs:
# 1. keep:保留匹配的目标
- source_labels: [__meta_kubernetes_namespace]
regex: 'monitoring'
action: keep
# 2. drop:丢弃匹配的目标
- source_labels: [__meta_kubernetes_namespace]
regex: 'kube-system'
action: drop
# 3. replace:替换或添加标签(默认操作)
- source_labels: [__address__]
target_label: instance
replacement: '$1'
# 4. labelmap:批量重命名标签
- action: labelmap
regex: '__meta_kubernetes_pod_label_(.+)'
# 5. labeldrop:删除标签
- action: labeldrop
regex: '__meta_kubernetes_.+'
# 6. labelkeep:保留标签
- action: labelkeep
regex: '(job|instance|environment)'
五、标签最佳实践 #
5.1 标签设计原则 #
text
标签设计原则:
┌─────────────────────────────────────────────┐
│ 1. 基数控制 │
├─────────────────────────────────────────────┤
│ • 避免高基数标签 │
│ • 标签值应该是有限集合 │
│ • 不要使用用户ID、请求ID等 │
│ │
│ 好的标签: │
│ status="200" # 有限值 │
│ method="GET" # 有限值 │
│ environment="prod" # 有限值 │
│ │
│ 不好的标签: │
│ user_id="12345" # 无限值 │
│ request_id="abc123" # 无限值 │
│ timestamp="1700000000" # 无限值 │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ 2. 标签数量控制 │
├─────────────────────────────────────────────┤
│ • 每个指标的标签数量适中 │
│ • 通常不超过10个标签 │
│ • 每个标签组合创建一个时间序列 │
│ │
│ 时间序列数量 = 标签值组合数 │
│ │
│ 示例: │
│ method: 5种 │
│ status: 10种 │
│ instance: 3个 │
│ │
│ 时间序列数 = 5 × 10 × 3 = 150 │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ 3. 标签一致性 │
├─────────────────────────────────────────────┤
│ • 相同概念使用相同标签名 │
│ • 标签值格式统一 │
│ • 避免同义不同名 │
│ │
│ 好的做法: │
│ service="user-service" │
│ service="order-service" │
│ │
│ 不好的做法: │
│ service="user-service" │
│ app="order-service" │
└─────────────────────────────────────────────┘
5.2 标签使用示例 #
yaml
# 好的标签设计示例
# HTTP请求指标
http_requests_total{
method="GET", # HTTP方法
status="200", # HTTP状态码
endpoint="/api/users", # API端点
service="user-service", # 服务名称
environment="prod" # 环境
}
# 数据库查询指标
db_query_duration_seconds{
db="mysql", # 数据库类型
operation="select", # 操作类型
table="users", # 表名
service="user-service" # 服务名称
}
# 缓存指标
cache_operations_total{
cache="redis", # 缓存类型
operation="get", # 操作类型
result="hit", # 结果
service="user-service" # 服务名称
}
5.3 高基数问题 #
text
高基数问题分析:
┌─────────────────────────────────────────────┐
│ 什么是高基数 │
├─────────────────────────────────────────────┤
│ • 标签值数量过多 │
│ • 导致时间序列数量爆炸 │
│ • 影响Prometheus性能 │
└─────────────────────────────────────────────┘
高基数标签示例:
# 用户ID(高基数)
user_id="user_12345"
user_id="user_12346"
user_id="user_12347"
...数百万个不同值
# 请求ID(高基数)
request_id="req_abc123"
request_id="req_abc124"
...无限个不同值
# 时间戳(高基数)
timestamp="1700000000"
timestamp="1700000001"
...无限个不同值
解决方案:
1. 不记录高基数标签
• 使用日志系统记录详细信息
• 只记录聚合指标
2. 使用分桶或分组
• 将连续值分桶
• 将用户分组(如VIP/普通)
3. 使用采样
• 只采样部分请求
• 使用Histogram记录分布
六、标签查询技巧 #
6.1 按标签过滤 #
promql
# 精确匹配
http_requests_total{method="GET"}
# 多标签过滤
http_requests_total{method="GET", status="200"}
# 正则匹配
http_requests_total{method=~"GET|POST"}
# 排除特定值
http_requests_total{status!="404"}
# 正则排除
http_requests_total{method!~"DELETE|PUT"}
6.2 按标签聚合 #
promql
# 按单个标签聚合
sum by (method) (http_requests_total)
# 按多个标签聚合
sum by (method, status) (http_requests_total)
# 保留特定标签
sum by (instance) (http_requests_total)
# 不保留任何标签
sum (http_requests_total)
# 使用without排除标签
sum without (instance) (http_requests_total)
6.3 标签操作函数 #
promql
# label_replace:替换标签值
label_replace(up{job="node-exporter"}, "host", "$1", "instance", "(.*):.*")
# label_join:连接标签值
label_join(up{job="node-exporter"}, "new_label", "-", "job", "instance")
# 获取所有标签名
label_names()
# 获取特定指标的标签名
label_names(http_requests_total)
# 获取标签值
label_values(job)
# 获取特定指标的标签值
label_values(http_requests_total, method)
七、总结 #
标签要点:
| 概念 | 说明 |
|---|---|
| 标签 | 键值对,区分时间序列 |
| 目标标签 | job, instance |
| 内部标签 | __前缀,不存储 |
| 选择器 | =, !=, =~, !~ |
最佳实践:
| 原则 | 说明 |
|---|---|
| 控制基数 | 避免无限值标签 |
| 保持一致 | 相同概念相同命名 |
| 适度使用 | 标签数量适中 |
下一步,让我们学习命名规范!
最后更新:2026-03-27