Docker 通过 cgroup 来控制容器使用的 资源配额,包括 CPU、内存、 磁盘等三个大的方面,基本覆盖了常见的资源配额和使用量的控制。
Cgroup( controller group),是Linux内核中提供的一种可以限制、记录、隔离进程组所使用的物理资源,例如CPU、Memory、磁盘IO等等)的机制,被LXC、Docker 等多种项目用于实现进程资源控制。
Cgroup 简单的来理解,就是可以将cpu、内存、磁盘I/O进行资源分配,限制使用的 大小、以及频率
1) 资源限制: 对进程组使用的资源总额进行限制
2) 优先级分配: 通过使用权重值分配CPU 的时间和硬盘的I/O大小
3) 资源统计: 记录容器对硬件的使用,时间用量等等
4) 进程控制: 对进程挂起、恢复等操作
5) 进程组隔离: 使不同的进程组使用不同的Namespace ,打到隔离的目的
不同的进程组有各自的进程、网络、文件系统挂载空间。
查看cgroup 挂载的子系统
[root@localhost ~]# ll /sys/fs/cgroup/
total 0
drwxr-xr-x. 5 root root 0 Mar 25 04:59 blkio
lrwxrwxrwx. 1 root root 11 Mar 25 04:59 cpu -> cpu,cpuacct
lrwxrwxrwx. 1 root root 11 Mar 25 04:59 cpuacct -> cpu,cpuacct
drwxr-xr-x. 5 root root 0 Mar 25 04:59 cpu,cpuacct
drwxr-xr-x. 3 root root 0 Mar 25 04:59 cpuset
drwxr-xr-x. 5 root root 0 Mar 25 04:59 devices
drwxr-xr-x. 3 root root 0 Mar 25 04:59 freezer
drwxr-xr-x. 3 root root 0 Mar 25 04:59 hugetlb
drwxr-xr-x. 5 root root 0 Mar 25 04:59 memory
lrwxrwxrwx. 1 root root 16 Mar 25 04:59 net_cls -> net_cls,net_prio
drwxr-xr-x. 3 root root 0 Mar 25 04:59 net_cls,net_prio
lrwxrwxrwx. 1 root root 16 Mar 25 04:59 net_prio -> net_cls,net_prio
drwxr-xr-x. 3 root root 0 Mar 25 04:59 perf_event
drwxr-xr-x. 5 root root 0 Mar 25 04:59 pids
drwxr-xr-x. 5 root root 0 Mar 25 04:59 systemd
Cgroup 将任意进程进行分组化管理的linux内核功能,cgroup 本身就是提供将进程进行分组化管理的功能和接口的基础结构,I/O或内存的分配控制等具体的资源管理功能是通过这个功能来实现的,这些具体的资源管理功能被称为一个Cgroup子系统。
blkio – 设置限制每个块设备(磁盘、U盘)的输入输出的控制。
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上的 线程
lssubsys -a cgroup
cpuset // 给task 分配独立的CPU
cpu,cpuacct // cpu(控制程序对CPU使用), cpuacct(生成CPU使用情况报告)
memory // 内存使用量进行限制,并且生成报告
devices // 开启关闭设备的访问,不仅仅是块设备
freezer // 挂起和恢复 task
net_cls,net_prio // 没有直接被使用一给网络数据打标签
blkio // 可以为块设备设置输入和输出限制
perf_event // 性能测试
hugetlb // 没有被使用 自动义
pids // 暂时没有被使用, 限制单一的 pid 运行
lssubsys -a
显示系统中支持的所有的子系统
lssybsys -m
显示限制的目录的层次结构
1) 同一个 hierarchy 可以附加一个或者多个子系统
2) 一个已经附加到 hierarchy 的 subsystem ,不可以附加到其他的含有子系统的 hierarchy 上,可以附加到没有定义的控制的 hierarchy。
3) 同一个 task 不能属于同一个 hierarchy 的不同 cgroup中,仅仅可以属于不同的 hierarchy 中的不同的cgroup中。
task 要在当前 hierarchy 当中处于唯一的一个位置。
4) 父进程在哪个task当中,子进程就在 task,子进程属于父进程, 子进程会继承欺负进程的 group
每次在系统中创建新的层级时,该系统中的所有任务都是那个层级的默认 cgroup (我们称为 root cgroup,在此cgroup 创建层级时自动创建,后面在该层级中创建的 cgroup都是此cgroup的后台)的初始成员
Cgroup 层级关系显示, CPU+Memory 两个子系统都有自己独立的层级系统,但是又通过 同一个task(进程)取得了联系。
Cgroup 相当于 跟进程挂上了钩子
yum -y install libcgroup-tools
lscgroup
Docker 提供 -c
或者 --cpu-shares
参数,在创建容器时指定容器所使用的CPU 份额,如果不指定,默认为1024
简单的说就是为 该容器的CPU指定使用宿主机 CPU的使用率
默认情况下,每个docker容器的份额都是 1024,单独的一个容器的份额是没有任何意义的,只有在同时运行多个容器的情况下,容器的CPU 加权的效果才会显示出来。
查看默认的 份额配置
[root@localhost ~]# cd /sys/fs/cgroup/cpu
[root@localhost cpu]# cat cpu.shares
1024
--cpu-shares
OR-c
限制 CPU 使用份额
--cpu-period
指定容器对CPU 的使用要在多久做一次重新分配,单位为 微秒
--cpu-quota
指定在这个周期内,最多可以有多少时间跑来这个容器,与–cpu-shares 相比,–cpu-quota 是一个绝对的值。 --cpu-quota 的值默认为 -1 ,表示不做控制, 单位为微秒
--cpuset-spus
指定CPU内核的节点
--cpuset-mems
指定 Memory 的节点
将宿主机调成单核cpu,用于验证试验效果明显一点
下载 progrium/stress 镜像进行测试
docker pull progrium/stress
[root@localhost ~]# docker run -itd --name aa -c 512 progrium/stress --cpu 1
b5014c68cce454391aec3751eadda317bfd12ac97e2a87b5fb243660488381a9
[root@localhost ~]# docker run -itd --name bb -c 1024 progrium/stress --cpu 1
d47746159b3f778cb4572674f0d565dc65d188d7a140b91e9a14255af24cb54f
[root@localhost docker]# pwd
/sys/fs/cgroup/cpu/docker
[root@localhost docker]# cd b5014c68cce454391aec3751eadda317bfd12ac97e2a87b5fb243660488381a9/
[root@localhost b5014c68cce454391aec3751eadda317bfd12ac97e2a87b5fb243660488381a9]# cat cpu.shares
512
[root@localhost docker]# pwd
/sys/fs/cgroup/cpu/docker
[root@localhost docker]# cd d47746159b3f778cb4572674f0d565dc65d188d7a140b91e9a14255af24cb54f/
[root@localhost d47746159b3f778cb4572674f0d565dc65d188d7a140b91e9a14255af24cb54f]# cat cpu.shares
1024
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G8w35EQ5-1585191910253)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200325191522755.png)]
docker 提供了 --cpu-period
--cpu-quota
两个参数控制容器可以分配到 CPU 时钟周期。
如果 容器进程需要每一秒使用单个CPU 的0.2秒的时间,可以将 cpu-period 设置为 1000000(1,秒),cpu-quota 设置 200000(0.2秒)。
[root@localhost ~]# docker run -itd --name test-cpu --cpu-period 1000000 --cpu-quota 20000 centos /bin/bash
11aab2163f34ad88fa87cd6f336999b524e4daae50be9297d0b38865668198f2
[root@localhost ~]# cat /sys/fs/cgroup/cpu/docker/11aab2163f34ad88fa87cd6f336999b524e4daae50be9297d0b38865668198f2/cpu.cfs_period_us
1000000
[root@localhost ~]# cat /sys/fs/cgroup/cpu/docker/11aab2163f34ad88fa87cd6f336999b524e4daae50be9297d0b38865668198f2/cpu.cfs_quota_us
20000
对于多核的CPU 服务器,Docker 可以控制容器运行时需要的 CPU 内核 的节点
通过 --cpuset-cpus 参数,指定容器所要 使用的 CPU内核节点
只对于有 多核CPU内核的主机生效
调整主机的 CPU 内核数
创建一个容器,只能使用 第一个、第二个内核
[root@localhost ~]# docker run -itd --name cpu --cpuset-cpus 0-1 centos /bin/bash
35fba50c4af0b1422d6db2824c97fe476302403ac3387a4456c708bc0a0f02a1
OR
[root@localhost ~]# docker run -itd --name cpu --cpuset-cpus="0,1" centos /bin/bash
7ed2fa82f40235ecc2973867a0f2115043837d35c1e9afccc400925668c65b91
[root@localhost ~]# docker exec -it cpu /bin/bash
[root@25f4353a555f /]# cat /sys/fs/cgroup/cpuset/cpuset.cpus
0-1
-m
OR--memory
设置内存的使用限额
--memory-swap
设置 内存+swap 的使用xinae
[root@localhost ~]#[root@localhost ~]# docker run -m 200M --memory-swap 300M -itd --name mem centos
3e39464ede52337d5e95e0e6166e80da1262d55a924e6152d1d0032dce0937d1
free -m
查看内存,单位 MB[root@localhost ~]# docker exec -it mem /bin/bash
[root@3e39464ede52 /]# free -m
total used free shared buff/cache available
Mem: 1819 335 1022 9 461 1332
Swap: 2047 0 2047
[root@3e39464ede52 /]# free -g
total used free shared buff/cache available
Mem: 1 0 0 0 0 1
Swap: 1 0 1
docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
参数:
--vm
启动一个内存工作进程
--vm-bytes 280M
每个线程分配 280 内存
[root@localhost ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 350M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [6] forked
stress: dbug: [6] allocating 314572800 bytes ...
stress: dbug: [6] touching bytes in strides of 4096 bytes ...
stress: FAIL: [1] (416) <-- worker 6 got signal 9
stress: WARN: [1] (418) now reaping child worker processes
stress: FAIL: [1] (422) kill error: No such process
stress: FAIL: [1] (452) failed run completed in 0s
分配 280MB内存
释放 280MB内存
再次分配 280MB内存
再次释放 280MB内存
一直循环下去
Block IO 是一种限制容器使用的资源,Block 指定的是磁盘的读写,docker 可以通过设置权重、限制 bps、iops 的方式控制容器读写磁盘的带宽。
相关参数:
--blkio-weight
设置 block IO读写的优先级
--device-read-bps
限制读取某个设备的 bps
--device-write-bps
限制写入某个设备的 bps
--device-read-iops
限制读取某个设备的 iops
--device-write-iops
限制写入某个设备的 iops
bps 与 iops
docker run -it --name io --blkio-weight 600 centos /bin/bash
例子: 限制硬盘每秒读写不超过 100MB
[root@localhost ~]# docker run -it --device-write-bps /dev/sda:95MB --device-read-bps /dev/sda:95MB centos
[root@f86e48c92612 /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 10.8136 s, 99.3 MB/s
docker run -it --name io --blkio-weight 600 centos /bin/bash
例子: 限制硬盘每秒读写不超过 100MB
[root@localhost ~]# docker run -it --device-write-bps /dev/sda:95MB --device-read-bps /dev/sda:95MB centos
[root@f86e48c92612 /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 10.8136 s, 99.3 MB/s