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

内存限额

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

  1. -m / --memory 设置内存的使用限额。
  2. -memory-swap 设置内存+swap 的使用限额。
  3. 例如:
  4. docker run -m 200M --memory-swap=300M ubuntu
  5. #允许容器最多使用200MB 的内存和100MB 的 swap。默认情况下,上面两组参数为-1即不加限制。
  1. docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M #该镜像可对容器进行压力测试
  2. --vm 1 启动一个内存工作线程。
  3. --vm-bytes 280M 每个线程分配280MB 内存。
  4. stress: dbug: [7] allocating 293601280 bytes ...
  5. stress: dbug: [7] touching bytes in strides of 4096 bytes ...
  6. stress: dbug: [7] freed 293601280 bytes
  7. 过程分配280MB 内存,释放280MB 内存,分配,释放......
  8. 让工作线程分配的内存超过限制:
  9. docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M
  10. stress: FAIL: [1] (422) kill error: No such process
  11. stress: FAIL: [1] (452) failed run completed in 1s
  12. 分配的内存超过限额,stress线程报错,容器退出。
  13. #如果在启动容器时只指定了 -m 而不指定 --memory-swap,那么后者默认为 -m 的两倍。

CPU 限额

默认情况下,容器平等使用 host 的 CPU 资源且没有限制。

Docker 可以通过 -c 或 —cpu-shares 设置容器使用 CPU 的权重,如果不指定,默认值为 1024 。

与内存限额不同,通过 -c 或 —cpu-shares 设置的 cpu share 并不是 CPU 资源的绝对数量,而是一个相对的权重值。某个容器最终能够分配到的 CPU 资源取决于其 cpu share 占全部的比例。

  1. docker run --name "container_A" -c 1024 ubuntu
  2. docker run --name "container_B" -c 512 ubuntu
  3. #当两个容器需要 CPU 资源时,A 是 B 的二倍。
  1. 注意:这种按照权重分配 CPU 只会发生在 CPU 资源紧张的状况下,如果container_A 处于空闲状态,这时,为了充分利用 CPU 资源,container_B 也可以分配到全部可用的 CPU
root@Wangying:~# docker run --name container_A -it -c 1024 progrium/stress --cpu 1
stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [8] forked

root@Wangying:~# docker run --name container_B -it -c 512 progrium/stress --cpu 1
stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [7] forked

--cpu 用来设置工作线程的数量。
使用 top 命令,在单核 CPU 上查看可见 A 的 CPU 占用约是 B 的两倍。停止 A 后,可见 B 几乎独自占满。

Block IO 宽带限额

Block IO 是另一种可以限制容器使用的资源。Block IO指的是磁盘的读写,docker 可通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽,下面分别讨论。

block IO 权重

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

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

docker run -it --name container_A --blkio-weight 600 ubuntu
docker run -it --name container_B --blkio-weight 300 ubuntu
#containerA读写磁盘的带宽是containerB的两倍。

限制 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。

docker run -it --device-write-bps /dev/sda:30MB ubuntu
#需要开启权限,但开启后性能下降。
time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
#执行上述命令速度始终在30MB 一下。
dd 测试在容器中写磁盘的速度。
oflag=direct 指定用 direct IO 方式写文件,这样才能使限制生效。