通过 metrics-server 获取的 NodeMetrics 为何会不准确

背景描述

在使用 metrics-server 的 NodeMetrics 获取 node 的 CPU 使用量时,会稍微大于 node 的 CPU 核心数,导致计算剩余可用的 CPU 时出现了负数。此时 node 的 cpu 是 100% 满载,但是理论上无论如何也不会超过 CPU 总量。

问题分析

通过 metrics-server 获取 NodeMetrics 的链路如下:metrics-server → kubelet 10250 端口→ cadvisor。所以问题的本质还是在于 cadvisor 如何统计 CPU 使用量。

通过分析 cadvisor 的代码可以知道,cadvisor 会读取 cgroup 根目录的 cpuacct.usage 中的值,来获取当前累积使用的 CPU 时间。如下图代码所示。

cadvisor1

cpuacct.usage 的描述如下:

  • reports the total CPU time (in nanoseconds) consumed by all tasks in this cgroup (including tasks lower in the hierarchy).

cadvisor 会定期(每秒)对 node 进行采样,保存到 CpuUsage 中。

cadvisor2

当 metrics-server 需要获取当前的 CPU 使用量时,cadvisor 会统计最近 60s 内(即60个采样数据)的累积 CPU 使用时间,并除以总采样时间(ns),得到 CPU 使用量。

cadvisor3

因为 CPU 使用量的时间单位是精确到纳秒(ns)的,因此难免在计算上会有一定的误差,所以当 CPU 满载时出现统计出来的数据会稍大于 CPU 核心数也是正常情况了。