relabel 通过修改 target 的内部标签(如__address__)来动态改变抓取目标,而非仅添加指标标签;必须显式重写__address__才能指向正确实例,配合keep/drop实现条件过滤,并慎用labelmap以防标签爆炸。

Relabel 是怎么改变抓取目标的
Relabel 不是给指标加标签,而是修改 target(即抓取端点)本身的元数据,比如 __address__、__metrics_path__、__scheme__ 这些以双下划线开头的「内部标签」。Prometheus 在服务发现阶段拿到原始 target 列表后,会按顺序执行 relabel_configs,每条规则可过滤、重写、丢弃 target。关键点在于:只有保留下来的 target 才会被真正发起 HTTP 抓取。
必须改 __address__ 才能动态指向不同实例
默认情况下,服务发现(如 Kubernetes、Consul、file_sd)返回的 __address__ 是原始 IP:port,但你往往需要拼接 hostname、替换端口、或根据 label 构造地址。这时必须用 relabel_configs 显式覆盖它:
relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port, __address__] separator: ':' regex: '(.+);(.+)' target_label: __address__ replacement: '$2:$1'
常见错误是只改了普通 label(如 instance),却忘了改 __address__,结果还是连到默认 9090 或原始地址,抓取失败。
-
source_labels必须包含所有参与拼接的字段,顺序和regex捕获组要对齐 -
replacement中的$1、$2对应regex的捕获组,不是索引号 - 如果
__address__被设为空字符串或非法值(如http://),该 target 会被静默丢弃
用 action: keep 和 action: drop 做条件过滤
动态抓取常需按环境、角色、版本等维度筛选 target。靠 keep / drop 配合 regex 最直接:
- source_labels: [__meta_kubernetes_namespace] regex: 'staging|prod' action: keep - source_labels: [__meta_kubernetes_pod_label_app] regex: 'api|worker' action: keep
注意两点:
- 多条
keep规则是「与」关系(必须全部匹配),而drop是「或」关系(任一匹配即丢弃) - 没匹配上的 target 不会报错,只是不进入后续流程——这容易让人误以为配置没生效,建议先用
promtool check config+ 查看/targets页面确认实际生效的 target 列表 -
regex默认是完整匹配,想做前缀匹配得写^prefix.*,别漏掉^和.*
避免标签爆炸:慎用 action: labelmap
labelmap 会把所有匹配 regex 的源 label 全部复制为新 label,看似方便,但在 Kubernetes 等场景下极易引入大量无用 label(比如 __meta_kubernetes_pod_label_* 有十几二十个),拖慢 Prometheus 内存占用和查询速度。
更安全的做法是显式列出需要的 label:
- source_labels: [__meta_kubernetes_pod_label_app] target_label: app - source_labels: [__meta_kubernetes_pod_annotation_version] target_label: version
真实环境中,一个 target 的 label 数量超过 50 个就该警惕;超过 100 个很可能已影响性能,且难以 debug。
Relabel 的执行顺序和条件组合比看起来更敏感,哪怕一行 regex 多了个空格,都可能导致整批 target 消失。上线前务必在测试环境跑通 /targets 页面,并观察 prometheus_target_metadata_cache_entries 指标是否异常突增。










