Cgroup 全称Control Group,其作用是限制一个进程组对系统资源的使用上限,包括CPU 、内存、Block I/O等;将一组进程放在一个Cgroup中,通过给这个Cgroup分配指定的可用资源,达到控制这—组进程可用资源的目的;Docker在操作系统的 /sys/fs/cgroup/docker 路径下,为每个容器创建了一个用于资源限制的文件夹,该路径中所有的资源种类均可被cgroup限制。
①、内存限额
容器可使用的内存包括两部分:物理内存和swap分区,如果在启动容器时只指定 -m 的值而不指定–memory-swap 的值, 那么 --memory-swap 默认为 -m 的两倍。
# -m 设置内存的使用限额; --memory-swap 设置内存+swap分区的使用限额
[root@node ~]# docker run -m 200M --memory-swap=300M centos:7
注:容器必须处于运行中,可以在目录 /sys/fs/cgroup/memory/docker/docker_id/下的memory.limit_in_bytes 会显示该容器的内存限额。
使用progrium/stress工具对容器执行压力测试,来探讨内存限额的机制。
❶、使用progrium/stress工具测试内存在不超过限额(内存+swap)的情况下,内存使用的工作机理是:通过给容器分配内存、容器使用、然后释放内存,然后一直循环这个过程;
# --vm 指定启动内存工作线程的个数;--vm-bytes 指定为每个线程分配的内存数
[root@node ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 250M
...
stress: dbug: [8] allocating 262144000 bytes ... #分配内存
stress: dbug: [8] touching bytes in strides of 4096 bytes ...
stress: dbug: [8] freed 262144000 bytes #释放内存
stress: dbug: [8] allocating 262144000 bytes ... #再次分配内存
stress: dbug: [8] touching bytes in strides of 4096 bytes ..
stress: dbug: [8] freed 262144000 bytes #再次释放内存
❷、使用progrium/stress工具测试内存在超过限额(内存+swap)的情况下,容器直接无法启动而退出
[root@node ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 350M
...
stress: FAIL: [1] (422) kill error: No such process
stress: FAIL: [1] (452) failed run completed in 0s
②、CPU份额
默认设置下,所有容器可以平等地使用host CPU 资源并且没有限制;设置的cpu shares 并不是CPU 资源的绝对数量,而是一个相对的权重值;
# -c和--cpu-shares参数一样,都是为容器指定CPU的份额
[root@node ~]# docker run --name container_a -c 1024 centos:7
[root@node ~]# docker run --name container_b --cpu-shares 512 centos:7
注:容器必须处于运行中,可以在目录 /sys/fs/cgroup/memory/docker/docker_id/下的cpu_shares 会显示该容器的CPU份额。
在发生CPU资源抢占的情况下,某个容器最终能分配到的CPU 资源取决于它的cpu share 占所有容器cpu share 总和的比例。
使用progrium/stress工具对容器执行压力测试,来探讨CPU限额的机制。
❶、使用progrium/stress镜像运行两个容器Container_A和Container_B,CPU份额分别设置为1024和512(CPU分配比是2:1)
[root@node ~]# lscpu | grep 'CPU(s)'
CPU(s): 2 #本机有2颗CPU
# --cpu是用来设置工作线程的数量,当前host有2颗CPU,需要2个工作线程来占用CPU资源
[root@node ~]# docker run -d -c 1024 --name Container_A progrium/stress --cpu 2
[root@node ~]# docker run -d -c 512 --name Container_B progrium/stress --cpu 2
❷、使用top查看系统资源使用情况可以看到:在%CPU中呈现出使用分配比为2:1的情况(Container_A分配到的资源是Container_B的两倍),因为是2颗CPU,所以每颗CPU都是按照2:1的比例去分配的。
[root@node ~]# top
...
PID USER PR NI ...SHR S %CPU %MEM TIME+ COMMAND
7167 root 20 0 ...0 R 64.8 0.0 2:56.89 /usr/bin/stress
7164 root 20 0 ...0 R 64.5 0.0 2:56.14 /usr/bin/stress
7416 root 20 0 ...0 R 36.9 0.0 1:10.96 /usr/bin/stress
7417 root 20 0 ...0 R 32.6 0.0 1:11.09 /usr/bin/stress
❸、此时停止Container_A可以看到:运行中的Container_B会独占2颗CPU资源,因为此时并没有发生资源抢占的情况。
[root@node ~]# docker stop Container_A
Container_A
[root@node ~]# top
...
PID USER ...SHR S %CPU %MEM TIME+ COMMAND
7416 root ...96 0 R 99.7 0.0 3:14.73 stress
7417 root ...96 0 R 99.0 0.0 3:15.13 stress
③、Block IO带宽限制
Block IO 指的是磁盘的读写, docker 可通过设置权重weight、限制bps 和iops 的方式控制容器读写磁盘的带宽。
(1).权重weight
默认情况下,所有容器能平等地读写磁盘,可以通过设置–blkio-weight 参数来改变容器block IO 的优先级;–blkio-weight 与–cpu-shares 类似,设置的是相对权重值,默认为500。
(2).限制bps和iops
bps 是 byte per second,每秒读写的数据量,通过 --device-read-bps / --device-write-bps 来限制设备的bps;
iops 是 io per second,每秒IO 的次数,通过 --device-read-iops / --device-write-iops 来限制设备的iops。
❶、验证带宽限制:运行一个base镜像,在没有进行IO带宽限制的情况下是239 MB/s
[root@node ~]# docker run -it centos:7
[root@231682cd2622 /]# dd if=/dev/zero of=test.out bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.438719 s, 239 MB/s
❷、将写IO限制在30M的情况下是30MB/s,注意在容器内部写IO的时候必须添加上oflag=direct参数这样–device-write-bps 才能生效。
注:查看容器使用的磁盘sda,所以限制参数只能限制到 /dev/sda上。
[root@node ~]# docker run -it --device-write-bps /dev/sda:30M centos:7
[root@f8163e8c0552 /]# lsblk #查看容器使用的磁盘sda
...
sda 8:0 0 100G 0 disk
|-sda1 8:1 0 1G 0 part
`-sda2 8:2 0 99G 0 part
[root@f8163e8c0552 /]# dd if=/dev/zero of=test.out bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.412428 s, 254 MB/s
[root@f8163e8c0552 /]# dd if=/dev/zero of=test.out bs=1M count=100 oflag=direct #添加该参数之后才能生效对bps的限制
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 3.3218 s, 31.6 MB/s