日期: May 10, 2022


对于PromQL常见的sum/rate/topk/irate/delte/count等这些的用法不必多说,网上一抓一大把

真正让我纠结了很长时间的是关于group_left和group_right的用法,网上能找到的介绍少的可怜,官方说明有一说一我看不咋懂,所以我也试了很多,看怎么结合多个不同指标的标签,其实有点类似sql的多表查询jion on那样的

对于group_left和group_right适用的是一对多/多对一的情况

所以得确定哪边充当多的一方

示例一:

当我有两个指标

指标一

kafka_topic_partition_current_offset  {partition="0", topic="mytopic"}      111
kafka_topic_partition_current_offset  {partition="1", topic="mytopic"}      111

指标二

kafka_consumergroup_current_offset  {consumergroup="lyp",  partition="0", topic="mytopic"}      11
kafka_consumergroup_current_offset  {consumergroup="lyp",  partition="1", topic="mytopic"}      10
kafka_consumergroup_current_offset  {consumergroup="lyp002",  partition="0", topic="mytopic"}      2
kafka_consumergroup_current_offset  {consumergroup="lyp002",  partition="1", topic="mytopic"}      3

我的目的是求所有 Topic 当前总的offset   -  topic 某个消费者组的offset

那我直接指标一减去指标二可不可以呢? 不行的

因为指标二带有标签”consumergroup”,一个topic对应多个消费者组,所以指标二的数量肯定是比指标一多的,直接相减肯定报错,这种就是一对多的情况

用group_right 表示右边充当多的角色

一对多会把少的那边”扩充”到多的那边的数量,返回的数量是多的那边的数量

至于ignoring 和 on  ,ignoring的是两边不一致的标签,on的是两边一致的标签,结果是一样的

语句

sum(kafka_topic_partition_current_offset) by (topic) - ignoring(consumergroup) group_right sum(kafka_consumergroup_current_offset) by (topic,consumergroup)

注意这里ignoring的是左边没有右边有的标签

结果

{topic="mytopic",consumergroup="lyp"}        (111+111)-(11+10)
{topic="mytopic",consumergroup="lyp002"}     (111+111)-(2+3)

示例二:

当我有两个指标

指标一

aliyun_acs_ecs_dashboard_diskusage_utilization  {device="C:\\", diskname="C:\\", instanceId="abaabaaba", job="aliyun-exporter", userId="xxx"}        70
aliyun_acs_ecs_dashboard_diskusage_utilization  {device="D:\\", diskname="D:\\", instanceId="abaabaaba", job="aliyun-exporter", userId="xxx"}        50

指标二

aliyun_meta_ecs_info  {CreationTime="1999-02-01T00:00Z", ExpiredTime="2222-02-01T00:00Z", InstanceId="abaabaaba", InstanceName="阿巴阿巴阿巴",  job="aliyun-exporter"}       1

我的目的是把aliyun_meta_ecs_info的标签InstanceName加到aliyun_acs_ecs_dashboard_diskusage_utilization 指标里,这样就可以根据服务器名称看其所有磁盘的使用率

这个是多对一的情况,并且aliyun_meta_ecs_info 指标的作用只是提供标签InstanceName方便结果显示

语句

(sum(aliyun_acs_ecs_dashboard_diskusage_utilization)  by (instanceId,diskname))   + on(instanceId)  group_left(InstanceName)   ( 0*   label_replace(aliyun_meta_ecs_info, "instanceId", "$1", "InstanceId", "(.+)"))

结果

{ diskname="C:\\",InstanceName="阿巴阿巴阿巴"}    70
{ diskname="D:\\",InstanceName="阿巴阿巴阿巴"}    50

这里需要注意指标一里instanceId是小写的,指标二里InstanceId是大写的,所以这个aliyun-exporter十分滴坑爹,这俩是不能直接对应得,需要先用label_replace把_InstanceId替换成instanceId_

又由于目的只是取_aliyun_meta_ecs_info_ 的一个标签,所以需要用0*aliyun_meta_ecs_info 目的是不影响结果

其实这里把_aliyun_meta_ecs_info_ 放前面,用group_right结果是一样的

示例三:

经过一番研究

我最终搞了一个这么惊天地泣鬼神的PromQL

(sum(kube_pod_container_resource_requests_cpu_cores{node=~"$node"}) by (node)  /
sum (kube_node_status_allocatable_cpu_cores{node=~"$node"})  by (node)   * 100 ) -
((sum((sum(kube_pod_status_phase{namespace="default",phase="Failed"}==1) by (pod)) *
on(pod ) group_right sum(kube_pod_container_resource_requests_cpu_cores{node=~"$node"}) by (pod,node)  ) by(node) /
sum (kube_node_status_allocatable_cpu_cores{node=~"$node"})  by (node)) *100)  or
sum(kube_pod_container_resource_requests_cpu_cores{node=~"$node"}) by (node)  /
sum (kube_node_status_allocatable_cpu_cores{node=~"$node"})  by (node)   * 100

目的是计算k8s节点的request占比,但由于节点上时不时有驱逐的pod残留也会算进去,那就不准了,所以需要对有驱逐pod 的节点进行过滤,减去已驱逐pod的request,这一长串我搞了老长时间(虽然直接删除残留的驱逐pod就没有这个问题了,但一直感觉可以在PromQL阶段解决这个问题,果然😃)