在Linux中使用cgroups和slice分配资源的步骤及示例
在Linux上使用fstab和systemd来更改/dev/shm,/run和其他文件的tmpfs分区大小。
现在从本文开始," cgroup"或者" Control Group"为进程组提供资源管理和资源核算。就性能而言,Cgroups内核的实现大多位于非关键路径上。 cgroups子系统实现了一个名为"cgroups
"的新虚拟文件系统(VFS)类型。所有cgroup操作都是通过文件系统操作完成的,例如在cgroup文件系统中创建cgroups目录,写入或者读取这些目录中的条目,安装cgroup文件系统等。
cgroups上的指针很少
自kernel 2.6.24以来,cgroup现在已与systemd集成在最新的Linux版本中。
控制组将资源放置在代表资源类型的控制器中,即,我们可以定义可用资源组,以确保应用程序(例如Web服务器)对资源有保证
为了做到这一点,cgroup与默认控制器一起使用,它们是
cpu
,memory
和blkio
。这些控制器分为树形结构,其中对每个分支应用不同的权重或者限制
这些分支中的每一个都是一个cgroup
一个或者多个进程分配给一个cgroup
cgroups可以从命令行或者
systemd
来应用手动创建是通过
cgconfig
服务和cgred
过程进行的在所有情况下,cgroup设置都被写入
/sys/fs/cgroups
中。
# ls -l /sys/fs/cgroup/ total 0 drwxr-xr-x 2 root root 0 Nov 26 12:48 blkio lrwxrwxrwx 1 root root 11 Nov 26 12:48 cpu -> cpu,cpuacct lrwxrwxrwx 1 root root 11 Nov 26 12:48 cpuacct -> cpu,cpuacct drwxr-xr-x 2 root root 0 Nov 26 12:48 cpu,cpuacct drwxr-xr-x 2 root root 0 Nov 26 12:48 cpuset drwxr-xr-x 3 root root 0 Nov 26 12:50 devices drwxr-xr-x 2 root root 0 Nov 26 12:48 freezer drwxr-xr-x 2 root root 0 Nov 26 12:48 hugetlb drwxr-xr-x 2 root root 0 Nov 26 12:48 memory lrwxrwxrwx 1 root root 16 Nov 26 12:48 net_cls -> net_cls,net_prio drwxr-xr-x 2 root root 0 Nov 26 12:48 net_cls,net_prio lrwxrwxrwx 1 root root 16 Nov 26 12:48 net_prio -> net_cls,net_prio drwxr-xr-x 2 root root 0 Nov 26 12:48 perf_event drwxr-xr-x 2 root root 0 Nov 26 12:48 pids drwxr-xr-x 4 root root 0 Nov 26 12:48 systemd
这些是内核本身创建的不同的"控制器"。例如,每个控制器都有自己的"可调参数"
# ls -l /sys/fs/cgroup/cpuacct/ total 0 -rw-r--r-- 1 root root 0 Nov 26 12:48 cgroup.clone_children --w--w---- 1 root root 0 Nov 26 12:48 cgroup.event_control -rw-r--r-- 1 root root 0 Nov 26 12:48 cgroup.procs -r--r--r-- 1 root root 0 Nov 26 12:48 cgroup.sane_behavior -r--r--r-- 1 root root 0 Nov 26 12:48 cpuacct.stat -rw-r--r-- 1 root root 0 Nov 26 12:48 cpuacct.usage -r--r--r-- 1 root root 0 Nov 26 12:48 cpuacct.usage_percpu -rw-r--r-- 1 root root 0 Nov 26 12:48 cpu.cfs_period_us -rw-r--r-- 1 root root 0 Nov 26 12:48 cpu.cfs_quota_us -rw-r--r-- 1 root root 0 Nov 26 12:48 cpu.rt_period_us -rw-r--r-- 1 root root 0 Nov 26 12:48 cpu.rt_runtime_us -rw-r--r-- 1 root root 0 Nov 26 12:48 cpu.shares -r--r--r-- 1 root root 0 Nov 26 12:48 cpu.stat -rw-r--r-- 1 root root 0 Nov 26 12:48 notify_on_release -rw-r--r-- 1 root root 0 Nov 26 12:48 release_agent -rw-r--r-- 1 root root 0 Nov 26 12:48 tasks
了解切片
默认情况下,systemd自动创建切片,作用域和服务单元的层次结构,以为cgroup树提供统一的结构。服务,范围和切片由系统管理员手动创建,或者由程序动态创建。默认情况下,操作系统定义了一些运行系统所需的内置服务。另外,默认情况下会创建四个切片:
-.slice
-根切片;system.slice-所有系统服务的默认位置;
user.slice-所有用户会话的默认位置;
machine.slice-所有虚拟机和Linux容器的默认位置。
在分片中如何分配资源?
让我们以" CPUShares"为例。
现在假设我们将以下" CPUShares"的值分配给以下切片
system.slice -> 1024 user.slice -> 256 machine.slice -> 2048
这些值是什么意思?
实际上,它们实际上没有任何意义,而是将这些值用作所有切片之间的比较因子。其中:如果我们假设总CPU可用性为" 100%",那么" user.slice"将获得"~7%"," system.slice"将获得" user.slice"分配的4倍,即"~30%" 和machine.slice
将获得两倍于system.slice的分配,这大约是可用CPU资源的~60%。
如果我在system.slice中创建多个服务怎么办?
假设我在system.slice内部创建了三个具有CPUShares
值的服务,如下所示,这是一个有效的问题
service1 -> 1024 service2 -> 256 service3 -> 512
如果加起来,总数将大于1024,在上述示例中,该总数实际上已分配给system.slice。再一次,这些值仅是比较的意思,实际上没有任何意义。其中:" service1"将获得最大的可用资源量,即,如果" system.slice"的资源的" 100%"可用,则" service1"将获得"~56%"," service2"将获得~14%
和service3
将获得可用CPU的~28%
"这就是大级别的此cgroup设置如何在不同片之间以及不同片之间与不同服务之间的关系。
如何创建自定义切片?
切片单元的每个名称都对应于层次结构中某个位置的路径。
子片将继承父片的设置。
破折号(-)充当路径组件的分隔符。
例如,如果切片的名称如下所示:
parent-name.slice
这意味着称为" parent-name.slice"的片是" parent.slice"的子片。该片可以具有其自己的名为" parent-name-name2.slice"的子片,依此类推。
使用示例测试资源分配
现在,我们将创建两个systemd单位文件,即stress1.service
和stress2.service
。这些服务脚本将利用我系统上的所有CPU
说明:
为了演示,我禁用了所有其他CPU,并且仅启用了一个CPU。因为如果我们有多个CPU,那么负载将被分配,而我将无法显示CPUShares的资源分配。
使用这些systemd单位文件,我将使用system.slice
来放置一些CPU负载。
# cat /etc/systemd/system/stress1.service [Unit] Description=Put some stress [Service] Type=Simple ExecStart=/usr/bin/dd if=/dev/zero of=/dev/null
这是我的第二个单位文件,具有相同的内容以向CPU施加压力
# cat /etc/systemd/system/stress2.service [Unit] Description=Put some stress [Service] Type=Simple ExecStart=/usr/bin/dd if=/dev/zero of=/dev/null
启动这些服务
# systemctl daemon-reload # systemctl start stress1 # systemctl start stress1
现在使用" top"命令验证CPU使用率
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1994 root 20 0 107992 608 516 R 49.7 0.0 0:03.11 dd 2001 root 20 0 107992 612 516 R 49.7 0.0 0:02.21 dd
如我们所见,由于有两个进程都在系统切片中,因此我有两个进程正在尝试利用可用的CPU,该进程同样会获取可用资源。因此,两个进程都按预期获得了CPU的~50%。
现在,让我们尝试在后台使用while命令在user.slice
上添加一个新进程。
# while true; do true; done &
接下来检查CPU使用情况,现在按预期将"可用CPU分为3个进程"。在user.slice和system.slice之间没有区别
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1983 root 20 0 116220 1404 152 R 32.9 0.0 1:53.28 bash 2193 root 20 0 107992 608 516 R 32.9 0.0 0:07.59 dd 2200 root 20 0 107992 612 516 R 32.9 0.0 0:07.13 dd
说明:
其中:我们看到用户和系统切片级进程都获得了相等数量的可用资源,这是因为默认情况下,我们的发行版中的DefaultCPUAccounting,DefaultBlockIOAccounting和DefaultMemoryAccounting处于禁用状态。
现在,让我们通过启用/etc/systemd/system.conf中的以下值来启用切片
DefaultCPUAccounting=yes DefaultBlockIOAccounting=yes DefaultMemoryAccounting=yes
重新启动节点以激活更改
重要的提示:
重新启动节点以激活更改很重要。
一旦系统恢复启动,接下来我们将再次使用bash shell启动" stress1"和" stress2"服务以及一个" while循环"。
# systemctl start stress1 # systemctl start stress2 # while true; do true; done &
现在使用" top"命令验证CPU使用率
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2132 root 20 0 116220 1520 392 R 49.3 0.0 1:16.47 bash 1994 root 20 0 107992 608 516 R 24.8 0.0 2:30.40 dd 2001 root 20 0 107992 612 516 R 24.8 0.0 2:29.50 dd
如我们所见,我们的切片已生效。现在,用户分片可以要求" CPU的50%",而系统分片则为两种压力服务分配"~25%"的资源。
现在让我们使用" CPUShares"为系统单元文件进一步预留CPU。
# cat /etc/systemd/system/stress2.service [Unit] Description=Put some stress [Service] CPUShares=1024 Type=Simple ExecStart=/usr/bin/dd if=/dev/zero of=/dev/null
# cat /etc/systemd/system/stress1.service [Unit] Description=Put some stress [Service] CPUShares=512 Type=Simple ExecStart=/usr/bin/dd if=/dev/zero of=/dev/null
现在,在上面的单元文件中,我将优先级指定为Stress2.service,以便将分配给Stress1.service的资源加倍。
说明:
CPUShares的允许范围是2到262144. 默认值为1024.
接下来重启服务
# systemctl daemon-reload # systemctl restart stress1 # systemctl restart stress2
验证" top"输出
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2132 root 20 0 116220 1520 392 R 49.7 0.0 2:43.11 bash 2414 root 20 0 107992 612 516 R 33.1 0.0 0:04.85 dd 2421 root 20 0 107992 608 516 R 16.6 0.0 0:01.95 dd
因此,正如预期的那样,在system.slice可用的" 50%" CPU资源中," stress2"获得了分配给" stress1"服务的CPU的"两倍"。
说明:
如果没有从" user.slice"运行的活动进程,则" system.slice"将被允许使用高达100%的可用CPU资源。
监控每片的资源使用情况
" systemd-cgtop"显示了本地Linux控制组层次结构中的顶级控制组,按其" CPU","内存"或者"磁盘I/O"负载排序。显示屏会定期刷新(默认情况下每1秒刷新一次),其样式类似于top命令。资源使用仅考虑相关层次结构中的控制组,即" CPU使用率"仅考虑cpuacct层次结构中的控制组,"内存"使用仅用于内存中的控制组,"磁盘I/O"使用对于blkio中的控制组。
Path Tasks %CPU Memory Input/s Output/s / 56 100.0 309.0M - /system.slice - 97.5 277.4M - /system.slice/stress3.service 1 59.9 104.0K - /system.slice/stress1.service 1 29.9 104.0K - /system.slice/stress2.service 1 7.5 108.0K - /user.slice - 1.7 10.7M - /user.slice/user-0.slice - 1.7 10.4M - /user.slice/user-0.slice/session-7.scope 3 1.7 4.6M - /system.slice/pacemaker.service 7 0.0 41.6M - /system.slice/pcsd.service 1 0.0 46.8M - /system.slice/fail2ban.service 1 0.0 9.0M - /system.slice/dhcpd.service 1 0.0 4.4M - /system.slice/tuned.service 1 0.0 11.8M - /system.slice/NetworkManager.service 3 0.0 11.3M - /system.slice/httpd.service 6 0.0 4.6M - /system.slice/abrt-oops.service 1 0.0 1.4M - /system.slice/rsyslog.service 1 0.0 1.5M - /system.slice/rngd.service 1 0.0 176.0K - /system.slice/ModemManager.service 1 - 3.6M - /system.slice/NetworkManager-dispatcher.service 1 - 944.0K -