CPU使用率其实就是你运行的程序占用的CPU资源,表示你的机器在某个时间点的运行程序的情况。
使用率越高,说明你的机器在这个时间上运行了很多程序,反之较少。
CPU使用率的高低与你的CPU强弱有直接关系。
Docker CPU 限制;
Docker 的资源限制和隔离完全基于 Linux cgroups。
对 CPU 资源的限制方式也和 cgroups 相同。
Docker 提供的 CPU 资源限制选项可以在多核系统上限制容器能利用哪些 vCPU。
而对容器最多能使用的 CPU 时间有两种限制方式:
一是有多个 CPU 密集型的容器竞争 CPU 时,设置各个容器能使用的 CPU 时间相对比例。
二是以绝对的方式设置容器在每个调度周期内最多能使用的 CPU 时间。
--cpuset-cpus="" # 允许使用的 CPU 集合
-c,--cpu-shares=0 # CPU 共享权值(相对权重)
cpu-period=0 # 限制 CPU CFS 的周期,范围从 100ms~1s,即[1000, 1000000]
--cpu-quota=0 # 限制 CPU CFS 配额,必须不小于1ms,即 >= 1000
--cpuset-mems="" # 允许在上执行的内存节点(MEMs),只对 NUMA 架构有效
NUMA
非统一内存访问(NUMA)是一种用于多处理器的电脑记忆体设计,内存访问时间取决于处理器的内存位置。 在NUMA下,处理器访问它自己的本地存储器的速度比非本地存储器(存储器的地方到另一个处理器之间共享的处理器或存储器)快一些。
CPU 查看在 cat /proc/cpuinfo
docker run -d -it --cpuset-cpus="0,6" --name Centos-3 centos /bin/bash
我们可以设置容器可以在哪些 CPU 核上运行。
例如:
docker run -it --cpuset-cpus="0,6" --name Centos centos /bin/bash
设置容器中的进程可以在 cpu 0 和 cpu 6上执行。
docker run -it --cpuset-cpus="0-5" --name Centos centos /bin/bash
设置容器中的进程可以在 cpu0 - cpu5 上执行。
在 NUMA CPU 架构上,我们可以设置容器可以使用的内存节点。
docker run -it --cpuset-mems="1,5" --name Centos centos /bin/bash
设置容器中的进程只能使用节点 1 和 5 上的内存。
docker run -it --cpuset-mems="0-3" --name Centos centos /bin/bash
设置容器中的进程只能使用节点 0、1、2、3 上的内存。
CPU 资源的相对限制
默认情况下,所有的容器得到同等比例的 CPU 周期。在有多个容器竞争 CPU 时我们可以设置每个容器能使用的 CPU 时间比例。这个比例叫作共享权值,通过-c或--cpu-shares设置。Docker 默认每个容器的权值为 1024。不设置或将其设置为 0,都将使用这个默认值。系统会根据每个容器的共享权值和所有容器共享权值和比例来给容器分配 CPU 时间。
CPU 资源的绝对限制
Linux 通过 CFS(Completely Fair Scheduler,完全公平调度器)来调度各个进程对 CPU 的使用。
CFS 默认的调度周期是 100ms。
设置每个容器进程的调度周期,以及在这个周期内各个容器最多能使用多少 CPU 时间。
--cpu-period 设置调度周期,
--cpu-quota 设置在每个周期内容器能使用的 CPU 时间。
例如:
docker run -it --cpu-period=50000 --cpu-quota=25000 Centos centos /bin/bash
将 CFS 调度的周期设为 50000,将容器在每个周期内的 CPU 配额设置为 25000,表示该容器每 50ms 可以得到 50% 的 CPU 运行时间。
docker run -it --cpu-period=10000 --cpu-quota=20000 Centos centos /bin/bash
将容器的 CPU 配额设置为 CFS 周期的两倍,CPU 使用时间怎么会比周期大呢?其实很好解释,给容器分配两个 vCPU 就可以了。该配置表示容器可以在每个周期内使用两个 vCPU 的 100% 时间。
CFS 周期的有效范围是 1ms~1s,对应的--cpu-period的数值范围是 1000~1000000。
而容器的 CPU 配额必须不小于 1ms,即--cpu-quota的值必须 >= 1000。可以看出这两个选项的单位都是 us。
正确的理解 "绝对"
--cpu-quota 设置容器在一个调度周期内能使用的 CPU 时间时实际上设置的是一个上限。
并不是说容器一定会使用这么长的 CPU 时间。
启动一个容器,将其绑定到 cpu 1 上执行。给其 --cpu-quota 和--cpu-period 都设置为 50000。
docker run -d --name mongo1 --cpuset-cpus 1 --cpu-quota=50000 --cpu-period=50000 docker.io/mongo
调度周期为 50000,容器在每个周期内最多能使用 50000 cpu 时间。
docker run -d --name mongo2 --cpuset-cpus 1 --cpu-quota=50000 --cpu-period=50000 docker.io/mongo
再docker stats mongo-1 mongo-2可以观察到这两个容器,
每个容器对 cpu 的使用率在 50% 左右。说明容器并没有在每个周期内使用 50000 的 cpu 时间。
使用docker stop mongo2命令结束第二个容器,再加一个参数-c 2048 启动它:
docker run -d --name mongo2 --cpuset-cpus 1 --cpu-quota=50000 --cpu-period=50000 -c 2048 docker.io/mongo
再用docker stats mongo-1命令可以观察到第一个容器的 CPU 使用率在 33% 左右,第二个容器的 CPU 使用率在 66% 左右。因为第二个容器的共享值是 2048,第一个容器的默认共享值是 1024,所以第二个容器在每个周期内能使用的 CPU 时间是第一个容器的两倍。