docker stats 里的 CPU%、内存、网络和磁盘数字到底怎么算的?为什么 CPU 能超过 100%?为什么写了一大堆文件内存却没涨?这篇和 cgroup、内核计数器对照着验证。
一行 JSON 的字段:['BlockIO', 'CPUPerc', 'Container', 'ID', 'MemPerc', 'MemUsage', 'Name', 'NetIO', 'PIDs'] 2 个满负荷进程:CPUPerc=198.98% MemUsage=13.41MiB / 7.748GiB MemPerc=0.17% NetIO=1.17kB / 126B BlockIO=3.47MB / 971kB PIDs=3 自己从 cgroup 的 cpu.stat 算:200% (CPU 时间增量 ÷ 墙钟时间;满 1 个 CPU = 100%) 虚拟机 CPU 数 = 10:docker stats 的 CPUPerc 可以超过 100% (每个核 100%)
CPUPerc 以一个 CPU 核为 100%,两个忙等进程大约 200%;我用 cgroup 的 cpu.stat 的 usage_usec 增量算出 200%,与 stats 的 198.98% 吻合。
docker stats 的 MemUsage:写 200 MiB 文件前 544KiB / 512MiB,写完 6.102MiB / 512MiB 写完之后从 cgroup 读(这次读本身用了一个 docker exec 进程,会多出几 MiB):memory.current=214.0 MiB,其中 anon=6.2 MiB、inactive_file=200.0 MiB 对比:cgroup 的 memory.current 增加了约 200 MiB(页缓存),而 docker stats 只增加了 6.102MiB / 512MiB,所以 MemUsage 不含页缓存
MemUsage 不包含页缓存(inactive_file)。写大文件会让 cgroup 的 memory.current 涨很多,但 docker stats 看不出来。判断容器会不会因为内存被杀,要看 cgroup 的实际限制行为,而不只是这个数字(页缓存在内存紧张时可回收,我没有在这里测)。
eth0 的 rx/tx 增量:21406 / 20924 字节;启动以来累计 rx=22096 tx=21008;docker stats NetIO = 22.1kB / 21kB 写 50 MiB(oflag=direct)后 docker stats BlockIO = 0B / 52.4MB
NetIO 是容器 eth0 的累计收发字节,和 /sys/class/net/eth0/statistics 一致;BlockIO 是块设备读写累计,direct I/O 写 50 MiB 后写入是 52.4MB。