Docker状态显示CPU使用率超过100%

28

我有一个关于docker stats命令的问题,希望有人可以帮助我。我是Docker领域的新手,想要监控docker容器的CPU使用率。

物理机器有8个核心(CPU0 ... CPU7)。我已经创建了一个容器,并使用以下命令将其CPU资源限制为1个核心(CPU0):   docker run -itd --cpuset-cpus = 0 -p 8081:8080 binfalse / bives-webapp

我通过从Jmeter发送请求来强化容器,然后通过docker stats命令监视容器的CPU使用情况,该命令给出的值大于100%。

即使只向容器分配了一个内核,我也不明白为什么它会给出超过100%的值! 您对原因有任何想法吗? 这个CPU值是否表示除容器之外的某些系统进程的CPU使用情况?

感谢您提前的帮助。

docker版本: 客户端:  版本:17.06.0-ce  API版本:1.30  Go版本:go1.8.3  Git提交:02c1d87  构建时间:2017年6月23日星期五21:23:31  操作系统/架构:linux/amd64

服务器:  版本:17.06.0-ce  API版本:1.30(最低版本1.12)  Go版本:go1.8.3  Git提交:02c1d87  构建时间:2017年6月23日星期五21:19:04  操作系统/架构:linux/amd64  实验性质:真

docker info结果: 容器:2  运行中:1  已暂停:0  已停止:1 镜像:10 服务器版本:17.06.0-ce 存储驱动程序:aufs  根目录:/var/lib/docker/aufs 支持的文件系统:extfs 目录:141 Dirperm1受支持:true  日志记录驱动程序:json-file Cgroup Driver:cgroupfs 插件:  卷:本地  网络:桥接主机ipvlan macvlan null覆盖

日志: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog Swarm: 未激活 运行时: runc 默认运行时: runc Init 二进制文件: docker-init containerd 版本: cfb82a876ecc11b5ca0977d1733adbe58599088a runc 版本: 2d41c047c83e09a6d61d464906feb2a2f3c52aa4 init 版本: 949e6fa 安全选项: apparmor seccomp Profile: default 内核版本: 4.4.0-98-generic 操作系统: Ubuntu 16.04.2 LTS 操作系统类型: linux 架构: x86_64 CPU: 8 总内存: 15.56GiB 名称: logti048131 ID: RHOG:IR6N:FVC4:YDI5:A6T4:QA4Y:DDYF:7HZN:AI3L:WVLE:BNHY:6YNV Docker 根目录: /var/lib/docker 调试模式 (客户端): false 调试模式 (服务器): false 注册表: https://index.docker.io/v1/ 实验性功能: true 不安全的镜像仓库: 127.0.0.0/8 启用 Live Restore: false

警告:不支持交换空间限制


你正在运行哪个内核和docker版本?docker info是否显示任何cgroup警告?您能否描述更多有关负载的详细信息?我无法在自己的实验室中使用bash shell中的简单while“true loop”来重现此问题。与其限制为物理CPU,不妨考虑对内核调度程序使用--cpus = 1.0 - BMitch
@BMitch 对于我来说,一个容器的情况下相当准确。偶尔我会看到它上升到100.34或100.67%。如果我添加20个容器,误差会达到+-16%。再添加20个,误差就会达到+-35%。这与操作系统跟踪的情况相去甚远。 - Matt
所有容器都锁定在同一个核心上吗?它们全部受到CPU限制,还是只有一个受到CPU限制的容器和许多其他空闲容器? - BMitch
一个容器绑定到一个核心的CPU,使用该核心的100%,有很多空闲的容器。我已经在Alpine和Debian虚拟机上尝试过了,但还没有在物理机上尝试过。目前看起来像是一个bug。 - Matt
@BMitch,我已添加了docker的版本和docker信息输出。 - SMA
Github问题:https://dev59.com/PFYN5IYBdhLWcg3wdn8Y - cdalxndr
2个回答

15
在Linux上,cgroups和Docker CPU统计数据以CPU的“时间片”为单位处理,即CPU使用的纳秒数。要获得百分比,将容器cgroup值“使用时间”与来自/proc/stat的整个系统值“可用时间”进行比较。

由于存储的“时间片”值是累积的,因此将当前值与先前收集的值进行比较以获得更即时的百分比。我认为这种比较是问题的基础。

统计数据收集

