--cpus 和 --cpu-shares 都是限制 CPU,有什么区别?一个是硬上限,另一个只在争抢时起作用。这篇用满负荷的 Python 进程,从 cgroup 的 cpu.stat 里读出实际占用的 CPU,逐项验证。
不限制:cgroup 里 cpu.max=max 100000 cpu.weight=100;用 12 个进程满负荷跑 6 秒,平均占用 9.72 个 CPU --cpus 0.5:cgroup 里 cpu.max=50000 100000 cpu.weight=100;用 12 个进程满负荷跑 6 秒,平均占用 0.50 个 CPU --cpus 1:cgroup 里 cpu.max=100000 100000 cpu.weight=100;用 12 个进程满负荷跑 6 秒,平均占用 1.00 个 CPU --cpus 2:cgroup 里 cpu.max=200000 100000 cpu.weight=100;用 12 个进程满负荷跑 6 秒,平均占用 2.02 个 CPU --cpu-quota 25000(周期默认 100000):cgroup 里 cpu.max=25000 100000 cpu.weight=100;用 12 个进程满负荷跑 6 秒,平均占用 0.25 个 CPU
--cpus 0.5 在容器的 cgroup 里是 cpu.max = 50000 100000(每 100 ms 周期最多用 50 ms),满负荷的容器稳定在 0.50 个 CPU;--cpu-quota 25000 是 0.25。不限制时 12 个进程占用了 9.72 个 CPU(虚拟机共 10 个)。这是 CPU 时间的上限,容器可以在多个核上同时跑,只是总和不超过。
只有这一个容器、--cpu-shares 2(最低权重)、2 个满负荷进程:平均占用 2.00 个 CPU(没有竞争时 shares 不限制)
两个容器钉在同一个 CPU(--cpuset-cpus 0)上同时满负荷跑:
shares 1024 对 1024:占用 0.50 对 0.51 个 CPU,实际比例 0.98;shares 比例 1.00
shares 1024 对 512:占用 0.63 对 0.40 个 CPU,实际比例 1.57;shares 比例 2.00
shares 1024 对 256:占用 0.74 对 0.30 个 CPU,实际比例 2.47;shares 比例 4.00
shares 2048 对 256:占用 0.83 对 0.26 个 CPU,实际比例 3.19;shares 比例 8.00
--cpu-shares 换算成 cgroup v2 的 cpu.weight:256 → 35, 512 → 59, 1024 → 100, 2048 → 174(不带参数时是 100)
用 cpu.weight 算出的比例:1024:512 = 1.69,1024:256 = 2.86,2048:256 = 4.97shares 只决定争抢时的比例。没有竞争时,shares 为 2 的容器也用满 2.00 个 CPU;把两个容器钉在同一个 CPU 上,1024 对 1024 各约一半,1024 对 512 是 0.63 对 0.40。cgroup v2 把 shares 换算成 cpu.weight(1024 → 100,512 → 59,256 → 35,2048 → 174),这个换算不是线性的。实际比例比 shares 的比例小,也比 weight 的比例小一些,我没有深究原因;每组只跑了一次 6 秒。