You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复用PromQL中重复的标签关联等查询片段?

PromQL查询片段复用:替代录制规则的高效方案

我有大量用于告警和仪表盘的PromQL查询,里面重复了很多过滤和标签增强的模板代码。有没有类似SQL视图的服务端复用方式,比如服务端函数、宏之类的,能复用这些重复的查询片段?

我知道可以用录制规则(recording rule),但做标签关联(join)的时候效率极低:录制规则得暴露所有可能用到的标签,会导致基数爆炸,生成的指标既占存储又耗内存。云环境里靠加内存解决很常见,但太浪费资源了。


示例1:存储卷指标的标签增强查询

下面是基于kube-state-metrics的查询,用来给存储卷指标补充业务标签和集群关联信息:

sum without(job,instance,service,endpoint,metrics_path,prometheus) (
  kubelet_volume_stats_available_bytes{kube_cluster="$kube_cluster"}
  # 补充业务自定义标签
  * on (namespace,persistentvolumeclaim)
    group_left(some_org_specific_label,other_org_specific_label)
    group by (namespace,persistentvolumeclaim,some_org_specific_label,other_org_specific_label) (
      kube_persistentvolumeclaim_labels{kube_cluster="$kube_cluster"}
  )
  # 关联PVC与PV名称(处理标签名不一致问题)
  * on (namespace,persistentvolumeclaim)
    group_left(persistentvolume)
    group by (namespace,persistentvolumeclaim,persistentvolume) (
    # kube_persistentvolumeclaim_info用volumename标签,而persistentvolume_info用persistentvolume标签
    label_replace(
      kube_persistentvolumeclaim_info{kube_cluster="$kube_cluster"},
      "persistentvolume", "$1", "volumename", "^(.*)$"
    )
  )
  # 补充PV的CSI驱动、卷句柄和存储类信息
  * on (persistentvolume)
    group_left(csi_driver,csi_volume_handle,storageclass)
    group by (persistentvolume,csi_driver,csi_volume_handle,storageclass) (
      kube_persistentvolume_info
  )
)

该查询逻辑:

  • 查询指定集群$kube_cluster下的存储卷可用空间指标
  • 关联kube_persistentvolumeclaim_labels添加业务标签
  • 转换PVC标签名,实现与PV的关联匹配
  • 补充PV的CSI相关信息
  • 移除冗余标签

如果要写磁盘空闲百分比、IO阈值告警等查询,必须重复上述所有模板代码,非常繁琐。而且Prometheus没有SQL式的下推过滤逻辑,需手动添加过滤条件才能保证效率。


示例2:工作负载指标的Pod信息增强查询

另一个场景是给工作负载指标补充Pod的标签、注解和容器镜像信息,查询如下:

# 聚合时丢弃无关标签,PromQL无原生label_drop操作
sum without(endpoint,instance,job,prometheus,container,uid) (
    some_workload_specific_metric{kube_cluster="$kube_cluster"}
    # 关联kube_pod_labels获取业务标签
    * on (uid)
    group_left(org_specific_label_1, org_specific_label_2, org_specific_annotation_1)
    # 用group by明确指定所需标签,避免无关标签波动影响结果
    group by (uid, org_specific_label_1, org_specific_label_2) (
        kube_pod_labels{kube_cluster="$kube_cluster"}
    )
    # 关联kube_pod_info获取Pod节点与IP
    * on (uid)
    group_left(pod_ip,node)
    group by (uid, pod_ip, node) (
        kube_pod_info{kube_cluster="$kube_cluster"}
    )
    # 关联kube_pod_container_info获取容器镜像
    * on (uid,container_id)
    group_left(image_spec,image_id)
    group by (uid,container_id,image_spec,image_id) (
        kube_pod_container_info{kube_cluster="$kube_cluster"}
    )
    # 关联kube_pod_annotations获取业务注解
    * on (uid)
    group_left(org_specific_annotation_1)
    group by (uid,org_specific_annotation_1) (
        kube_pod_annotations{kube_cluster="$kube_cluster"}
    )
)

每个Alertmanager告警都重复这套逻辑,维护成本极高。


可行的替代方案

1. Prometheus客户端宏

Prometheus原生支持客户端宏,通过配置文件定义重复查询片段,在查询中引用。需开启--web.enable-lifecycle参数,然后在prometheus.yml中配置:

macros:
  enrich_volume_labels: |
    * on (namespace,persistentvolumeclaim)
      group_left(some_org_specific_label,other_org_specific_label)
      group by (namespace,persistentvolumeclaim,some_org_specific_label,other_org_specific_label) (
        kube_persistentvolumeclaim_labels{kube_cluster="$kube_cluster"}
    )
    * on (namespace,persistentvolumeclaim)
      group_left(persistentvolume)
      group by (namespace,persistentvolumeclaim,persistentvolume) (
        label_replace(
          kube_persistentvolumeclaim_info{kube_cluster="$kube_cluster"},
          "persistentvolume", "$1", "volumename", "^(.*)$"
        )
    )
    * on (persistentvolume)
      group_left(csi_driver,csi_volume_handle,storageclass)
      group by (persistentvolume,csi_driver,csi_volume_handle,storageclass) (
        kube_persistentvolume_info
    )

简化后的查询:

sum without(job,instance,service,endpoint,metrics_path,prometheus) (
  kubelet_volume_stats_available_bytes{kube_cluster="$kube_cluster"}
  $enrich_volume_labels
)

宏由客户端解析,不增加服务端存储开销,能大幅减少代码重复。

2. Thanos/Cortex服务端查询模板

如果使用Thanos或Cortex等分布式Prometheus方案,它们支持服务端查询模板,可将重复逻辑存储在服务端,通过模板名称调用并传入参数,实现类似SQL视图的复用能力。

3. 自定义查询中间层

开发轻量API服务,封装常用的标签增强逻辑。比如接收基础指标名和集群参数,返回拼接好的完整PromQL查询,再转发给Prometheus。这种方式完全自定义,灵活度最高。

4. 优化kube-state-metrics输出

若标签增强逻辑固定,可修改kube-state-metrics配置,在指标生成阶段直接添加所需标签。比如调整--metric-labels-allowlist参数,将PVC/PV的业务标签/注解同步到目标指标中,避免在PromQL中做关联操作。

5. 轻量录制规则(按需聚合)

若必须用录制规则,避免暴露所有标签,而是按需聚合:只保留业务必需的标签,提前通过sum by或avg by聚合,降低指标基数,减少存储和内存消耗。


内容的提问来源于stack exchange,提问作者Craig Ringer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 18:40:55