目录
前言
一、CPU 资源控制
1、cgroup 介绍
2、cgroup 的功能
3、Cgroup子系统
4、CPU使用率控制
5、限制cpu时间周期
5.1 方式1
5.2 方式2
6、设置容器的权重
7、限制容器使用的cpu(指定使用第2第4个)
8、CPU配额控制参数的混合使用
二、内存资源限制
三、磁盘 IO 配额控制
1、创建容器并限制写速度
2、创建容器并限制写次数
3、清理 docker 占用的磁盘空间
四、构建镜像(docker build)时指定资源限制
总结
在使用 docker 运行容器时,默认的情况下,docker没有对容器进行硬件资源的限制,当一台主机上运行几百个容器,这些容器虽然互相隔离,但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制,那么容器之间会互相影响,小的来说会导致容器资源使用不公平;大的来说,可能会导致主机和集群资源耗尽,服务完全不可用。
Cgroup 是 Control group 的简称,是 Linux 内核提供的一个特性,用于限制和隔离一组进程对系统资源的使用。对不同资源的具体管理是由各个子系统分工完成的。
限制资源使用,比如内存使用上限以及文件系统的缓存限制。
优先级控制,CPU利用和磁盘IO吞吐。
资源统计,主要目的是为了计费。
任务控制,挂起进程,恢复执行进程。
blkio | 设置限制每个块设备的输入输出控制,例如:磁盘、光盘、usb等等 |
CPU | 使用调度程序为cgroup任务提供CPU的访问 |
cpuacct | 产生cgroup任务的CPU资源报告 |
cpuset | 如果是多核心的CPU,这个子系统会为cgroup任务分配单独的CPU和内存 |
devices | 允许或拒绝cgroup任务对设备的访问 |
freezer | 暂停和恢复cgroup任务 |
memory | 设置每个cgroup的内存限制以及产生内存资源报告 |
net_cls | 标记每个网络包以供cgroup方便使用 |
ns | 命名空间子系统 |
perf_event | 增加了对每个group的检测跟踪能力,可以检测属于某个特定的group的所有线程以及运行在特定CPU上的线程 |
[root@localhost docker]# cat /sys/fs/cgroup/cpu/docker/容器ID/cpu.cfs_quota_us
-1
#-1:代表此容器可以使用得资源不受限制
[root@localhost ~]# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
01e51947aa64 t10 0.00% 82.71MiB / 3.683GiB 2.19% 13.5MB / 272kB 0B / 49.1MB 1
假如需要给此容器分配cpu使用率的20%,则参数需要设置为20000,相当于每个周期分配给这个容器0.2s
[root@localhost ~]# docker run -itd --name=t1 --cpu-quota 20000 centos:7 /bin/bash
8167c75eef1a67baaef63e0b8575b9aac91be5ab79edbb51abe7028388f923f2
压力测试
[root@localhost ~]# docker exec -it 8167c75eef1a /bin/bash
[root@8167c75eef1a /]# yum -y install bc
#计算圆周率
[root@8167c75eef1a /]# echo "scale=5000;4*a(1)"| bc -l -q
[root@localhost ~]# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
8167c75eef1a t1 20.00% 74.42MiB / 3.683GiB 1.97% 13.1MB / 223kB 0B / 47.6MB 3
01e51947aa64 t10 0.00% 82.71MiB / 3.683GiB 2.19% 13.5MB / 272kB 0B / 49.1MB 1
[root@localhost ~]# cd /sys/fs/cgroup/cpu/docker/
[root@localhost docker]# echo "20000" > 01e51947aa6402395f05a2573efa48191e3d8b85a67caf1ed58746a44e68d347/cpu.cfs_quota_us
按比例分配设置容器的权重,此处权重是所有值相加然后看占用百分比
[root@localhost docker]# docker run -itd --name=c1 --cpu-shares 512 centos:7 /bin/bash
4421cdb3f44c091ac88a6538725141a627cf0645b5a8917fab1e2425786fc777
[root@localhost docker]# docker run -itd --name=c2 --cpu-shares 1024 centos:7 /bin/bash
ba70c6b4b47e9d77c47ea750a521a83ffd4438f03303835696d6d25f81554048
#创建以上容器,设置权重。会使用512+1024的合,按占比分配权重
压力测试
[root@localhost ~]# docker exec -it 4421cdb3f44c /bin/bash
[root@4421cdb3f44c /]# yum -y install epel-release #依赖包
[root@4421cdb3f44c /]# yum -y install stress
[root@ba70c6b4b47e /]# stress -c 4 #模拟4个CPU工作
###容器B操作相同
[root@localhost ~]# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
ba70c6b4b47e c2 269.75% 120.8MiB / 3.683GiB 3.20% 22MB / 440kB 0B / 49.7MB 7
4421cdb3f44c c1 129.27% 120.9MiB / 3.683GiB 3.21% 22MB / 436kB 0B / 49.8MB 7
[root@localhost ~]# docker run -itd --name=test1 --cpuset-cpus 1,3 centos:7 /bin/bash
5fe80298d3c14087cf9855dcccac0717eebb287588bf9d07786102a03044240a
压力测试
[root@localhost ~]# docker exec -it 5fe80298d3c1 /bin/bash
[root@5fe80298d3c1 /]# yum -y install epel-release
[root@5fe80298d3c1 /]# yum -y install stress
##查看
[root@localhost ~]# top
top - 00:45:27 up 3:19, 3 users, load average: 0.16, 0.08, 0.14
Tasks: 132 total, 3 running, 129 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 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
通过cpuset-cpus参数指定容器A使用CPU内核0,容器B只是用CPU内核1
在主机上只有这两个容器使用对应CPU内核的情况,它们各自占用全部的内核资源,cpu-shares 没有明显效果。
cpuset-cpus. cpuset-mems 参数只在多核、多内存节点上的服务器上有效,并且必须与实际的物理配置匹配,否则也无法达到资源控制的目的。
在系统具有多个CPU内核的情况下,需要通过cpuset-cpus参数为设置容器CPU内核才能方便地进行测试。
docker stop `docker ps -qa`
docker run -itd --name cpu3 --cpuset-cpus 0 --cpu-shares 512 centos:stress stress -c 1
docker run -itd --name cpu4 --cpuset-cpus 2 --cpu-shares 1024 centos:stress stress -c 1
与操作系统类似,容器可使用的内存包括两部分:物理内存和Swap.
Docker通过下面两组参数来控制容器内存的使用量。
-m或–memory: 设置(物理)内存的使用限额,例如100M、 1024M.
–memory-swap: 设置内存+ swap的使用限额。
执行如”下命令允许该容器最多使用200M的内存和300M的swap
docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
--vm 1:启动一个内存工作线程
--vm-bytes 280M:每个线程分配280M内存
默认情况下,容器可以使用主机上的所有空闲内存
与CPU的cgroups配置类似,Docker会自动为容器再目录/sys/fs/cgroup/memory/docker/<容器完整id>中创建相应cgroup配置文件。
如果让线程分配的内存大于等于设定的300M,stress线程报错,容器退出。
docker run -it -m 200M --momory-swap=300M progrium/stress --vm 1 --vm-bytes 300M
–device-read-bps:限制某个设备上的读速度 bps(数据量),单位可以是 kb、mb(M) 或者 gb。
例:docker run -itd --name test1 --device-read-bps /dev/sda:1M centos:7 bash
–device-write-bps:限制某个设备上的写速度 bps(数据量),单位可以是 kb、mb(M) 或者 gb。
例:docker run -itd --name test2 --device-write-bps /dev/sda:1mb centos:7 bash
–device-read-iops:限制读某个设备的 iops(次数)
–device-write-iops:限制写入某个设备的 iops(次数)
[root@docker ~]# docker run -it --name test --device-write-bps /dev/sda:1mb centos:7 bash
[root@d638b2689beb /]# dd if=/dev/zero of=write_test bs=1M count=10 oflag=direct
##添加oflag参数以规避掉文件系统cash
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 10.003 s, 1.0 MB/s
[root@docker ~]# docker run -itd --name test --device-write-iops /dev/sda:10 centos:7 bash
480096c14d1a13953a03573097826b2c151f63a8942998316a67ba45403e6177
[root@docker ~]# docker inspect test
······
"BlkioDeviceWriteIOps": [
{
"Path": "/dev/sda",
"Rate": 10
}
],
······
清除停止的容器以及未被使用的镜像
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 87a94228f133 9 hours ago 133MB
centos 7 eeb6ee3f44bd 3 weeks ago 204MB
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c754e5c5f4f centos:7 "bash" 6 minutes ago Up 6 minutes test1
480096c14d1a centos:7 "bash" 7 minutes ago Exited (137) 5 seconds ago test
[root@docker ~]# 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:
480096c14d1a13953a03573097826b2c151f63a8942998316a67ba45403e6177
Deleted Images:
untagged: nginx:latest
untagged: nginx@sha256:b0c17557e2a3a17bcf18498222824312832f69dbf78edab10f08334900bd7fda
deleted: sha256:87a94228f133e2da99cb16d653cd1373c5b4e8689956386c1c12b60a20421a02
deleted: sha256:55b6972054b24c53054322a52748324df5797eefbb6dc374e41522a91d532dd5
deleted: sha256:6b88aa6f4485486bfc779cccfbe4a7a47a502a7cff2cd70be89c59dcd0db12a8
deleted: sha256:472c64059965c7b6b1b534ba07374c1d034b17c99acb3cf4534fe78abed41101
deleted: sha256:788a5cf1e4599312b5923694f53e556ba0e2eb4a6bbb51958e0ec2b510345a49
deleted: sha256:410f31f9ae37c62af85e8f9575c5f4d75542be1739ac1ca5982cf461be0b13bc
deleted: sha256:e81bff2725dbc0bf2003db10272fef362e882eb96353055778a66cda430cf81b
Total reclaimed space: 133.3MB
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7 eeb6ee3f44bd 3 weeks ago 204MB
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c754e5c5f4f centos:7 "bash" 6 minutes ago Up 6 minutes
--build-arg=[] : 设置镜像创建时的变量
--cpu-shares : 设置 cpu 使用权重
--cpu-period : 限制 CPU CFS 周期
--cpu-quota : 限制 CPU CFS 配额
--cpuset-cpus : 指定使用的CPU id
--cpuset-mems : 指定使用的内存 id
--disable-content-trust : 忽略校验,默认开启
-f : 指定要使用的 Dockerfile 路径
--force-rm : 设置镜像过程中删除中间容器
--isolation : 使用容器隔离技术
--label=[] : 设置镜像使用的元数据
-m : 设置内存最大值
--memory-swap : 设置 Swap 的最大值为内存 +swap,"-1"表示不限 swap
--no-cache : 创建镜像的过程不使用缓存
--pull : 尝试去更新镜像的新版本
--quiet, -q : 安静模式,成功后只输出镜像 ID
--rm : 设置镜像成功后删除中间容器
--shm-size : 设置 /dev/shm 的大小,默认值是 64M
--ulimit : Ulimit 配置
--squash : 将 Dockerfile 中所有的操作压缩为一层
--tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签
--network: 默认 default。在构建期间设置 RUN 指令的网络模式
资源限制的主要类型
① CPU 权重 shares、quota、cpuset、周期 cpu-period
② 磁盘 BPS、TPS 限制,指定使用哪个磁盘、磁盘分区
③ 内存 -m -swap 内存、交换分区
大部分做的是上限的限制
资源限制的几种方式
① build 构建镜像时,可以指定该镜像的资源限制
② run 将镜像跑为容器的时候,可以指定容器的资源限制
③ 容器启动之后,可以在宿主机对应容器的目录下。修改资源限制,然后重载
/sys/fs/cgroup/*(cpu、blk、mem)/docker/容器ID/--->修改对应的资源限制文件参数就可以
资源限制的状态查询
① docker inspect 镜像ID/容器ID
② 直接查看宿主机对应容器 ID 资源限制的文