获取 Docker 容器 CPU 使用率百分比

30
Docker提供了一个交互式的stats命令:docker stats [cid],它可以实时提供有关CPU使用情况的信息,如下所示:
CONTAINER      CPU %          MEM USAGE/LIMIT       MEM %       NET I/O
36e8a65d       0.03%          4.086 MiB/7.798 GiB   0.05%       281.3 MiB/288.3 MiB

我正在尝试以易于分析的格式获取CPU使用率的百分比,以进行一些分析。

我在/sys/fs中看到了类似于Docker远程API提供的统计信息,该API为我提供了此JSON blob:

{
    "cpu_usage": {
        "usage_in_usermode": 345230000000, 
        "total_usage": 430576697133, 
        "percpu_usage": [
            112999686856, 
            106377031910, 
            113291361597, 
            97908616770
        ], 
        "usage_in_kernelmode": 80670000000
    }, 
    "system_cpu_usage": 440576670000000, 
    "throttling_data": {
        "throttled_time": 0, 
        "periods": 0, 
        "throttled_periods": 0
    }
}

但我不确定如何准确地从中获得CPU使用率百分比。

有什么想法吗?


上面的例子中,你的值不是以百分比表示的吗?还是我理解错了什么? - white_gecko
1
他的意思是他如何从api中获取百分比,以与docker客户端显示方式相同的方式。 - luxas
3个回答

38
如果你想使用 Stats API 调用,可以看一下 Docker 客户端是如何做的:https://github.com/docker/docker/blob/eb131c5383db8cac633919f82abad86c99bffbe5/cli/command/container/stats_helpers.go#L175-L188
func calculateCPUPercent(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
    var (
        cpuPercent = 0.0
        // calculate the change for the cpu usage of the container in between readings
        cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU)
        // calculate the change for the entire system between readings
        systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem)
    )

    if systemDelta > 0.0 && cpuDelta > 0.0 {
        cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
    }
    return cpuPercent
}

基本上,您需要选择一个参考点,然后查看在10秒内的差异,然后就可以确定容器使用了多少时间。例如,我们从0 SystemCPUUsage和0 CPUUsage开始计算容器使用情况。如果10秒后,我们有了10 SystemCPUUsage和1 CPUUsage,则容器使用率为10%。API中提供的结果以纳秒为单位而不是以秒为单位。实际时间并不重要,重要的是SystemCPUUsage的总变化量,然后将其与CPUUsage进行比较。


2
以上链接已失效。在以下链接找到它: https://github.com/docker/docker/blob/eb131c5383db8cac633919f82abad86c99bffbe5/cli/command/container/stats_helpers.go - darKoram
1
值得注意的是,v.CPUStats.CPUUsage.PercpuUsage 是一个包含所有 CPU 核心使用情况的数组。不幸的是,如果核心未被使用,则它返回值为 0。这意味着如果 Docker 列出未使用的核心,则百分比将会失真。当我的百分比没有加起来时,我才发现了这一点。 此外,在 API 的新版本中提供了 cpu_stats.online_cpus,因此您可以直接使用它。 - Byebye

10
在我们调用远程API之后,我们会得到这些字段:precpu_stats/cpu_stats 然后,基本上这就是代码:(JavaScript示例)
var res <---- remote api response
    
var cpuDelta = res.cpu_stats.cpu_usage.total_usage -  res.precpu_stats.cpu_usage.total_usage;
var systemDelta = res.cpu_stats.system_cpu_usage - res.precpu_stats.system_cpu_usage;
var RESULT_CPU_USAGE = cpuDelta / systemDelta * 100;

只是为了澄清RESULT_CPU_USAGE...它是从您的物理硬件消耗的资源量,所以假设您得到RESULT_CPU_USAGE50%,这意味着50%的所有PC功率都被容器X使用。

1
你的计算没有考虑到CPU数量。 - smishra
我认为将结果乘以CPU数量并没有太多意义。我的笔记本有4个核心,如果我从docker容器中压力测试这些核心,然后从外部运行docker stats...我会得到大约400%的CPU使用率。如果我正在监视一个Docker主机,我宁愿将范围设置在0%到100%之间。 - LiberQuack
这个 CPU 使用率百分比似乎是一秒钟的。有没有办法在不每分钟调用此 API 60 次的情况下获取容器使用的平均 CPU? - zeroweb
有人得到正确的计算结果吗?这个答案是不正确的。 - user3241084
@user3241084 给出的答案是正确的计算。我已经验证结果与docker stats CLI的输出相似。 - Astitva Srivastava

1

所以我也需要这个,以下代码能够给出正确的 CPU 使用率,并且考虑了处理器核心数。

var cpuDelta = metric.cpu_stats.cpu_usage.total_usage -  metric.precpu_stats.cpu_usage.total_usage;
var systemDelta = metric.cpu_stats.system_cpu_usage - metric.precpu_stats.system_cpu_usage;
var RESULT_CPU_USAGE = cpuDelta / systemDelta * metric.cpu_stats.cpu_usage.percpu_usage.length * 100;

console.log(RESULT_CPU_USAGE);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接