注:
- Oracle 提供的免费实验室环境中提供了本教程。
- 它使用 Oracle Cloud Infrastructure 身份证明、租户和区间示例值。完成实验室后,请使用特定于您的云环境的这些值替换这些值。
在 Oracle Linux 上运行控制组版本 2
简介
控制组 (Control Groups, cgroups) 是一项 Linux 内核功能,用于限制、确定优先级并为正在运行的进程分配 CPU 时间、内存和网络带宽等资源。
本教程指导您限制使用 cgroups v2 的用户进程的 CPU 时间。
目标
在此实验室中,您将学习:
- 启用 cgroups v2
- 为用户进程设置软 CPU 限制
- 为用户进程设置硬 CPU 限制
先决条件
- 安装有 Oracle Linux 8 的系统具有以下配置:
- 具有
sudo权限的非 root 用户
- 具有
设置实验室环境
注意:使用免费实验室环境时,请参见 Oracle Linux Lab Basics 了解连接和其他使用情况说明。
在开始实验室之前,我们需要完成一些清洁用品。创建的项目用于演示 cgroup 的限制功能。
创建加载生成脚本
-
如果尚未连接,请打开终端并通过 ssh 连接到 ol8-server 系统。
ssh oracle@<ip_address_of_ol8-server> -
创建
foo.exe脚本。echo '#!/bin/bash /usr/bin/sha1sum /dev/zero' > foo.exe -
将
foo.exe脚本复制到$PATH中的某个位置并设置正确的权限。sudo mv foo.exe /usr/local/bin/foo.exe sudo chown root:root /usr/local/bin/foo.exe sudo chmod 755 /usr/local/bin/foo.exe注意:(可选)如果使用 SELinux
enforcing运行:sudo sestatus通过运行以下命令在复制和更改权限后修复 SELinux 标签:
sudo /sbin/restorecon -v /usr/local/bin/foo.exe
创建加载生成服务
-
创建
foo.service文件。echo '[Unit] Description=the foo service After=network.target [Service] ExecStart=/usr/local/bin/foo.exe [Install] WantedBy=multi-user.target' > foo.service -
将
foo.service脚本复制到 systemd 脚本所在的位置并设置正确的权限。sudo mv foo.service /etc/systemd/system/foo.service sudo chown root:root /etc/systemd/system/foo.service sudo chmod 644 /etc/systemd/system/foo.service注意:(可选)如果使用 SELinux
enforcing运行,请通过运行以下命令在复制和更改权限后修复 SELinux 标签:sudo /sbin/restorecon -v /etc/systemd/system/foo.service -
重新加载守护进程,以便 systemd 识别新服务。
sudo systemctl daemon-reload -
启动
foo.service并检查其状态。sudo systemctl start foo.service sudo systemctl status foo.service
创建用户
其他用户将允许在这些不同的帐户下运行负载生成脚本以及不同的 CPU 权重。
-
创建用户和设置密码。
sudo useradd -u 8000 ralph sudo useradd -u 8001 alice echo "ralph:oracle" | sudo chpasswd echo "alice:oracle" | sudo chpasswd -
允许 SSH 连接。
从
oracle用户帐户复制 SSH 密钥。sudo mkdir /home/ralph/.ssh sudo cp /home/oracle/.ssh/authorized_keys /home/ralph/.ssh/authorized_keys sudo chown -R ralph:ralph /home/ralph/.ssh sudo chmod 700 /home/ralph/.ssh sudo chmod 600 /home/ralph/.ssh/authorized_keys -
对
alice用户重复此步骤。sudo mkdir /home/alice/.ssh sudo cp /home/oracle/.ssh/authorized_keys /home/alice/.ssh/authorized_keys sudo chown -R alice:alice /home/alice/.ssh sudo chmod 700 /home/alice/.ssh sudo chmod 600 /home/alice/.ssh/authorized_keys -
打开新终端并验证两个 SSH 连接是否正常工作。
ssh ralph@<ip_address_of_ol8-server>然后,对会话执行
exit,然后对以下用户重复此步骤。ssh alice@<ip_address_of_ol8-server>退出会话,然后关闭终端窗口。
挂载 cgroups v2
默认情况下,Oracle Linux 在引导时挂载 cgroups v1。要使用 cgroups v2,必须手动配置引导内核参数。
-
返回到您以
oracle身份登录的终端。 -
添加 cgroups v2 systemd 内核参数。
sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"而只能通过运行
sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=1"来指定当前引导项。 -
重新引导。
sudo reboot重新引导需要几分钟才能完成。
注意:在重新引导完成并且 sshd 守护进程正在运行之前,您将无法对系统执行 ssh 操作。
-
通过 ssh 重新连接到 ol8-server 系统。
ssh oracle@<ip_address_of_ol8-server> -
验证是否已挂载 cgroups v2。
sudo mount -l | grep cgroup输出示例:
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate) -
检查 cgroups 已挂载目录的内容。
ll /sys/fs/cgroup输出示例:
total 0 -r--r--r--. 1 root root 0 Mar 13 21:20 cgroup.controllers -rw-r--r--. 1 root root 0 Mar 13 21:20 cgroup.max.depth -rw-r--r--. 1 root root 0 Mar 13 21:20 cgroup.max.descendants -rw-r--r--. 1 root root 0 Mar 13 21:20 cgroup.procs -r--r--r--. 1 root root 0 Mar 13 21:20 cgroup.stat -rw-r--r--. 1 root root 0 Mar 13 21:20 cgroup.subtree_control -rw-r--r--. 1 root root 0 Mar 13 21:20 cgroup.threads -rw-r--r--. 1 root root 0 Mar 13 21:20 cpu.pressure -r--r--r--. 1 root root 0 Mar 13 21:20 cpuset.cpus.effective -r--r--r--. 1 root root 0 Mar 13 21:20 cpuset.mems.effective drwxr-xr-x. 2 root root 0 Mar 13 21:20 init.scope -rw-r--r--. 1 root root 0 Mar 13 21:20 io.pressure -rw-r--r--. 1 root root 0 Mar 13 21:20 memory.pressure drwxr-xr-x. 87 root root 0 Mar 13 21:20 system.slice drwxr-xr-x. 4 root root 0 Mar 13 21:24 user.slice输出显示 root control group 的缺省位置。该目录包含所有以 cgroup 为前缀的接口文件以及与以
.scope和.slice结尾的systemd相关的目录。
使用虚拟文件系统
在开始之前,我们需要了解挂载在 /sys/fs/cgroup 上的 cgroups 虚拟文件系统。
-
显示每个人都参与 CPU 的 CPU。
cat /sys/fs/cgroup/cpuset.cpus.effective输出示例:
[oracle@ol8-server ~]$ cat /sys/fs/cgroup/cpuset.cpus.effective 0-1我们的测试箱是部署在 VM.Standard2.1 配置上的 Oracle Linux 8 实例,这是双核系统。
-
显示哪些控制器处于活动状态。
cat /sys/fs/cgroup/cgroup.controllers输出示例:
[oracle@ol8-server ~]$ cat /sys/fs/cgroup/cgroup.controllers cpuset cpu io memory pids rdma最好查看显示 CPU 控制器,因为我们稍后将在此实验室中使用它。
-
显示
oracle产生的进程。首先,我们需要确定
oracle的用户 ID (UID)。who id输出示例:
[oracle@ol8-server ~]$ who oracle pts/0 2022-03-13 21:23 (10.39.209.157) [oracle@ol8-server ~]$ id uid=1001(oracle) gid=1001(oracle) groups=1001(oracle),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023使用 UID,可以找到
oracle用户分片。cd /sys/fs/cgroup/user.slice ls输出示例:
[oracle@ol8-server ~]$ cd /sys/fs/cgroup/user.slice [oracle@ol8-server user.slice]$ ls cgroup.controllers cgroup.subtree_control memory.events memory.pressure pids.max cgroup.events cgroup.threads memory.events.local memory.stat user-0.slice cgroup.freeze cgroup.type memory.high memory.swap.current user-1001.slice cgroup.max.depth cpu.pressure memory.low memory.swap.events user-989.slice cgroup.max.descendants cpu.stat memory.max memory.swap.max cgroup.procs io.pressure memory.min pids.current cgroup.stat memory.current memory.oom.group pids.eventsSystemd 为每个用户分配一个名为
user-<UID>.slice的分片。那么该目录下是什么?cd user-1001.slice ls输出示例:
[oracle@ol8-server user.slice]$ cd user-1001.slice/ [oracle@ol8-server user-1001.slice]$ ls cgroup.controllers cgroup.max.descendants cgroup.threads io.pressure user-runtime-dir@1001.service cgroup.events cgroup.procs cgroup.type memory.pressure cgroup.freeze cgroup.stat cpu.pressure session-3.scope cgroup.max.depth cgroup.subtree_control cpu.stat user@1001.service这些是
oracle用户的顶层 cgroup。但是,cgroup.procs中未列出进程。那么,用户进程列表在哪里?cat cgroup.procs输出示例:
[oracle@ol8-server user-1001.slice]$ cat cgroup.procs [oracle@ol8-server user-1001.slice]$当
oracle在此实验开始时打开 SSH 会话时,用户会话将创建一个范围子单元。在此范围内,可以检查cgroup.procs以获取该会话下产生的进程列表。注意:根据与系统的连接数,用户可能有多个会话;因此,根据需要替换下面示例中的 3。
cd session-3.scope ls cat cgroup.procs输出示例:
[oracle@ol8-server user-1001.slice]$ cd session-3.scope/ [oracle@ol8-server session-3.scope]$ ls cgroup.controllers cgroup.max.depth cgroup.stat cgroup.type io.pressure cgroup.events cgroup.max.descendants cgroup.subtree_control cpu.pressure memory.pressure cgroup.freeze cgroup.procs cgroup.threads cpu.stat [oracle@ol8-server session-3.scope]$ cat cgroup.procs 3189 3200 3201 54217现在,我们发现这些进程非常困难,因此可以使用
systemd-cgls在树形视图中显示相同的信息。注意:在虚拟文件系统中运行时,
systemd-cgls将 cgroup 输出限制为当前工作目录。cd /sys/fs/cgroup/user.slice/user-1001.slice systemd-cgls输出示例:
[oracle@ol8-server user-1001.slice]$ systemd-cgls Working directory /sys/fs/cgroup/user.slice/user-1001.slice: ├─session-3.scope │ ├─ 3189 sshd: oracle [priv] │ ├─ 3200 sshd: oracle@pts/0 │ ├─ 3201 -bash │ ├─55486 systemd-cgls │ └─55487 less └─user@1001.service └─init.scope ├─3193 /usr/lib/systemd/systemd --user └─3195 (sd-pam)
限制使用的 CPU 核心
对于 cgroups v2,systemd 对 cpuset 控制器具有完全控制权。通过此控制级别,管理员可以仅调度特定 CPU 核心上的工作。
-
检查 CPU
user.slice。cd /sys/fs/cgroup/user.slice ls cat ../cpuset.cpus.effective输出示例:
[oracle@ol8-server cgroup]$ cd /sys/fs/cgroup/user.slice/ [oracle@ol8-server user.slice]$ ls cgroup.controllers cgroup.subtree_control memory.events memory.pressure pids.max cgroup.events cgroup.threads memory.events.local memory.stat user-0.slice cgroup.freeze cgroup.type memory.high memory.swap.current user-1001.slice cgroup.max.depth cpu.pressure memory.low memory.swap.events user-989.slice cgroup.max.descendants cpu.stat memory.max memory.swap.max cgroup.procs io.pressure memory.min pids.current cgroup.stat memory.current memory.oom.group pids.events [oracle@ol8-server user.slice]$ cat ../cpuset.cpus.effective 0-1cpuset.cpus.effective显示了 user.slice 使用的实际核心。如果特定 cgroup 目录中不存在参数,或者未设置参数,则从父级继承值,这恰好是此情况的顶级 cgroup 根目录。 -
将
system和用户 0、1001 和 989 分片限制为 CPU 核心 0。cat /sys/fs/cgroup/system.slice/cpuset.cpus.effective sudo systemctl set-property system.slice AllowedCPUs=0 cat /sys/fs/cgroup/system.slice/cpuset.cpus.effective输出示例:
[oracle@ol8-server user.slice]$ cat /sys/fs/cgroup/system.slice/cpuset.cpus.effective cat: /sys/fs/cgroup/system.slice/cpuset.cpus.effective: No such file or directory [oracle@ol8-server user.slice]$ sudo systemctl set-property system.slice AllowedCPUs=0 [oracle@ol8-server user.slice]$ cat /sys/fs/cgroup/system.slice/cpuset.cpus.effective 0注意:
No such file or directory指示默认情况下,system分片从父级继承其cpuset.cpus.effective值。sudo systemctl set-property user-0.slice AllowedCPUs=0 sudo systemctl set-property user-1001.slice AllowedCPUs=0 sudo systemctl set-property user-989.slice AllowedCPUs=0 -
将
ralph用户限制为 CPU 核心 1。sudo systemctl set-property user-8000.slice AllowedCPUs=1 cat /sys/fs/cgroup/user.slice/user-8000.slice/cpuset.cpus.effective输出示例:
[oracle@ol8-server ~]$ sudo systemctl set-property user-8000.slice AllowedCPUs=1 [oracle@ol8-server ~]$ cat /sys/fs/cgroup/user.slice/user-8000.slice/cpuset.cpus.effective 1 -
打开新终端,并通过 ssh 作为
ralph连接到 ol8-server 系统。ssh ralph@<ip_address_of_ol8-server> -
使用
foo.exe脚本进行测试。foo.exe &检验结果。
top运行
top后,命中1 key以分别显示 CPU。输出示例:
top - 18:23:55 up 21:03, 2 users, load average: 1.03, 1.07, 1.02 Tasks: 155 total, 2 running, 153 sleeping, 0 stopped, 0 zombie %Cpu0 : 6.6 us, 7.0 sy, 0.0 ni, 84.8 id, 0.0 wa, 0.3 hi, 0.3 si, 1.0 st %Cpu1 : 93.0 us, 6.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.3 si, 0.0 st MiB Mem : 14707.8 total, 13649.1 free, 412.1 used, 646.6 buff/cache MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 13993.0 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 226888 ralph 20 0 228492 1808 1520 R 99.7 0.0 199:34.27 sha1sum 269233 root 20 0 223724 6388 1952 S 1.3 0.0 0:00.04 pidstat 1407 root 20 0 439016 41116 39196 S 0.3 0.3 0:17.81 sssd_nss 1935 root 20 0 236032 3656 3156 S 0.3 0.0 0:34.34 OSWatcher 2544 root 20 0 401900 40292 9736 S 0.3 0.3 0:10.62 ruby 1 root 20 0 388548 14716 9508 S 0.0 0.1 0:21.21 systemd ...键入
q退出顶部。 -
检查运行进程的处理器的替代方式。
ps -eo pid,psr,user,cmd | grep ralph输出示例:
[ralph@ol8-server ~]$ ps -eo pid,psr,user,cmd | grep ralph 226715 1 root sshd: ralph [priv] 226719 1 ralph /usr/lib/systemd/systemd --user 226722 1 ralph (sd-pam) 226727 1 ralph sshd: ralph@pts/2 226728 1 ralph -bash 226887 1 ralph /bin/bash /usr/local/bin/foo.exe 226888 1 ralph /usr/bin/sha1sum /dev/zero 269732 1 ralph ps -eo pid,psr,user,cmd 269733 1 ralph grep --color=auto ralphpsr列是cmd或实际进程的 CPU 编号。 -
退出并关闭用于以
ralph身份登录的终端窗口。 -
中止
foo.exe作业。切换回您以
oracle身份登录的终端,然后运行以下命令。sudo pkill sha1sum
调整用户的 CPU 权重
现在可以让 alice 联接有趣的内容。她需要完成一些关键工作,因此,我们会将 CPU 的正常优先级提高一倍。
-
将
alice分配给与ralph相同的 CPU。sudo systemctl set-property user-8001.slice AllowedCPUs=1 cat /sys/fs/cgroup/user.slice/user-8001.slice/cpuset.cpus.effective -
设置
CPUWeight。sudo systemctl set-property user-8001.slice CPUWeight=200 cat /sys/fs/cgroup/user.slice/user-8001.slice/cpu.weight默认权重是 100,因此 200 是该数字的两倍。
-
打开新终端,并通过 ssh 作为
ralph连接到 ol8-server 系统。ssh ralph@<ip_address_of_ol8-server> -
以
ralph身份运行foo.exe。foo.exe & -
打开另一个新终端,并通过 ssh 作为
alice连接到 ol8-server 系统。ssh alice@<ip_address_of_ol8-server> -
以
alice身份运行foo.exe。foo.exe & -
通过
top验证alice是否获得更高优先级。top顶部运行后,命中
1 key以分别显示 CPU。输出示例:
top - 20:10:55 up 25 min, 3 users, load average: 1.29, 0.46, 0.20 Tasks: 164 total, 3 running, 161 sleeping, 0 stopped, 0 zombie %Cpu0 : 0.0 us, 0.0 sy, 0.0 ni, 96.5 id, 0.0 wa, 0.0 hi, 3.2 si, 0.3 st %Cpu1 : 92.4 us, 7.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 15715.8 total, 14744.6 free, 438.5 used, 532.7 buff/cache MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 15001.1 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 7934 alice 20 0 15800 1768 1476 R 67.0 0.0 0:36.15 sha1sum 7814 ralph 20 0 15800 1880 1592 R 33.3 0.0 0:34.60 sha1sum 1 root 20 0 388476 14440 9296 S 0.0 0.1 0:02.22 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd ... -
返回以
oracle用户身份登录的终端。 -
使用
foo.service加载system.slice。sudo systemctl start foo.service现在,查看仍在
alice终端窗口中运行的顶部输出。查看foo.service正在占用 CPU 0,而用户根据其权重拆分 CPU 1。输出示例:
top - 19:18:15 up 21:57, 3 users, load average: 2.15, 2.32, 2.25 Tasks: 159 total, 4 running, 155 sleeping, 0 stopped, 0 zombie %Cpu0 : 89.1 us, 7.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.3 si, 2.6 st %Cpu1 : 93.7 us, 5.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.3 si, 0.0 st MiB Mem : 14707.8 total, 13640.1 free, 420.5 used, 647.2 buff/cache MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 13984.3 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 280921 root 20 0 228492 1776 1488 R 93.4 0.0 0:07.74 sha1sum 279185 alice 20 0 228492 1816 1524 R 65.6 0.0 7:35.18 sha1sum 279291 ralph 20 0 228492 1840 1552 R 32.8 0.0 7:00.30 sha1sum 2026 oracle-+ 20 0 935920 29280 15008 S 0.3 0.2 1:03.31 gomon 1 root 20 0 388548 14716 9508 S 0.0 0.1 0:22.30 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.10 kthreadd ...
分配 CPU 限额
最后,我们将限制 ralph 的 CPU 时间。
-
返回以
oracle用户身份登录的终端。 -
将定额设置为 5%
sudo systemctl set-property user-8000.slice CPUQuota=5%更改将立即生效,如在仍在
alice用户终端中运行的顶部输出中所示。输出示例:
top - 19:24:53 up 22:04, 3 users, load average: 2.21, 2.61, 2.45 Tasks: 162 total, 4 running, 158 sleeping, 0 stopped, 0 zombie %Cpu0 : 93.0 us, 4.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.0 si, 1.7 st %Cpu1 : 91.7 us, 5.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 1.0 hi, 1.0 si, 0.7 st MiB Mem : 14707.8 total, 13639.4 free, 420.0 used, 648.4 buff/cache MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 13984.7 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 280921 root 20 0 228492 1776 1488 R 97.4 0.0 6:26.75 sha1sum 279185 alice 20 0 228492 1816 1524 R 92.1 0.0 12:21.12 sha1sum 279291 ralph 20 0 228492 1840 1552 R 5.3 0.0 8:44.84 sha1sum 1 root 20 0 388548 14716 9508 S 0.0 0.1 0:22.48 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.10 kthreadd ... -
使用
oracle终端窗口恢复ralph用户的上限。
echo "max 100000" | sudo tee -a user-8000.slice/cpu.max
配额将写入 cpu.max 文件,缺省值为 max 100000。
输出示例:
[oracle@ol8-server user.slice]$ echo "max 100000" | sudo tee -a user-8000.slice/cpu.max max 100000
您可以启用 cgroups v2,将用户限制在系统负载不足时使用的特定 CPU,并将其锁定为仅使用该 CPU 的百分比。查看其他资源,了解有关 Oracle Linux 的更多信息。
详细信息
请参阅其他相关资源:
更多学习资源
在 docs.oracle.com/learn 上浏览其他实验室,或者在 Oracle Learning YouTube 渠道上访问更多免费学习内容。此外,访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。
有关产品文档,请访问 Oracle 帮助中心。
Run Control Groups Version 2 on Oracle Linux
F54931-01
March 2022
Copyright © 2022, Oracle and/or its affiliates.