目录
一、cgroups简介
cgroups有四大功能:
二、cpu时间片的概念
三、对CPU使用的限制
3.1 设置CPU使用率上限
(1)查看容器的默认CPU使用限制
(2)进行压力测试
(3)创建容器时设置CPU使用时间限制
(4)对已存在的容器进行CPU限制
3.2 设置CPU资源占用比(设置多个容器时才有效)
(1)创建两个容器,设置CPU资源占用比
(2)分别进入两个容器,进行压力测试
(3)查看容器运行状态,观察CPU使用占比
3.3 设置容器绑定指定的CPU(绑核)
四、对内存使用的限制
4.1 限制容器可以使用的最大内存
4.2 限制容器可用的swap 大小
五、对磁盘IO的配置控制(blkio)的限制
5.1 创建容器,不限制写速度
5.2 创建容器,并限制写速度
六、清除docker占用的磁盘空间
总结
1.对cpu的限制参数
2.对内存的限制
3.对磁盘IO的限制
一、cgroups简介
cgroups,是一个非常强大的linux内核工具,他不仅可以限制被namespace 隔离起来的资源,还可以 为资源设置权重、计算使用量、操控进程启停等等。所以cgroups (Control groups) 实现了对资源的配额和度量。
cgroups有四大功能:
- 资源限制:可以对任务使用的资源总额进行限制。
- 优先级分配:通过分配的cpu时间片数量以及磁盘IO带宽大小,实际上相当于控制了任务运行优先级。
- 资源统计:可以统计系统的资源使用量,如cpu时长,内存用量等。
- 任务控制: cgroup可以对任务 执行挂起、恢复等操作。
二、cpu时间片的概念
时间片即CPU分配给各个程序的时间,每个线程被分配一个时间段,称作它的时间片,即该进程允许运行的时间,使各个程序从表面上看是同时进行的。如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。而不会造成CPU资源浪费。
在宏观上:我们可以同时打开多个应用程序,每个程序并行不悖,同时运行。但在微观上:由于只有一个CPU,一次只能处理程序要求的一部分,如何处理公平,一种方法就是引入时间片,每个程序轮流执行。
三、对CPU使用的限制
3.1 设置CPU使用率上限
Linux通过CFS (Completely Fair Scheduler, 完全公平调度器)来调度各个进程对CPU的使用。CFS默认的调度周期是100ms。
我们可以设置每个容器进程的调度周期,以及在这个周期内各个容器最多能使用多少CPU时间。
使用 --cpu-period 即可设置调度周期,使用 --cpu-quota 即可设置在每个周期内容器能使用的CPU时间。两者可以配合使用。
CFS周期的有效范围是1ms ~ 1s, 对应的 --cpu-period 的数值范围是 1000 ~1000000 (单位微秒)。
而容器的CPU配额必须不小于1ms,即 --cpu-quota 的值必须 >= 1000。
(1)查看容器的默认CPU使用限制
#创建并启动容器 [root@yuji ~]# docker run -itd --name test1 centos:7 /bin/bash WARNING: IPv4 forwarding is disabled. Networking will not work. 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08 #查看容器状态 [root@yuji ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 059823a1abbe centos:7 "/bin/bash" 12 seconds ago Up 10 seconds test1 #切换到cgroup下针对容器的相关配置目录 [root@yuji ~]# cd /sys/fs/cgroup/cpu/docker/ [root@yuji docker]# ls 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08 cpu.cfs_quota_us cgroup.clone_children cpu.rt_period_us cgroup.event_control cpu.rt_runtime_us cgroup.procs cpu.shares cpuacct.stat cpu.stat cpuacct.usage notify_on_release cpuacct.usage_percpu tasks cpu.cfs_period_us ##切换到test1容器的目录 [root@yuji docker]# cd 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08 [root@yuji 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08]# ls cgroup.clone_children cgroup.procs cpuacct.usage cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release cgroup.event_control cpuacct.stat cpuacct.usage_percpu cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks ##查看test1容器的CPU使用限额。即每个调度周期内可占用的CPU时间(单位:微秒) [root@yuji 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08]# cat cpu.cfs_quota_us -1 #默认为-1,表示不限制 ##查看CPU调度周期(单位:微秒) [root@yuji 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08]# cat cpu.cfs_period_us 100000 #单位微秒,即100毫秒,0.1秒 #cpu.cfs_period_us:分配的周期(微秒,所以文件名中用u),默认为100000。 #cpu.cfs_quota_us:表示该cgroups限制占用的时间(微秒),默认为-1,表示不限制。 #cpu.cfs_quota_us 如果设为50000,表示占用 50000/100000=50%的CPU。
(2)进行压力测试
[root@yuji ~]# docker exec -it test1 bash #进入容器 [root@059823a1abbe /]# vi /cpu.sh #写个死循环脚本 #!/bin/bash i=0 while true do let i++ done [root@059823a1abbe /]# chmod +x cpu.sh #给脚本权限 [root@059823a1abbe /]# ./cpu.sh #运行脚本 #再开一个终端,查看cpu.sh进程的cpu使用率 [root@localhost ~]# top #可以看到使用率接近100% PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3328 root 20 0 11688 1100 916 R 99.7 0.1 7:04.44 cpu.sh #之后在容器中使用ctrl+c,停止脚本的执行,再top观察CPU使用率
(3)创建容器时设置CPU使用时间限制
#创建容器test2,并限制CPU使用时间为50000微秒,表示最多占用50%的CPU。 [root@yuji ~]# docker run -itd --name test2 --cpu-quota 50000 centos:7 WARNING: IPv4 forwarding is disabled. Networking will not work. 8e7ba758a231b29dad1f668ba83092e8f637d2a9785999c6d23b27c60935b12b #查看CPU限额文件 [root@yuji ~]# cd /sys/fs/cgroup/cpu/docker/ [root@yuji docker]# ls 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08 cpuacct.usage cpu.shares 8e7ba758a231b29dad1f668ba83092e8f637d2a9785999c6d23b27c60935b12b cpuacct.usage_percpu cpu.stat cgroup.clone_children cpu.cfs_period_us notify_on_release cgroup.event_control cpu.cfs_quota_us tasks cgroup.procs cpu.rt_period_us cpuacct.stat cpu.rt_runtime_us [root@yuji docker]# cd 8e7ba758a231b29dad1f668ba83092e8f637d2a9785999c6d23b27c60935b12b [root@yuji 8e7ba758a231b29dad1f668ba83092e8f637d2a9785999c6d23b27c60935b12b]# cat cpu.cfs_quota_us 50000 #登录容器test2,写个死循环脚本并运行 [root@yuji ~]# docker exec -it test2 bash [root@8e7ba758a231 /]# vi /cpu.sh #!/bin/bash i=0 while true do let i++ done [root@8e7ba758a231 /]# chmod +x cpu.sh [root@8e7ba758a231 /]# ./cpu.sh #再开一个终端,查看cpu使用率 [root@yuji ~]# top #CPU使用率在50%左右 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3746 root 20 0 11688 1096 916 R 50.0 0.1 1:55.26 cpu.sh #容器的CPU使用时间限制设为50000,而调度周期为100000,表示容器占用50000/100000=50%的CPU。
(4)对已存在的容器进行CPU限制
直接修改 /sys/fs/cgroup/cpu/docker/容器id/cpu.cfs_quota_us 文件即可
#进入test1容器目录,修改CPU使用时间限制 [root@yuji ~]# cd /sys/fs/cgroup/cpu/docker/ [root@yuji docker]# ls 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08 cpuacct.usage cpu.shares 8e7ba758a231b29dad1f668ba83092e8f637d2a9785999c6d23b27c60935b12b cpuacct.usage_percpu cpu.stat cgroup.clone_children cpu.cfs_period_us notify_on_release cgroup.event_control cpu.cfs_quota_us tasks cgroup.procs cpu.rt_period_us cpuacct.stat cpu.rt_runtime_us [root@yuji docker]# cd 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08 #修改CPU使用时间限制 [root@yuji 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08]# echo "33000" >cpu.cfs_quota_us [root@yuji 059823a1abbe2ac6ed35599ca0d3d68049e49263ff9add8f65cc55daa094ec08]# cat cpu.cfs_quota_us 33000 #此时再进入test1容器执行之前创建好的脚本,进行压力测试 [root@yuji ~]# docker exec -it test1 bash [root@059823a1abbe /]# ./cpu.sh #再开一个终端,查看cpu使用率 [root@localhost ~]# top PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4635 root 20 0 11688 1096 916 R 33.3 0.1 1:27.62 cpu.sh #容器的CPU使用时间限制设为33000,而调度周期为100000,表示容器占用33000/100000=33%的CPU。
3.2 设置CPU资源占用比(设置多个容器时才有效)
Docker 通过 --cpu-shares 指定CPU份额,默认值为1024,值为1024的倍数。
(1)创建两个容器,设置CPU资源占用比
#先删除所有容器 [root@yuji ~]# docker rm -f $(docker ps -aq) 9c48e09ea156 7c7e024b557e #创建两个容器为c1和c2 #只有这2个容器的情况下,cpu资源分摊给这两个容器,512:1024等于1:2,一个占1/3,一个占2/3。 [root@yuji ~]# docker run -itd --name c1 --cpu-shares 512 centos:7 WARNING: IPv4 forwarding is disabled. Networking will not work. 300b50f13ebef4921029e352f5850b1c81f8f8e28827a8d11f20e55eec94642b [root@yuji ~]# docker run -itd --name c2 --cpu-shares 1024 centos:7 WARNING: IPv4 forwarding is disabled. Networking will not work. 7a999b00c9eef7fdb916c2914087809e7eba55b1c52aaaabeeda16a4006f57a9 [root@yuji ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7a999b00c9ee centos:7 "/bin/bash" 4 seconds ago Up 3 seconds c2 300b50f13ebe centos:7 "/bin/bash" 6 seconds ago Up 5 seconds c1
(2)分别进入两个容器,进行压力测试
#宿主机开启路由转发功能,使容器能够连通外网 [root@yuji ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf [root@yuji ~]# sysctl -p net.ipv4.ip_forward = 1 #进入c1容器,进行压力测试 docker exec -it c1 bash yum install -y epel-release #下载epel源 yum install -y stress #安装stress工具 stress -c 4 #产生四个进程,每个进程都反复不停地计算随机数的平方根 #进入c2容器,进行压力测试 docker exec -it c2 bash yum install -y epel-release #下载epel源 yum install -y stress #安装stress工具 stress -c 4 #产生四个进程,每个进程都反复不停的计算随机数的平方根
进入c1容器,进行压力测试:
进入c2容器,进行压力测试:
(3)查看容器运行状态,观察CPU使用占比
#再打开一个终端,查看容器运行状态(动态更新) [root@yuji ~]# docker stats #可以看到CPU使用占比大约是1:2 CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 7a999b00c9ee c2 266.52% 188.9MiB / 1.938GiB 9.52% 32.8MB / 152kB 1.91MB / 50MB 7 300b50f13ebe c1 133.03% 203.1MiB / 1.938GiB 10.24% 33.7MB / 603kB 108MB / 51.4MB 7 #因为宿主机有4核,所以CPU总百分比是400%。 #c1:c2 = 133.03%:266.52% ≈ 1:2
3.3 设置容器绑定指定的CPU(绑核)
注意:CPU编号从0开始。 编号1、3代表第二个核和第四个核 。
#先为虚拟机分配4个CPU核数 #创建容器c3时,绑定1号和3号这两个CPU [root@yuji ~]# docker run -itd --name c3 --cpuset-cpus 1,3 centos:7 /bin/bash #进入容器,进行压力测试 docker exec -it c3 bash yum install -y epel-release #下载epel源 yum install -y stress #安装stress工具 stress -c 4 #产生四个进程,每个进程都反复不停地计算随机数的平方根 #退出容器,执行top命令再按1查看CPU使用情况 [root@yuji ~]# top #可以看到CPU1和CPU3占满,其他CPU使用率为0 top - 01:12:49 up 4:01, 3 users, load average: 3.47, 2.96, 2.49 Tasks: 183 total, 6 running, 177 sleeping, 0 stopped, 0 zombie %Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 2031912 total, 150852 free, 635800 used, 1245260 buff/cache KiB Swap: 4194300 total, 4194236 free, 64 used. 1138692 avail Mem
四、对内存使用的限制
4.1 限制容器可以使用的最大内存
-m (或--memory=)选项用于限制容器可以使用的最大内存
#-m(--memory=)选项用于限制容器可以使用的最大内存。 #创建容器c4,并限制容器可以使用的最大内存为512m [root@yuji ~]# docker run -itd --name c4 -m 512m centos:7 /bin/bash #查看容器状态,可以看到c4可以使用的最大内存是512M [root@yuji ~]# docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 437180fc6266 c4 0.00% 396KiB / 512MiB 0.08% 648B / 0B 0B / 0B 1 ebcc06da3a03 c3 0.00% 174.2MiB / 1.938GiB 8.78% 32.8MB / 196kB 47.7MB / 50.6MB 1 7a999b00c9ee c2 0.00% 101.7MiB / 1.938GiB 5.13% 32.9MB / 152kB 1.91MB / 50MB 2 300b50f13ebe c1 0.00% 113MiB / 1.938GiB 5.69% 33.7MB / 603kB 108MB / 51.4MB 1
4.2 限制容器可用的swap 大小
#限制可用的swap 大小,--memory-swap ●强调一下, --memory-swap是必须要与 --memory(或-m)一起使用的。 ●正常情况下, --memory-swap 的值包含容器可用内存和可用swap 。 ●所以 -m 300m --memory-swap=1g 的含义为:容器可以使用300M 的物理内存,并且可以使用700M (1G - 300M)的swap。 设置为0或者不设置,则容器可以使用的 swap 大小为 -m 值的两倍。 如果 --memory-swap 的值和 -m 值相同,则容器不能使用swap。 如果 --memory-swap 值为 -1,它表示容器程序使用的内存受限,而可以使用的swap空间使用不受限制(宿主机有多少swap 容器就可以使用多少)。
示例:
#--memory-swap 的值包含容器可用内存和可用swap,减去-m的值才是可用swap的值。 #表示容器可以使用512M的物理内存,并且可以使用512M的swap。因为1g减去512m的物理内存,剩余值才是可用swap。 docker run -itd --name yy01 -m 512m --memory-swap=1g centos:7 bash #--memoryswap值和 -m 的值相同,表示容器无法使用swap docker run -itd --name yy02 -m 512m --memory-swap=512m centos:7 bash # --memory-swap 的值设置为0或者不设置,则容器可以使用的 swap 大小为 -m 值的两倍。 docker run -itd --name yy03 -m 512m centos:7 bash # --memory-swap 值为 -1,它表示容器程序使用的内存受限,但可以使用的swap空间使用不受限制(宿主机有多少swap 容器就可以使用多少)。 docker run -itd --name yy04 -m 512m --memory-swap=-1 centos:7 bash
五、对磁盘IO的配置控制(blkio)的限制
--device-read-bps:限制某个设备上的读速度bps ( 数据量),单位可以是kb、mb (M)或者gb。
--device-write-bps : 限制某个设备上的写速度bps ( 数据量),单位可以是kb、mb (M)或者gb。
--device-read-iops :限制读某个设备的iops (次数)
--device-write-iops :限制写入某个设备的iops ( 次数)
--device-read-bps:限制某个设备上的读速度bps ( 数据量),单位可以是kb、mb (M)或者gb。
例: docker run -itd --name test9 --device-read-bps /dev/sda:1M centos:7 /bin/bash
#表示该容器每秒只能读取1M的数据量
--device-write-bps : 限制某个设备上的写速度bps ( 数据量),单位可以是kb、mb (M)或者gb。
例: docker run -itd --name test10 --device-write-bps /dev/sda:1mb centos:7 /bin/bash
#表示该容器每秒只能写入1M的数据量
--device-read-iops :限制读某个设备的iops (次数)
--device-write-iops :限制写入某个设备的iops ( 次数)
5.1 创建容器,不限制写速度
#创建容器tt01,不限制写入速度
docker run -it --name tt01 centos:7 /bin/bash
#通过dd来验证写速度,拷贝50M的数据
dd if=/dev/zero of=/opt/test.out bs=10M count=5 oflag=direct #添加oflag参数以规避掉文件系统cache
#创建容器tt01,不限制写入速度
[root@yuji ~]# docker run -it --name tt01 centos:7 /bin/bash
#通过dd来验证写速度,拷贝50M的数据到容器中
[root@a62f5b811e58 /]# dd if=/dev/zero of=/opt/test.out bs=10M count=5 oflag=direct #添加oflag参数以规避掉文件系统cache
5+0 records in
5+0 records out
52428800 bytes (52 MB) copied, 0.0948474 s, 553 MB/s
#没有限制写速度的情况下,写入很快,0.09秒的时间内已写入50M的数据,写入速度为553M/s。
5.2 创建容器,并限制写速度
#创建容器,并限制写入速度为1MB/s,即每秒只能写入1MB的数据量。
[root@yuji ~]# docker run -it --name tt02 --device-write-bps /dev/sda:1mb centos:7 bash
#通过dd来验证写速度,拷贝50M的数据到容器中
[root@655f6cca0175 /]# dd if=/dev/zero of=/opt/test.out bs=10M count=5 oflag=direct #添加oflag参数以规避掉文件系统cache
5+0 records in
5+0 records out
52428800 bytes (52 MB) copied, 50.0048 s, 1.0 MB/s
#写入50M的数据,需要50s左右,因为限制了容器的写速度是 1.0 MB/s。
六、清除docker占用的磁盘空间
docker system prune -a 可用于清理磁盘,删除关闭的容器、无用的数据卷和网络。
示例:
#查看容器
[root@yuji ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
655f6cca0175 centos:7 "bash" 10 minutes ago Exited (0) 4 minutes ago tt02
a62f5b811e58 centos:7 "/bin/bash" 19 minutes ago Exited (0) 11 minutes ago tt01
437180fc6266 centos:7 "/bin/bash" 36 minutes ago Up 36 minutes c4
ebcc06da3a03 centos:7 "/bin/bash" 50 minutes ago Up 50 minutes c3
#清理磁盘,删除关闭的容器、无用的数据卷和网络。
[root@yuji ~]# docker system prune -a
WARNING! This will remove: #提示
- all stopped containers #删除清理所有停止的容器
- all networks not used by at least one container #删除未被使用的网络
- all images without at least one container associated to them #未被使用的镜像
- all build cache #删除已建立的缓存
Are you sure you want to continue? [y/N] y #是否确定删除
Deleted Containers:
655f6cca01754d27a080e01b64aa26c4f96642ab5b5931b186ad04082a98430f
a62f5b811e584cc6e8d344830d5df9ddcbdd72761966989245b0c52f6abb9a4a
......
Total reclaimed space: 451MB
#再次查看容器,只剩下启动中的容器
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
525d77ff7423 centos:7 "/bin/bash" 3 minutes ago Up 3 minutes c6
fb2ee21e0468 centos:7 "/bin/bash" 12 minutes ago Up 12 minutes c4
81e3ea8f526e centos:7 "/bin/bash" 18 minutes ago Up 18 minutes c3
总结
1.对cpu的限制参数
docker run -cpu-period #设置调度周期时间1000~1000000
-cpu-quota #设置容器进程的CPU占用时间,要与调度周期时间成比例
--cpu-shares #设置多个容器之间的CPU资源占用比
--cpuset-cpus #绑核(第一个CPU编号从0开始)
2.对内存的限制
-m 物理内存 [--memory-swap=总值]
3.对磁盘IO的限制
--device-read-bps 设备文件:1mb/1M #限制读速度
--device-write-bps 设备文件:1mb/1M #限制写速度
--device-read-iops #限制读次数
--device-write-iops #限制写次数
docker system prune -a #清理磁盘,删除关闭的容器、无用的数据卷和网络。