我有一个关于
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版本:
Client:
Version: 17.06.0-ce
API version: 1.30
Go version: go1.8.3
Git commit: 02c1d87
Built: Fri Jun 23 21:23:31 2017
OS/Arch: linux/amd64
Server:
Version: 17.06.0-ce
API version: 1.30 (minimum version 1.12)
Go version: go1.8.3
Git commit: 02c1d87
Built: Fri Jun 23 21:19:04 2017
OS/Arch: linux/amd64
Experimental: true
docker信息结果:
Containers: 2
Running: 1
Paused: 0
Stopped: 1
Images: 10
Server Version: 17.06.0-ce
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 141
Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: cfb82a876ecc11b5ca0977d1733adbe58599088a
runc version: 2d41c047c83e09a6d61d464906feb2a2f3c52aa4
init version: 949e6fa
Security Options:
apparmor
seccomp
Profile: default
Kernel Version: 4.4.0-98-generic
Operating System: Ubuntu 16.04.2 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 15.56GiB
Name: logti048131
ID: RHOG:IR6N:FVC4:YDI5:A6T4:QA4Y:DDYF:7HZN:AI3L:WVLE:BNHY:6YNV
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: true
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: No swap limit support
在 Linux 上,cgroups 和 Docker CPU 统计数据处理 CPU 的“时间片”,即 CPU 已使用的纳秒数。要获得百分比,请将容器 cgroup 的“已用时间”值与来自
/proc/stat
的“可用时间”的整体系统值进行比较。
由于存储的“时间片”值是累积的,因此将当前值与之前收集的值进行比较以获得更瞬时的百分比。我认为这个比较是问题的基础。
docker stats
命令实际上在客户端中为这些信息做了很多跑腿工作。客户端查询所有容器,监视容器启动/停止的事件,并为每个正在运行的容器打开单独的统计数据流。这些容器统计数据流用于计算流中每个统计数据转储的百分比。
对于容器统计数据流,Docker 守护进程首先收集系统使用的 CPU 时间。然后,它使用 libcontainer 读取容器 cgroup 文件并将文本解析为值。这是所有统计数据结构。然后将其作为 JSON 响应发送到客户端进行处理。
我相信至少部分问题源于在不同时间读取和解析/proc/stat
系统信息和容器 cgroup 统计信息。每当读取容器信息的 goroutine 延迟一点时,与系统相比,该样本中会包含更多的纳秒。由于收集过程计划每 X 秒运行一次,因此下一次读取包含的总纳秒数会减少,因此这些值可以在繁忙的系统上反弹,然后回落相同的量,因为第二次读取中没有包含完整的“刻度”样本。运行的容器越多,系统就越繁忙,问题就会变得更加复杂。统计数据的收集和转发给客户端似乎是一个相对重量级的过程,仅仅
docker stats
大量的容器就足以导致更多的不准确。我最好的猜测是所有试图读取统计数据的 goroutine 中存在争用。我不确定这是否能解释 Docker 显示的不准确程度。我要么完全错了,要么还有其他问题加剧了这个问题。Linux cgroups
cgroup 中进行跟踪。可以通过cgroup文件系统查看CPU记账信息:
→ 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