避坑指南:为什么你在 `relabel_configs` 里过滤不掉指标?

很多刚接触 Prometheus 的小伙伴在优化监控时,都会遇到一个令人困惑的"玄学"问题:

"我明明在配置文件里写了要丢弃 go_gc_duration_seconds 这个指标,为什么重载配置后,它依然活蹦乱跳地出现在数据库里?"

检查配置语法,没错;重启服务,没用。

原因只有一个:你放错了位置。

你把针对 指标名称(__name__ 的过滤规则,写在了 relabel_configs 里,而它其实应该待在 metric_relabel_configs 里。

今天这篇博文,我们就来彻底搞懂这两个配置块的区别,帮你避开这个 90% 的新手都会踩的坑。


🕵️‍♂️ 核心误区:把"事后清洗"当成了"事前拦截"

Prometheus 的抓取过程并不是"一蹴而就"的,它分为两个截然不同的阶段。理解这两个阶段,是掌握 Relabeling 的关键。

阶段一:目标发现与准备 (relabel_configs)

  • 时间点 :Prometheus 刚刚通过 K8s、DNS 或静态列表发现了一个目标(比如 192.168.1.5:9100),正准备发起 HTTP 请求之前
  • 手里有什么 :此时,Prometheus 手里只有目标的元数据(地址、端口、Pod 名字、节点标签等)。
  • 手里没有什么它还没有拿到任何具体的指标数据! 它根本不知道这个目标会暴露 http_requests_total 还是 go_gc_duration_seconds
  • 结论 :在这个阶段,__name__(指标名)这个标签甚至还不存在。你试图根据一个不存在的值去过滤,自然是无效的。

阶段二:数据解析与入库 (metric_relabel_configs)

  • 时间点 :Prometheus 已经成功连接目标,下载了 /metrics 接口的所有文本数据,正在逐行解析,准备存入内存之前
  • 手里有什么 :此时,每一行数据都被解析成了样本,拥有了明确的指标名(__name__)、标签集(Labels)和数值(Value)。
  • 能做什么 :现在 Prometheus 终于知道"哦,这一行是 go_gc_duration_seconds"。你可以基于此决定:"扔掉这一行" 或者 "删掉这一行的某个标签"
  • 结论 :只有在这个阶段,基于 __name__ 的过滤才会生效。

❌ 错误示范:为什么你的配置不生效?

看看下面这段配置,是不是觉得很眼熟?

yaml 复制代码
scrape_configs:
  - job_name: 'my-java-app'
    static_configs:
      - targets: ['localhost:8080']
    
    # ⚠️ 错误位置!这里还没有指标数据,__name__ 是空的
    relabel_configs:
      - source_labels: [__name__]
        regex: 'go_.*'
        action: drop

发生了什么?

  1. Prometheus 发现 localhost:8080
  2. 进入 relabel_configs 阶段。它尝试读取 __name__,发现是空的(或者未定义)。
  3. 正则匹配失败(或者不匹配),action: drop 不触发。
  4. Prometheus 继续发起 HTTP 请求,抓取所有数据。
  5. 数据解析完成,所有 go_ 开头的指标被原封不动地存入数据库。

结果:过滤失败,内存继续爆炸。


✅ 正确姿势:把刀用在刀刃上

要过滤具体的指标(如 go_.*, jvm_.*),必须使用 metric_relabel_configs

yaml 复制代码
scrape_configs:
  - job_name: 'my-java-app'
    static_configs:
      - targets: ['localhost:8080']
    
    # ✅ 正确位置!此时指标已解析,__name__ 有值
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: 'go_.*'
        action: drop
      
      # 顺便再丢弃一些没用的 JVM 指标
      - source_labels: [__name__]
        regex: 'jvm_gc_pause_seconds.*'
        action: drop

现在的流程

  1. 抓取数据。
  2. 解析出一行 go_gc_duration_seconds{...} 0.05
  3. 进入 metric_relabel_configs
  4. 发现 __name__go_gc_duration_seconds,匹配正则 go_.*
  5. 触发 action: drop直接丢弃该行数据,不写入内存,不写入磁盘。

结果:完美过滤,资源节省。


🆚 深度对比:两张表看懂区别

为了让你以后不再混淆,请保存这张对比表:

特性 relabel_configs metric_relabel_configs
执行时机 抓取前 (Before Scrape) 抓取后,存储前 (After Scrape)
处理对象 Target (目标) Sample (样本/指标行)
__name__ 可用吗? 不可用 (此时还没抓到数据) 可用 (数据已解析)
主要用途 1. 筛选要抓取的目标 (如只抓特定 Pod)2. 重命名发现标签 (如 __meta_... -> pod)3. 构造静态标签 1. 过滤具体指标 (Drop/Keep __name__)2. 删除高基数标签 (LabelDrop)3. 修改样本值
性能优势 ⭐⭐⭐⭐⭐ (省去了网络请求和解析开销) ⭐⭐⭐ (省去了存储和索引开销,但已消耗带宽)
典型场景 "我只需要抓取名为 web-server 的 Pod" "我不需要 go_gc 指标" 或 "删掉 trace_id 标签"

💡 进阶技巧:什么时候用 relabel_configs 更优?

虽然 relabel_configs 不能过滤 __name__,但它在筛选目标方面效率更高。

场景 :你有 1000 个 Pod,但你只想监控其中名字包含 production 的 100 个 Pod。

  • 做法 A (错误) :在 metric_relabel_configs 里抓取所有 1000 个 Pod 的数据,然后根据指标过滤?不行,因为这是针对 Target 的筛选,不是针对指标的。
  • 做法 B (正确且高效) :在 relabel_configs 中直接丢弃那 900 个不需要的 Target。
yaml 复制代码
scrape_configs:
  - job_name: 'kubernetes-pods'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      # 在发起任何 HTTP 请求之前,直接丢弃非 production 的 Pod
      # 这样连网络带宽和 CPU 解析都省下了!
      - source_labels: [__meta_kubernetes_pod_name]
        regex: '.*production.*'
        action: keep

最佳实践总结

  1. 先粗筛 :用 relabel_configs 决定**"抓谁"**(基于 Pod 名、IP、Namespace 等元数据)。
  2. 后精洗 :用 metric_relabel_configs 决定**"存什么"**(基于 __name__ 指标名、具体标签值)。

🔍 如何验证你的配置?

改完配置别盲目自信,用这两招验证:

  1. 语法检查(必做):

    bash 复制代码
    promtool check config prometheus.yml

    确保没有 YAML 格式错误。

  2. 查询验证

    重载配置后,去 Prometheus UI 的 Graph 页面:

    • 如果你过滤了 go_.*,查询 count({__name__=~"go_.*"})。如果返回 0No data,恭喜成功!
    • 如果你删除了标签,查询该指标并查看 Table 视图,确认该标签是否消失。

🎉 结语

Prometheus 的配置看似复杂,其实逻辑非常清晰:

  • relabel_configs 是门卫,决定谁可以进门(Target)。
  • metric_relabel_configs 是安检员,决定进门的人身上哪些东西可以带进去(Metrics & Labels)。

下次再想过滤指标名时,记得找安检员metric_relabel_configs),别在门口(relabel_configs)白费功夫了!

希望这篇博文能帮你解决疑惑。如果觉得有用,欢迎点赞收藏,转发给那些还在为 Prometheus 内存溢出头疼的运维同事!

相关推荐
i建模1 小时前
Ubuntu Node.js 升级方案
linux·运维·ubuntu·node.js
2401_832298101 小时前
域名绑定怎么操作?服务器绑定域名失败的解决方法个人网站怎么绑定域名详细步骤教程
运维·服务器
顶点多余2 小时前
进程:计算机世界的执行单元
linux·运维·服务器·进程
AnchorYYC2 小时前
Docker入门
运维·docker·容器
Riemann~~2 小时前
docker包括那些内容
运维·docker·容器
芒果披萨2 小时前
Linux目录详解
linux·运维·服务器
东方鲤鱼2 小时前
MAC部署openClaw 实现自动化助手实战
运维·macos·自动化
阿成学长_Cain2 小时前
Linux 打印队列管理:accept 命令超详细使用教程
linux·运维·服务器