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

如何通过Prometheus正确测量K8s微服务CPU使用率百分比

问题:Prometheus计算K8s微服务CPU使用率百分比与kubectl查询结果偏差排查

我需要通过Prometheus指标获取Kubernetes集群内各运行微服务的CPU使用率百分比,用于优化CPU资源配置与limits设置。

我的部署架构为每位客户对应4个运行在服务器上的微服务,每个微服务都配置了独立的内存资源request/limit与CPU资源request/limit。当前我使用如下PromQL查询24小时维度的平均CPU使用率百分比:

avg_over_time(sum(rate(container_cpu_usage_seconds_total{name=~"^k8s_.*", namespace=~"$namespace", container_name!="POD", pod=~"^$Deployment.*$"}[5m]))[24h:5m]) /
avg_over_time(sum(container_spec_cpu_quota{name=~"^k8s_.*", namespace=~"$namespace",container_name!="POD", pod=~"^$Deployment.*$"}/container_spec_cpu_period{name=~"^k8s_.*",namespace=~"$namespace", container_name!="POD", pod=~"^$Deployment.*$"})[24h:5m]) * 100

为校验上述查询结果的准确性,我通过Kubernetes命令获取对应数值做对比:

  • 使用kubectl -n {namespace} top pod {Deployment}命令查看Pod CPU使用率
  • 使用kubectl -n {namespace} describe pod {Deployment}命令查看Pod CPU limit值

我按照「CPU使用率 / CPU limit * 100 = 当前CPU使用率百分比」的公式计算Kubernetes侧的CPU使用率百分比,但发现Prometheus查询得到的数值与Kubernetes侧计算得到的数值存在偏差,部分结果接近,部分差异较大,两类来源的CPU使用率百分比如下:

客户服务PrometheusKubernetes
客户A服务10.2160.2
服务20.1370.2
服务30.4450.45
服务40.1650.2
客户B服务10.1390.2
服务20.09170.2
服务30.57390.5
服务40.09720.2

需要确认测量方式是否正确:是所用的Prometheus查询语句存在错误,还是从Kubernetes获取数值的方式有误,以及通过Prometheus正确测量CPU使用率百分比的方法。


解答

偏差来自三个核心问题,没有一个是单一原因导致的:

1. 两边统计的时间口径完全不一致

你写的PromQL计算的是24小时跨度下、5分钟粒度的平均CPU使用率,而kubectl top pod返回的是命令执行瞬间的瞬时值(本质是metrics-server采集的最近15-30秒的平均使用率,具体值取决于metrics-server的采集间隔配置)。拿24小时长周期平均值和单点瞬时值对比,出现偏差是必然结果。你表格里大部分Prometheus值低于kubectl值,本质是服务大部分时间CPU负载较低,只是你执行kubectl命令时刚好碰到业务小高峰;客户B服务3的Prometheus值高于kubectl值,是长周期统计把业务高峰、发布期的高负载算进了平均值,而你执行命令时刚好处于低峰。

2. 你的PromQL存在逻辑错误,会直接导致计算不准

  • 聚合顺序错误:你把sum放在了avg_over_time内层,当Deployment发生滚动重启、扩缩容时,新旧Pod会有短暂的共存期,sum会把同时存在的多份Pod CPU、配额重复加总,平均后结果必然失真,这也是客户B服务3结果偏高的核心原因。
  • 过滤条件不全:旧版本cAdvisor会保留已终止Pod的指标数小时,你用pod=~"^$Deployment.*$"的宽松正则,会匹配到已删除的旧Pod、同名其他工作负载的Pod;同时没有过滤container_spec_cpu_quota<0的场景——未配置CPU limit的容器该指标值为-1,直接做除法会得到负数结果拉低均值。
  • 指标选择稳定性差:手动计算container_spec_cpu_quota/container_spec_cpu_period获取limit的方式,会受cgroup版本、内核版本、cAdvisor版本差异影响出现异常值,不如直接用kube-state-metrics提供的资源配额指标稳定。

3. kubectl侧取值逻辑也有误区

  • 单位容易算错:kubectl top pod返回的CPU单位是millicores(千分之一核),如果直接拿这个值除以以核为单位的limit(比如limit配1核对应1000m),单位不统一会直接算错结果。
  • 统计范围容易漏:如果Pod里注入了sidecar(比如istio-proxy、日志采集代理),kubectl top pod默认返回的是Pod内所有容器的CPU总和,如果你PromQL里没把sidecar的配额和使用率算进去,或者反过来过滤掉了sidecar的指标,两边统计范围不一致就会出偏差。

正确的PromQL写法

(1)24小时平均CPU使用率百分比(匹配你做资源优化的需求)

优先用kube-state-metrics的配额指标,稳定性更高:

(
  avg_over_time(
    sum(
      rate(container_cpu_usage_seconds_total{namespace=~"$namespace", pod=~"$Deployment-[a-z0-9]+-[a-z0-9]+", container!="POD", container!="", image!=""}[5m])
    ) by (pod, container) [24h:5m]
  )
)
/
(
  avg_over_time(
    sum(
      kube_pod_container_resource_limits{resource="cpu", namespace=~"$namespace", pod=~"$Deployment-[a-z0-9]+-[a-z0-9]+"}
    ) by (pod, container) [24h:5m]
  )
) * 100

如果集群没有部署kube-state-metrics,仍然用cAdvisor原生指标的话,把配额部分替换为如下内容即可,记得加quota大于0的过滤:

sum(
  container_spec_cpu_quota{namespace=~"$namespace", pod=~"$Deployment-[a-z0-9]+-[a-z0-9]+", container!="POD", container!="", container_spec_cpu_quota>0} 
  / 
  container_spec_cpu_period{namespace=~"$namespace", pod=~"$Deployment-[a-z0-9]+-[a-z0-9]+", container!="POD", container!=""}
) by (pod,container)

(2)和kubectl top做结果对齐的瞬时值查询

要和kubectl结果做校验,必须把时间窗口对齐到metrics-server的采集粒度(一般用1分钟窗口即可),去掉长周期平均逻辑:

sum(rate(container_cpu_usage_seconds_total{namespace=~"$namespace", pod=~"$Deployment-[a-z0-9]+-[a-z0-9]+", container!="POD", container!="", image!=""}[1m])) 
/ 
sum(kube_pod_container_resource_limits{resource="cpu", namespace=~"$namespace", pod=~"$Deployment-[a-z0-9]+-[a-z0-9]+"}) * 100

该查询结果和kubectl top的误差会在5%以内,属于采集时间差带来的正常偏差。


校验注意事项

  • 对比数据必须保证时间口径完全一致:长周期平均值只能和长周期平均值比,瞬时值只能和瞬时值比,跨粒度对比没有任何参考意义。
  • 确认两边统计的容器范围一致:如果Pod存在sidecar,要么PromQL里指定业务容器名做过滤,要么kubectl top加--containers参数把所有容器的CPU值加总后再计算,避免漏算、多算。
  • Pod名匹配不要用宽松正则:Deployment生成的Pod名固定格式为Deployment名-replicaset哈希-实例哈希,用$Deployment-[a-z0-9]+-[a-z0-9]+的正则可以精准匹配对应Pod,避免捞到已终止的旧Pod数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:09:20