资源限制
资源限制
cgroup
(control group,控制组) 是 Linux 内核的一个功能,可以用来限制、控制与分离一个进程组。Docker 就是通过 cgroup 来控制容器的 CPU、内存、磁盘输入输出等资源。
在默认情况下,Docker 容器是没有资源限制的,它会尽可能地使用宿主机能够分配给它的资源。如果不对容器资源进行限制,容器之间就会相互影响,一些占用硬件资源较高的容器会吞噬掉所有的硬件资源,从而导致其它容器无硬件资源可用,发生停服。
Docker 提供了限制内存,CPU 或磁盘 IO 的方法, 在 docker create 或者 docker run 的时候可以对容器所占用的硬件资源大小以及多少进行限制。
CPU 限制
默认情况下,所有容器可以平等地使用宿主机的 CPU 资源,如果想要限制 CPU 资源,可以使用以下参数进行限制。
相对限制
-c
或--cpu-shares
:用于多个容器运行时设置容器对于 CPU 的使用权重比例(共享权值)。Docker 默认每个容器的权值为
1024
。如果不指定或将其设置为 0,都将使用默认值。当系统上运行了两容器,第一个权重是 1024,第二个权重是 512。第二个启动后没运行任何进程,第一个的进程很多。此时,第一个完全可以占用第二个的 CPU 空闲资源,这就是共享式 CPU 资源。如果第二个也跑了进程,那么就会把自己的 512 给要回来,按照正常权重1024:512 划分。
CPU 共享式证明了 CPU 为可压缩性资源。
--cpus
:用于限制容器运行的核数。- 从 1.13 版本之后开始支持限定容器能使用的 CPU 核数,属于常用的限制手段之一。
--cpuset-cpus
:用于限制容器运行的 CPU 核心。- 例如,主机有 4 个 CPU 核心,CPU 核心标识为 0-3,可以指定容器只在标识 0 和 3 的两个 CPU 核心上运行。
通过 -c 设置的并不是 CPU 资源的绝对数量,而是一个相对的权重值。某个容器最终能分配到的 CPU 资源取决于它的分配的权重占所有容器总和的比例。换句话说,通过 -c 参数可以设置容器使用 CPU 的优先级。
1 | # 指定权重 |
绝对限制
Linux 通过 CFS
(Completely Fair Scheduler,完全公平调度器)来调度各个进程对 CPU 的使用。CFS 默认的调度周期是 100ms
。
我们可以通过设置每个容器进程的调度周期,以及在这个周期内各个容器最多能使用多少 CPU 时间来达到限制 CPU 的目的。具体参数如下:
--cpu-period
:设置每个容器进程的调度周期,单位 us。--cpu-quota
:设置在每个周期内容器能使用的 CPU 时间,单位 us。
示例 1:
1 | # 将 CFS 调度周期设为 50000,将每个周期内的 CPU 配额设置为 25000 |
该配置表示该容器每 50ms 可以得到 50% 的 CPU 运行时间。
示例 2:
1 | # 将容器的 CPU 配额设置为 CFS 周期的两倍 |
CPU 使用时间是周期的两倍,意味着给容器分配了两个 CPU。容器可以在每个周期内使用两个 CPU 的 100% 时间。
CFS 周期的有效范围是 1ms1s,对应的 –cpu-period 的数值范围是 10001000000。
容器的 CPU 配额必须不小于 1ms,即 –cpu-quota 的值必须 >= 1000。
–cpu-quota 设置容器在一个调度周期内能使用的 CPU 时间实际上是一个上限时间,并不是说容器一定会使用这么长的 CPU 时间。
内存限制
在默认的情况下,容器的内存是没有限制的。也是就说,如果不限制,容器将能使用宿主机能够调用的最大内存。
这在生产环境是非常危险的行为,很容易造成宿主机 OOM(内存溢出),然后为了释放内存空间而杀掉一些其它进程,这其中可能包含 docker daemon 进程(docker 对优先级做了调整,一般杀不到它)。但这在生产中是绝对不允许的。
可以通过两个参数限制内存:
-m,--memory
:设置内存使用限额,例如:100MB,1GB。--memory-swap
:设置内存 + Swap 的是使用限额。
默认情况下,两个参数的值都是-1
。但是如果在启动是指定了-m
,那么--memory-swap
会是-m
的两倍。
限制内存使用的示例:
1 | # 允许容器使用 100M 内存和 100M Swap |
如果发生内存溢出错误,内核将 kill 掉容器中的进程。可以使用 --oom-kill-disable
参数控制。
磁盘 IO 限制
Block IO 是另一种可以限制容器使用的资源。Block IO 指的是磁盘的读写,docker 可通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽。
bps
: byte per second,表示每秒读写的数据量。iops
:io per second,表示每秒的输入输出量(或读写次数)。
目前 Block IO 限额只对 direct IO(不使用文件缓存)有效。
支持如下参数:
--blkio-weight
:用于改变容器的权重,类似于 CPU 限制的 -c 参数,默认值为 500。--device-read-bps
:限制读某个设备的 bps。--device-write-bps
:限制写某个设备的 bps。--device-read-iops
:限制读某个设备的 iops。--device-write-iops
:限制写某个设备的 iops。
使用示例:
1 | # 限制读写权重 |