文章目录
- 前言
- 一、cgroup 介绍
-
-
- 1.cgroup 的四大功能
-
- 二、CPU 资源控制
-
-
- 1.CPU 三种资源控制方法
- 2. 设置 CPU 使用率上限
-
- 2.1 使用率配置
- 2.2 压力测试
- 3. 设置 CPU 资源占用率(多个容器生效)
-
- 3.1 设置资源比例
- 3.2 压力测试(设置宿主机为 4 核)
- 4. 设置容器绑定指定 CPU
-
- 4.1 指定 CPU 设置
- 4.2 压力测试
-
- 二、内存资源限制
-
-
- 1. 物理内存
- 2. 交换空间内存
-
- 三、 磁盘 IO 配额控制
-
-
- 1. 创建容器,限制写速度
- 2. 创建容器,限制写作次数
- 3. 清理 docker 磁盘空间占用
-
- 四、构建镜像(docker build)指定资源限制
- 总结
前言
容器 = cgroup namespace rootfs 容器引擎
- cgroup:资源控制
- namespace:访问隔离
- rootfs:文件系统隔离。镜像的本质是一个 rootfs 文件
- 容器发动机:生命周期控制
一、cgroup 介绍
Cgroup 是 Control group 的简称,是 Linux核心提供的一个特点是限制和隔离系统资源的使用。不同资源的具体管理由各子系统分工完成。
1.cgroup 的四大功能
- 资源限制:任务使用的资源总额可以限制
- 优先分配:通过分配 cpu 时间片的数量和磁盘 IO 带宽大小,实际上相当于控制了任务运行优先级
- 资源统计:可以统计系统的资源利用,如 cpu 时长、内存用量等
- 任务控制:cgroup 可挂起、恢复任务执行等操作
二、CPU 资源控制
1.CPU 三种资源控制方法
- 设置 CPU 使用率上限
- 设置 CPU 资源占用比(设置多个容器时生效)
- 设置容器绑定指定 CPU
2. 设置 CPU 使用率上限
2.1 使用率配置
- Linux 通过 CFS(Completely Fair Schedular,调度完全公平的调度器CPU 的使用。CFS 默认调度周期为100ms。我们可以设置每个容器过程的调度周期,以及每个容器在这个周期中最多 CPU 时间。
- 使用 --cpu-period 可设置调度周期,使用 --cpu-quota 容器可以设置在每个周期内使用 CPU 时间。两者可以一起使用。
- cpu-period 和 cpu-quota 单位为微秒。cpu-period 的最小值为 1000 最大值为微秒 1 秒,默认值为 0.1 秒。
- cpu-quota 的值默认为 -一、表示不做控制。cpu-period 和 cpu-quota 参数一般联合使用。
[root@docker ~]# docker run -itd --name test1 centos:7 bash a9c1ed9d865bec0dd2df5bd42adc157686e916abc1425f6dc9bd624006b1d45a [root@docker ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a9c1ed9d865b centos:7 "bash" 7 seconds ago Up 5 seconds test1 [root@docker ~]# cd /sys/fs/cgroup/cpu/docker/a9c1ed9d865bec0dd2df5bd42adc157686e916abc1425f6dc9bd624006b1d45a/ ###路径为/sys/fs/cgroup/cpu/docker/容器ID开头的文件名 [root@docker a9c1ed9d865bec0dd2df5bd42adc157686e916abc1425f6dc9bd624006b1d45a]# 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 [root@docker a9c1ed9d865bec0dd2df5bd42adc157686e916abc1425f6dc9bd624006b1d45a]# cat cpu.cfs_quota_us -1 [root@docker a9c1ed9d865bec0dd2df5bd42adc157686e916abc1425f6dc9bd624006b1d45a]# cat cpu.cfs_period_us 100000
cpu.cfs_period_us:cpu 分配周期(微秒,默认为 100000) cpu.cfs_quota_us:表示该 cgroups 默认情况下,限制占用时间(微秒) -1.表示没有限制。如果设置为 50000,表示占用 50000/100000=50% 的 CPU。
2.2 压力测试
[root@docker ~]# docker exec -it test1 bash
[root@a9c1ed9d865b /]# vi cpu.sh
#!/bin/bash
i=0
while true
do
let i++
done
[root@a9c1ed9d865b /]# chmod +x cpu.sh
[root@a9c1ed9d865b /]# ./cpu.sh
[root@docker ~]# top
top - 19:59:59 up 6:17, 2 users, load average: 0.94, 0.43, 0.20
Tasks: 213 total, 2 running, 210 sleeping, 1 stopped, 0 zombie
%Cpu(s): 46.2 us, 3.5 sy, 0.0 ni, 50.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 4030168 total, 2481744 free, 625300 used, 923124 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 3058428 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
9732 root 20 0 11688 1096 916 R 100.0 0.0 2:44.05 cpu.sh
##来自 cpu.sh 的命令占用了近 50% 的 CPU 资源
3. 设置 CPU 资源占用比(多个容器生效)
3.1 资源占比设置
Docker 通过 --cpu-shares
指定 CPU 份额,默认值为 1024,值为 1024 的倍数。
创建两个容器为 test1 和 tests2,若只有这两个容器,设置容器的权重,使得 test1 和 test2 的 CPU 资源占比为 1/3 和 2/3。
[root@docker ~]# docker run -itd --name test1 --cpu-shares 1024 centos:7
b4b37e6d33a914756296f165c6cc7317fd48324b4b2a05482bc49ad2f3a5ed06
[root@docker ~]# docker run -itd --name test2 --cpu-shares 2048 centos:7
900ebea2c5ed9fd6adc3fe2b7a823b041f904312e67b9cbd4b9023ae64e38149
#若出现WARNING: IPv4 forwarding is disabled. Networking will not work.
#如下开启宿主机的IP转发功能即可
[root@docker ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
[root@docker ~]# sysctl -p
net.ipv4.ip_forward = 1
[root@docker ~]# systemctl restart network
[root@docker ~]# systemctl restart docker
3.2 压力测试(设置宿主机为 4 核)
test1 容器
[root@docker ~]# docker exec -it test1 bash
[root@b4b37e6d33a9 /]# yum install -y epel-release && yum install -y stress
[root@b4b37e6d33a9 /]# stress -c 4
stress: info: [93] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
test2 容器
[root@docker ~]# docker exec -it test2 bash
[root@900ebea2c5ed /]# yum install -y epel-release && yum install -y stress
[root@900ebea2c5ed /]# stress -c 4
stress: info: [110] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
宿主机查看负载
[root@docker ~]# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
29900b8c61c3 test1 132.90% 2.586MiB / 3.843GiB 0.07% 2.42kB / 0B 4.88MB / 0B 7
c062b6088afb test2 265.13% 1008KiB / 3.843GiB 0.03% 648B / 0B 1.18MB / 0B 7
##由于宿主机开了4核,因此cpu负载为400%
4. 设置容器绑定指定的 CPU
4.1 指定 CPU 设置
[root@docker ~]# docker run -itd --name test1 --cpuset-cpus 0,3 centos:7 bash
##指定本容器使用 0 和 3 号 cpu
a8efc1d070d82266478473be987d98d1a0689c5a44dbbf6f75e6fde70769a346
4.2 压力测试
进入容器压测
[root@docker ~]# docker exec -it test1 bash
[root@a8efc1d070d8 /]# yum install -y epel-release && yum install -y stress
[root@a8efc1d070d8 /]# stress -c 4
stress: info: [166] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
宿主机查看负载
[root@docker ~]# top
top - 17:07:25 up 15 min, 2 users, load average: 0.17, 1.41, 1.61
Tasks: 232 total, 6 running, 226 sleeping, 0 stopped, 0 zombie
%Cpu0 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.3 us, 0.0 sy, 0.0 ni, 99.7 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 : 4030168 total, 2522948 free, 564680 used, 942540 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 3134820 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2989 root 20 0 7312 96 0 R 49.8 0.0 0:02.78 stress
2990 root 20 0 7312 96 0 R 49.8 0.0 0:02.78 stress
2991 root 20 0 7312 96 0 R 49.8 0.0 0:02.79 stress
2992 root 20 0 7312 96 0 R 49.8 0.0 0:02.78 stress
······
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a8efc1d070d8 test1 201.01% 168.7MiB / 3.843GiB 4.29% 27.7MB / 490kB 52.8MB / 25.2MB 7
二、内存资源限制
1. 物理内存
-m(--memory=)选项用于限制容器可以使用的最大内存
[root@docker ~]# docker run -itd --name test1 -m 1g centos:7 bash
add63bbc42c166dc0c7336c36c352760162193f338e4a1b78973ab553ebc7b29
[root@docker ~]# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
add63bbc42c1 test1 0.00% 392KiB / 1GiB 0.04% 578B / 0B 0B / 0B 1
##MEM LIMIT 为物理内存大小
2. 交换空间内存
`–memory-swap 可限制 swap 分区的内存大小,但必须与 -m 命令一起使用。 正常情况下,–memory-swap 的值包含容器可用内存和可用 swap。 所以 -m 300m --memory-swap=1g 的含义为:容器可以使用 300M 的物理内存,并且可以使用 700M(1G-300M)的 swap。 如果 --memory-swap 设置为 0 或者不设置,则容器可以使用的 swap 大小为 -m 值的两倍。 如果 --memory-swap 的值和 -m 相同,则容器不能使用 swap。 如果 --memory-swap 的值为 -1,它表示容器程序使用的内存受限,而可以用的 swap 空间使用不受限制(宿主机有多少 swap 容器就可以使用多少)。
[root@docker ~]# docker run -itd --name test1 -m 300m --memory-swap=1G centos:7 bash
cd4169e1c9a9cba52b5cff580fb60d3694b09d9f5ac843bee339aadc63c6d7a5
##给与容器300M物理内存以及700M交换空间
三、 磁盘 IO 配额控制
–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(次数)
1. 创建容器并限制写速度
[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
2. 创建容器并限制写次数
[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
}
],
······
3. 清理 docker 占用的磁盘空间
docker system prune -a
#清除停止的容器以及未被使用的镜像
[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
四、构建镜像(docker build)时指定资源限制
--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 资源限制的文件