你是否遇到过这样的情况:Prometheus 运行一段时间后,内存飙升、查询变慢,甚至直接崩溃(OOM)?打开监控面板,发现成千上万个根本用不到的指标在疯狂写入?
这通常是因为**"数据噪声"太多**。在 Kubernetes 或微服务架构中,默认抓取的指标往往包含大量无用信息。
今天这篇博文,将手把手教你如何通过配置,精准过滤不需要的指标和标签,让你的 Prometheus 轻盈如飞。
🚨 为什么要过滤?
在 Prometheus 中,每一个唯一的标签组合(Label Set)都会生成一条独立的时间序列。
- 存储压力:无用的指标占用磁盘空间。
- 内存爆炸 :时间序列的元数据(Meta Data)存储在内存中。如果标签基数(Cardinality)过高(例如每个请求都有一个唯一的
request_id),内存会迅速被吃光。 - 查询变慢:扫描几百万条无用序列,查询速度自然快不起来。
核心原则:在数据进入磁盘之前,就把它扔掉!
🛠️ 核心武器:Relabeling
Prometheus 提供了两个配置块来实现过滤,它们都位于 scrape_configs 下:
relabel_configs:抓取前执行。主要用于处理目标发现(Service Discovery)阶段的标签。效率最高,推荐优先使用。metric_relabel_configs:抓取后、存储前执行。用于处理具体的指标行(Metric Line)。功能更强大,适合处理指标内容和动态生成的标签。
小白建议 :如果你不确定用哪个,针对"过滤具体指标"或"删除指标上的标签",首选
metric_relabel_configs。
✅ 场景一:我不想要这个指标(整行丢弃)
有些指标你永远都不会查,比如 Go 语言的 GC 详情,或者某些过于细粒度的文件系统指标。直接让它们"消失"。
1. 黑名单模式:丢弃特定指标
使用 action: drop 配合正则匹配指标名(__name__)。
yaml
scrape_configs:
- job_name: 'my-app'
metric_relabel_configs:
# 丢弃所有以 "go_" 开头的指标
- source_labels: [__name__]
regex: 'go_.*'
action: drop
# 丢弃特定的几个指标
- source_labels: [__name__]
regex: 'container_fs_reads_bytes_total|container_fs_writes_bytes_total'
action: drop
2. 白名单模式:只保留我想要的
如果你的应用输出了几百个指标,但你只关心其中两个。
yaml
scrape_configs:
- job_name: 'my-app'
metric_relabel_configs:
# 只保留 http_requests_total 和 app_latency_seconds,其他全部丢弃
- source_labels: [__name__]
regex: 'http_requests_total|app_latency_seconds'
action: keep
✅ 场景二:指标我要,但里面的某个标签太烦人(删除标签)
这是降低基数 最有效的技巧。
比如:你的应用给每个请求打了一个唯一的 trace_id 标签。这会导致每一秒都产生新的时间序列,瞬间撑爆内存。我们需要保留指标数据,但把 trace_id 这个标签删掉。
1. 删除特定标签
使用 action: labeldrop。
yaml
scrape_configs:
- job_name: 'my-app'
metric_relabel_configs:
# 删除名为 "trace_id" 的标签
# 结果:指标还在,数值还在,但 trace_id 标签没了,不同请求的数据会合并
- regex: 'trace_id'
action: labeldrop
# 删除所有以 "tmp_" 开头的临时标签
- regex: 'tmp_.*'
action: labeldrop
2. 根据标签是否存在来过滤
有时候,某些指标只有在带了特定标签(如 le 或 quantile)时我们才不想要,或者反过来。
yaml
scrape_configs:
- job_name: 'my-app'
metric_relabel_configs:
# 如果指标包含 "le" 标签(通常是直方图的桶),则删除该标签
# 注意:这会将直方图的不同桶合并,通常用于将直方图强制转为普通 Gauge,需谨慎
- source_labels: [le]
regex: '.+' # '.+' 表示只要标签有值就匹配
action: labeldrop
# 或者:如果指标包含了 "unwanted_label",直接丢弃整个指标
- source_labels: [unwanted_label]
regex: '.+'
action: drop
✅ 场景三:Kubernetes 环境特供优化
在 K8s 中,pod 名称经常变化(每次部署都变),container_id 更是瞬息万变。如果不加控制,历史数据中会残留大量已销毁 Pod 的序列。
推荐配置:
yaml
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
# 1. 在发现阶段,就把不需要的元数据标签扔掉,防止它们变成指标标签
relabel_configs:
- regex: '__meta_kubernetes_pod_uid|__meta_kubernetes_container_id'
action: labeldrop
# 2. 在存储阶段,进一步清洗
metric_relabel_configs:
# 假如你的业务代码不小心打印了随机 ID,必须在这里删掉!
- regex: 'request_id|transaction_id'
action: labeldrop
# 如果你只关心 Namespace 级别的聚合,不需要细分到 Pod,可以删掉 pod 标签
# (慎用:这将导致无法查看单个 Pod 的状态)
# - regex: 'pod'
# action: labeldrop
🔍 如何验证配置是否生效?
配置改完别急着走,验证一下才放心。
-
重载配置:
bash# 发送信号重载(无需重启) kill -HUP <prometheus_pid> # 或者在 K8s 中:kubectl rollout restart deployment/prometheus -
查询验证 :
打开 Prometheus UI -> Graph。
-
验证指标是否被丢弃 :
查询你刚才 drop 掉的指标名。如果显示
No data,成功!promqlgo_gc_duration_seconds -
验证标签是否被删除 :
查询该指标,鼠标悬停在图表线条上,或者点击 Table 视图。检查标签列表中是否还有那个被你
labeldrop的标签。如果没有,成功! -
终极查询技巧 :
想知道哪些指标还带有
pod标签?promqlcount by (__name__) ({pod!=""})这会列出所有带有
pod标签的指标名及其数量。
-
💡 避坑指南(重要!)
-
不要误删关键区分标签 :
如果你删除了
instance或pod标签,Prometheus 会把不同机器/容器的数据合并 成一条线。如果它们的值不同,数据可能会乱跳或被覆盖。只删除那些真的没用的标签(如 UUID、IP、随机 ID)。 -
正则表达式要严谨 :
regex默认为完全匹配。- 匹配开头:
^my_metric_.* - 匹配包含:
.*unwanted.* - 匹配任意非空值(用于判断标签存在):
.+
- 匹配开头:
-
先检查语法 :
修改配置文件后,先用官方工具检查语法,避免重启失败:
bashpromtool check config prometheus.yml
🎉 总结
Prometheus 的强大在于灵活,但灵活也带来了噪音。通过合理使用 metric_relabel_configs 中的 drop、keep 和 labeldrop,你可以:
- 📉 减少 50%~90% 的存储占用
- 🚀 显著提升查询响应速度
- 🛡️ 避免内存溢出崩溃
现在就打开你的 prometheus.yml,开始给你的监控系统"大扫除"吧!
觉得有用?欢迎转发给身边的运维小伙伴!如果有具体的过滤需求,欢迎在评论区留言讨论。