前戏

一个docker host上会运行若干容器,每个容器都需要CPU、内存和IO资源。对于KVM、VMware等虚拟化技术,用户可以控制分配多少CPU、内存资源给每个虚拟机。对于容器,Docker也提供了类似的机制避免某个容器因占用太多资源而影响其他容器乃至整个host的性能。

内存限额

与操作系统类似,容器可使用的内存包括两部分:物理内存和swap。Docker通过下面两组参数来控制容器内存的使用量。

  • (1)-m或 --memory:设置内存的使用限额,例如100MB,2GB。
  • (2)--memory-swap:设置内存+swap的使用限额

当我们执行如下命令:

    docker run -m 200M --memory-swap=300M 

其含义是允许该容器最多使用200MB的内存和100MB的swap。默认情况下,上面两组参数为 -1,即对容器内存和swap的使用没有限制

例子:

下面我们将使用progrium/stress镜像来学习如何为容器分配内存。该镜像可用于对容器执行压力测试。执行如下命令:

    docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
  •  --vm 1:启动1个内存工作线程。
  •  --vm-bytes 280M:每个线程分配280MB内存。

Docker 资源限制_docker

因为280MB在可分配的范围(300MB)内,所以工作线程能够正常工作,其过程是:

(1)分配280MB内存。

(2)释放280MB内存。

(3)再分配280MB内存。

(4)再释放280MB内存。

(5)一直循环……

如果让工作线程分配的内存超过300MB

Docker 资源限制_工作线程_02

注:分配的内存超过限额,stress线程报错,容器退出

如果在启动容器时只指定 -m而不指定 --memory-swap,那么 --memory-swap默认为 -m的两倍,比如

    docker run -it -m 200M ubuntu

容器最多使用200MB物理内存和200MB swap。

CPU限额

默认设置下,所有容器可以平等地使用host CPU资源并且没有限制。Docker可以通过 -c或 --cpu-shares设置容器使用CPU的权重。如果不指定,默认值为1024。

与内存限额不同,通过 -c设置的cpu share并不是CPU资源的绝对数量,而是一个相对的权重值。某个容器最终能分配到的CPU资源取决于它的cpu share占所有容器cpu share总和的比例。换句话说:通过cpu share可以设置容器使用CPU的优先级。

比如在host中启动了两个容器:

    docker run --name "container_A" -c 1024 ubuntu 
docker run --name "container_B" -c 512 ubuntu

ontainerA的cpu share 1024,是containerB的两倍。当两个容器都需要CPU资源时,containerA可以得到的CPU是containerB的两倍。需要特别注意的是,这种按权重分配CPU只会发生在CPU资源紧张的情况下。如果containerA处于空闲状态,这时,为了充分利用CPU资源,containerB也可以分配到全部可用的CPU。

例子:

1)启动container_A, cpu share为1024

Docker 资源限制_工作线程_03

--cpu用来设置工作线程的数量。因为当前host只有1颗CPU,所以一个工作线程就能将CPU压满。如果host有多颗CPU,则需要相应增加 --cpu的数量。

2)启动container_B, cpu share为512

Docker 资源限制_docker_04

3)在host中执行top,查看容器对CPU的使用情况

Docker 资源限制_工作线程_05

containerA消耗的CPU是containerB的两倍。

4)现在暂停container_A

Docker 资源限制_工作线程_06

5)top显示containerB在containerA空闲的情况下能够用满整颗CPU

Docker 资源限制_ubuntu_07

Block IO带宽限额

默认情况下,所有容器能平等地读写磁盘,可以通过设置 --blkio-weight参数来改变容器block IO的优先级。

--blkio-weight与 --cpu-shares类似,设置的是相对权重值,默认为500。

containerA读写磁盘的带宽是containerB的两倍

docker run -it --name container_A --blkio-weight 600 ubuntu 
docker run -it --name container_B --blkio-weight 300 ubuntu
限制bps和iops

bps是byte per second,每秒读写的数据量。

iops是io per second,每秒IO的次数。

可通过以下参数控制容器的bps和iops:

● --device-read-bps:限制读某个设备的bps。

● --device-write-bps:限制写某个设备的bps。

● --device-read-iops:限制读某个设备的iops。

● --device-write-iops:限制写某个设备的iops。

​例子:

限制容器写 /dev/sda的速率为30 MB/s:

    docker run -it --device-write-bps /dev/sda:30MB ubuntu

Docker 资源限制_docker_08

通过dd测试在容器中写磁盘的速度。因为容器的文件系统是在host /dev/sda上的,在容器中写文件相当于对host /dev/sda进行写操作。另外,oflag=direct指定用direct IO方式写文件,这样 --device-write-bps才能生效。结果表明,bps 25.6 MB/s没有超过30 MB/s的限速。

作为对比测试,如果不限速

Docker 资源限制_docker_09