01-本章背景知识

在生产环境里运行服务的一个主要问题是如何公平有效的进行资源分配。
1、Docker 容器使用核心操作系统的 Cgroups 管理容器的 CPU资源分配。
2、Docker 容器资源竞争时,默认使用简单均分(CFS)算法。
3、Docker 容器也可以根据用户需求自定义限制某个容器或者某类容器的 CPU资源。
编者注:本章所有的 CPU 资源是指 CPU 的逻辑个数,而不是物理个数。

一、CPU CFS 调度

1、CFS 是 LInux 内核的 CPU 调度程序。
2、CFS 用于限制 Linux 进程的资源限制和资源使用量。
3、Docker 会根据 CFS 配置修改 Cgroups 资源组配置,从而达到资源限制的目的。
4、针对容器限制的相关参数。

Option

说明

--cpus=<value>

指定一个容器可以使用多少可用的资源。例如:主机有两个 CPU,而你设置 --cpus="1.5" ,那么容器可以使用 1.5 个 CPU 可以被它所使用。这个选项相当于设置 --cpu-period="100000"--cpu-quota="150000" .

--cpu-period=<value>

指定容器对 CPU 的使用要在多长时间内做一次重新分配。需要与 --cpu-quota 一起使用,默认为 100000 微妙(100 毫秒),一般这个参数值无需修改。

--cpu-quota=<value>

是用来指定在这个周期内,最多可以有多少时间用来跑这个容器,单位为微秒,一般这个参数值无需修改。。

--cpuset-cpus

指定一个容器可以使用特定的 CPU 个数,第一个 CPU 的编号为 0,依次类推 1,2,3,4 。例如:--cpuset-cpus=0-3 使用第一,第二,第三,第四 CPU)。--cpuset-cpus=0-1,3 (使用第一,第二,第三 CPU。)

--cpu-shares

当一个容器启动起来后,会得到一个 CPU 的默认为 1024 的值。当只有一个进程在运行的时候,他对一个 CPU 内核 100% 使用权,不管他有多少 CPU 份额。当和其他容器竞争 CPU 的时候,这个数值才有用。

5、 --cpu-shares 详细说明。
假设有 3 台容器(A、B 和 C)同时都在试图使用所有的可用 CPU 资源,并且只有一个 CPU 。
(1)如果他们的 CPU 份额相等,那么每个容器都可以分配到 1/3 的 CPU;
(2)如果 A 和 B 拿到 512,C 拿到 1024,那么 C 将获得 CPU 的一半,A 和 B 各活的 1/4;
(3)如果 A 拿到 10,B 拿到 100,C 拿到 1000,A 可拿到的 CPU 资源为 1%,并且只有在 B 和 C 空闲的时候才能做一些资源消耗较大的工作。
(4)Docker 会尽量将容器的负载分配到所有内核上。如果两个容器在一个双核机器上运行,那么容器权重就会失效。

(5)计算公式如下:
【当前容器份额数值】/【所有容器数值总和】=当前资源权重。
10\10+100+1000 =0.09* 100%=0.9%。

二、CPU 动态调度

1、对 Docker 服务配置时,为全局动态调整方式。
2、对 Docker 容器配置时,为局部动态调整方式。开启动态调度功能首先要配置宿主机操作系统内核。

3、CPU动态调度宿主机操作系统内核配置文件。

参数文件

说明

cpu.rt_period_us

统计 CPU 使用时间的周期,单位 us,最小值为 1 ,t > 1。参数值大:适用于 OLAP 系统。粒度小:适合进程高并发使用,适用于 OLTP 系统。

cpu.rt_runtime_us

周期内允许任务使用单个 CPU 核的时间,如果系统中有多个核,则可以使用核倍数的时间,单位 us,最小值为 0。参数值大:适用于 OLAP 系统。粒度小:适合进程高并发使用,适用于 OLTP 系统。

CPU动态调度是内核的高级功能,一般不需要更改这些值,如果配置不当,则主机系统将变得不稳定或者无法使用。

4、全局 Docker服务配置参数。

参数

说明

–cpu-rt-runtime=950000

单位为微秒。确保实时调度程序的容器可以在 100000 微妙时间内运行 950000 微秒,至少有 50000 微秒可用于非实时任务。

–cpu-rt-period=100000

指定 CPU CFS 调度器周期,需要与 --cpu-quota 一起使用,默认为 100000 微妙(100 毫秒),一般这个参数值无需修改。

5、局部容器级别动态调度参数。

选项

说明

–cap-add=CAP_SYS_NICE

允许提升优先级及设置其他进程的优先级的开关参数。

–cpu-rt-runtime

表示的时间 (缺省是 0.95 s)之后才能被重新调度。必须设置了–cap-add=sys_nice 参数才能使用。

–ulimit rtprio

允许容器设置的最大实时优先级,必须设置了–cap-add=sys_nice 参数才能使用。

LAB 01-容器 CPU 资源静态限制

一、指定容器使用一个 CPU

1、指定使用第一个 CPU。

$ docker run --cpuset-cpus=0 centos:7 -c 'cat /dev/zero  
>/dev/null'

2、启动另外的终端窗口,使用 top 命令会显示出这些个容器只使用了第一个 CPU。

$ top

二、指定容器使用多个 CPU

1、指定使用第一个、第二个、第四个 CPU 。

docker run --cpuset-cpus=0-1,3 centos:7 -c 'cat /dev/zero
>/dev/null'

2、启动另外的终端窗口,使用 top 命令会显示出这些容器只使用了第些 CPU。

$ top

三、指定容器使用的 CPU 权重

1、指定两个容器同时使用第一个 CPU。
2、第一个容器权重为 10000 。
3、第二个容器权重为 1.
4、第二个容器分配的 CPU 资源非常少。

docker run --cpuset-cpus=0 -c 10000 ubuntu:14.04 \  
sh -c 'cat /dev/zero > /dev/null' &  
docker run --cpuset-cpus=0 -c 1 -it ubuntu:14.04 bash

编者注:可以看到在 bash 中执行操作是非常缓慢的。

LAB02-容器 CPU 资源动态限制

一、配置宿主机内核参数

验证在 Linux 内核中是否启用动态调整功能。更多详细的内核实时调度程序,请参见操作系统文档。

cat /sys/fs/cgroup/cpu,cpuacct/cpu.rt_runtime_us
cat /sys/fs/cgroup/cpu,cpuacct/user.slice/cpu.rt_period_us

编者注:如果上述命令有输出信息,则动态调整功能是打开的。

二、对 kcm_centos 01 容器开启进程调度功能

docker run -it \
    --cpu-rt-runtime=950000 \
    --ulimit rtprio=99 \
    --cap-add=sys_nice \
    --name kcm_centos01
    centos:7.2:1152