docker stats命令实际上在客户端中完成了大部分信息的工作。客户端查询所有容器,监视容器启动/停止事件,并为每个正在运行的容器打开一个单独的统计流。这些容器统计数据的流用于在从流中转储统计数据时计算百分比

对于容器统计流,Docker守护程序首先收集系统使用的CPU时间。然后使用libcontainer读取容器cgroup文件并将文本解析为值。这里是所有统计数据结构。然后将所有内容作为JSON响应发送到客户端进行处理。
我认为问题至少部分源于在不同时间读取和解析/proc/stat系统信息和容器cgroup统计信息。每次读取容器信息的goroutine都会稍微延迟一些时间,与系统相比,该样本中包含更多纳秒。由于收集过程安排每X秒运行一次,因此下次读取包括的总纳秒数较少,因此在繁忙的系统上,值可能会反弹,然后回落相同数量,因为第二个样本中没有完整的“tick” 。
问题会随着容器数量增加和系统繁忙程度的提高而变得更加复杂。统计数据的收集和转发似乎是一个相对较重的过程,仅使用大量容器的docker stats就足以导致更多的不准确性。我最好的猜测是在所有尝试读取统计信息的goroutine中存在争用。我不确定这是否可以解释Docker显示的不准确程度。我可能完全错误或者还有其他因素导致了这个问题。

Linux cgroups

每个Docker容器的使用情况都在cgroup中进行跟踪。CPU记账信息可以通过cgroup文件系统查看:
→ find /sys/fs/cgroup/cpuacct/docker -type d
/sys/fs/cgroup/cpuacct/docker
/sys/fs/cgroup/cpuacct/docker/f0478406663bb57d597d4a63a031fc2e841de279a6f02d206b27eb481913c0ec
/sys/fs/cgroup/cpuacct/docker/5ac4753f955acbdf38beccbcc273f954489b2a00049617fdb0f9da6865707717
/sys/fs/cgroup/cpuacct/docker/a4e00d69819a15602cbfb4f86028a4175e16415ab9e2e9a9989fafa35bdb2edf
/sys/fs/cgroup/cpuacct/docker/af00983b1432d9ffa6de248cf154a1f1b88e6b9bbebb7da2485d94a38f9e7e15

→ cd /sys/fs/cgroup/cpuacct/docker/f0478406663bb57d597d4a63a031fc2e841de279a6f02d206b27eb481913c0ec
→ ls -l
total 0
-rw-r--r--    1 root     root             0 Nov 20 22:31 cgroup.clone_children
-rw-r--r--    1 root     root             0 Nov 20 04:35 cgroup.procs
-r--r--r--    1 root     root             0 Nov 20 21:51 cpuacct.stat
-rw-r--r--    1 root     root             0 Nov 20 21:51 cpuacct.usage
-r--r--r--    1 root     root             0 Nov 20 22:31 cpuacct.usage_all
-r--r--r--    1 root     root             0 Nov 20 21:51 cpuacct.usage_percpu
-r--r--r--    1 root     root             0 Nov 20 22:31 cpuacct.usage_percpu_sys
-r--r--r--    1 root     root             0 Nov 20 22:31 cpuacct.usage_percpu_user
-r--r--r--    1 root     root             0 Nov 20 22:31 cpuacct.usage_sys
-r--r--r--    1 root     root             0 Nov 20 22:31 cpuacct.usage_user
-rw-r--r--    1 root     root             0 Nov 20 22:31 notify_on_release
-rw-r--r--    1 root     root             0 Nov 20 22:31 tasks

→ cat cpuacct.usage_percpu
3625488147 6265485043 6504277830 

每个值都是该 CPU 上累计使用的纳秒数。
→ grep -w ^cpu /proc/stat
cpu  475761 0 10945 582794 2772 0 159 0 0 0

这里的值是USER_HZ

等于一秒的1/100,所以在Docker中进行一些转换。

@Alwansm 是的。对于一个绑定到1个CPU的stress-ng容器,同时与docker一起每秒采样cgroup CPU纳秒时间片值,读数很少偏离~9999xxxxx ns,这对我来说似乎是正确的,与top相比。 - Matt

0

这里是 Docker 统计 CPU 百分比的公式:

Docker 项目中的代码

cpuPercent = (cpuDelta / systemDelta) * onlineCPUs * 100.0 

其中 Delta 值的计算为 currentCPUUsage - previousCPUUsage


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