系统版本:RHEL9.3
一、Docker资源限制简介
Linux Cgroups 的全称是 Linux Control Group。
-
是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。
-
对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。
Linux Cgroups 给用户暴露出来的操作接口是文件系统
-
它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。
-
执行此命令查看:mount -t cgroup
cpp
[root@docker ~]# mount -t cgroup #在rhel9中默认使用cgroup2
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/misc type cgroup (rw,nosuid,nodev,noexec,relatime,misc)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
-
在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。
-
在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。
-
控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定。
二、限制CPU的使用
2.1 限制CPU的使用量
不限制容器cpu的使用量的情况下
cpp
# 运行一个容器
[root@docker-node1 ~]# docker run -it --rm ubuntu:latest
root@44a15d349dfa:/# dd if=/dev/zero of=/dev/null & # 使用dd命令占用资源
root@44a15d349dfa:/# top # 容器内查看cpu使用量
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 9 root 20 0 2736 1096 1008 R 100.0 0.0 0:21.14 dd
[root@docker-node1 ~]# top # 系统中查看cpu使用量
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2609 root 20 0 2736 1096 1008 R 99.7 0.0 1:05.57 dd
# 可以发现在没有限制的情况下容器将cpu的资源全部消耗了
限制cpu使用量
cpp
[root@docker ~]# docker run -it --rm --name test \
--cpu-period 100000 \ #设置 CPU 周期的长度,单位为微秒(通常为 100000,即 100 毫秒)
--cpu-quota 20000 ubuntu #设置容器在一个周期内可以使用的 CPU 时间,单位也是微秒。
root@5797d76b20f5:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@5797d76b20f5:/# top
top - 11:53:22 up 1 day, 1:58, 0 user, load average: 0.00, 0.00, 0.00
Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 4.4 us, 6.0 sy, 0.0 ni, 89.5 id, 0.0 wa, 0.2 hi, 0.0 si, 0.0 st
MiB Mem : 3627.1 total, 558.1 free, 899.4 used, 2471.0 buff/cache
MiB Swap: 2063.0 total, 2062.0 free, 1.0 used. 2727.7 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8 root 20 0 2736 1536 1536 R 20.0 0.0 0:00.92 dd #使用cpu的百分比
1 root 20 0 4588 3968 3456 S 0.0 0.1 0:00.03 bash
9 root 20 0 8856 5248 3200 R 0.0 0.1 0:00.00 top
#在cgroup中查看docker的资源限制
[root@docker ~]# cat /sys/fs/cgroup/cpu/docker/"docker id(所要查看容器的id)"/cpu.cfs_period_us #cpu总量划分
[root@docker ~]# cat /sys/fs/cgroup/cpu/docker/"docker id(所要查看容器的id)"/cpu.cfs_quota_us #cpu限制
实例
cpp
# 开启容器并限制只能使用20%的cpu算力
[root@docker-node1 ~]# docker run -it --name test --cpu-period 100000 --cpu-quota 20000 ubuntu:latest
root@b12ac1791814:/# dd if=/dev/zero of=/dev/null &
# 主机中查看cpu使用情况
[root@docker-node1 ~]# top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2802 root 20 0 2736 1100 1012 R 19.6 0.0 0:03.86 dd
# 可以看见现在容器最多使用到20%的cpu算力了
# 查看cpu总量划分
# 注意容器一定需要是运行状态才可以在/docker目录下看到容器id
[root@docker-node1 ~]# cat /sys/fs/cgroup/cpu/docker/43646513c3eab33e4a8ca054aa42b8525259140ec46dacbf6d1ed6366dfa8378//cpu.cfs_period_us
100000
[root@docker-node1 ~]# cat /sys/fs/cgroup/cpu/docker/43646513c3eab33e4a8ca054aa42b8525259140ec46dacbf6d1ed6366dfa8378//cpu.cfs_quota_us
20000
2.2 限制CPU的优先级
cpp
#关闭cpu的核心,当cpu都不空闲下才会出现争抢的情况,为了实验效果我们可以关闭cpu核心到只剩1个
root@docker ~]# echo 0 > /sys/devices/system/cpu/cpu1/online
[root@docker ~]# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 58
model name : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping : 9
microcode : 0x21
cpu MHz : 3901.000
cache size : 8192 KB
physical id : 0
siblings : 1
core id : 0
cpu cores : 1 ##cpu核心数为1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust smep arat md_clear flush_l1d arch_capabilities
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit srbds mmio_unknown
bogomips : 7802.00
clflush size : 64
cache_alignment : 64
address sizes : 45 bits physical, 48 bits virtual
power management:
#开启容器时如果指定了cpu使用优先级,那么设定文件为
[root@docker ~]# cat /sys/fs/cgroup/cpu/docker/"docker id(所要查看容器的id)"/cpu.shares
#开启容器并限制资源
[root@docker ~]# docker run -it --rm --cpu-shares 100 ubuntu #设定cpu优先级,最大为1024,值越大优先级越高
root@dc066aa1a1f0:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@dc066aa1a1f0:/# top
top - 12:16:56 up 1 day, 2:22, 0 user, load average: 1.20, 0.37, 0.20
Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 37.3 us, 61.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 1.0 hi, 0.3 si, 0.0 st
MiB Mem : 3627.1 total, 502.5 free, 954.5 used, 2471.7 buff/cache
MiB Swap: 2063.0 total, 2062.3 free, 0.7 used. 2672.6 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8 root 20 0 2736 1536 1536 R 3.6 0.0 0:16.74 dd #cpu有限制被限制
1 root 20 0 4588 3968 3456 S 0.0 0.1 0:00.03 bash
9 root 20 0 8856 5248 3200 R 0.0 0.1 0:00.00 top
#开启另外一个容器不限制cpu的优先级
root@17f8c9d66fde:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@17f8c9d66fde:/# top
top - 12:17:55 up 1 day, 2:23, 0 user, load average: 1.84, 0.70, 0.32
Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 36.2 us, 62.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 1.3 hi, 0.3 si, 0.0 st
MiB Mem : 3627.1 total, 502.3 free, 954.6 used, 2471.7 buff/cache
MiB Swap: 2063.0 total, 2062.3 free, 0.7 used. 2672.5 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8 root 20 0 2736 1408 1408 R 94.0 0.0 1:09.34 dd #cpu未被限制
1 root 20 0 4588 3968 3456 S 0.0 0.1 0:00.02 bash
9 root 20 0 8848 5248 3200 R 0.0 0.1 0:00.01 top
实例
cpp
# 下线多的cpu
[root@docker-node1 ~]# echo 0 > /sys/devices/system/cpu/cpu1/online
[root@docker-node1 ~]# echo 0 > /sys/devices/system/cpu/cpu2/online
[root@docker-node1 ~]# echo 0 > /sys/devices/system/cpu/cpu3/online
[root@docker-node1 ~]# cat /proc/cpuinfo | grep cores
cpu cores : 1
# 开启容器并限制cpu的优先级
[root@docker-node1 ~]# docker run -it --name test --cpu-shares 100 ubuntu:latest
root@1cae7d65d23d:/#
root@1cae7d65d23d:/# dd if=/dev/zero of=/dev/null & # 开始占用cpu算力
# 查看cpu使用情况
root@1cae7d65d23d:/# top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8 root 20 0 2736 1080 992 R 99.0 0.0 0:38.71 dd # 可见cpu被占完
# 开启另外一个不限制cpu优先级的容器
[root@docker-node1 ~]# docker run -it --name test1 ubuntu:latest
root@d74c046e084e:/# dd if=/dev/zero of=/dev/null & # 开始占用cpu
# 查看cpu使用情况
root@d74c046e084e:/# top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
9 root 20 0 2736 1180 1092 R 90.0 0.0 0:26.90 dd # 可见该处cpu占用到了90%
# 查看被限制优先级的容器的cpu占用情况
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND # 可见只能使用10%的cpu了
8 root 20 0 2736 1080 992 R 9.0 0.0 1:42.46 dd
# 如果两个都没有限制的容器均开始抢占则互相平分cpu算力,一边50%,不再
三、限制内存的使用
示例
cpp
# 开启nginx限制内存
[root@docker-node1 ~]# docker run -d --name test --memory 200M --memory-swap 200M nginx:1.26
07eaa4c6be323e61b11d306ffdf2b7ceb409edd3cda8b3a7655b3365753c660c
# 查看
[root@docker-node1 ~]# cat /sys/fs/cgroup/memory/docker/07eaa4c6be323e61b11d306ffdf2b7ceb409edd3cda8b3a7655b3365753c660c/memory.memsw.limit_in_bytes
209715200
# 安装检测工具
[root@docker-node1 ~]# rpm -ivh libcgroup-0.41-19.el8.x86_64.rpm
[root@docker-node1 ~]# rpm -ivh libcgroup-tools-0.41-19.el8.x86_64.rpm
# 检测
[root@docker-node1 ~]# cgexec -g memory:docker/07eaa4c6be323e61b11d306ffdf2b7ceb409edd3cda8b3a7655b3365753c660c dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200M
已杀死
[root@docker-node1 ~]# df -h
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 1.8G 194M 1.6G 11% /dev/shm # /dev/shm 是 Linux 系统中(不是磁盘!),专为进程间高速共享数据设计的内存虚拟文件系统。它像一块"内存白板"------多个程序能同时读写它,速度比磁盘快千倍,但断电即消失。你向 /dev/shm 写文件时,直接存入内存的 page cache
四、限制Docker的磁盘IO
示例
cpp
# 创建容器并使用dd命令写入
[root@docker-node1 ~]# docker run -it --name test --rm ubuntu:latest
root@46806e7c5239:/# dd if=/dev/zero of=/bigfile bs=1M count=1000
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 3.25502 s, 322 MB/s
# 可以看见IO速度非常快
# 重新创建限制的容器并dd命令写入
[root@docker-node1 ~]# docker run -it --rm --device-write-bps /dev/sda:30M ubuntu:latest
root@ea955e653e89:/# dd if=/dev/zero of=/bigfile bs=1M count=1000 oflag=direct
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 33.3383 s, 31.5 MB/s
# 可以看见IO速度被限制