如何在使用 cgroups v2 的 Ubuntu 22.04 上以当前用户身份在不使用 sudo 的情况下运行 cgexec,并出现“cgroup 组更改失败”的提示?

如何在使用 cgroups v2 的 Ubuntu 22.04 上以当前用户身份在不使用 sudo 的情况下运行 cgexec,并出现“cgroup 组更改失败”的提示?

我尝试过以下步骤:

但它们在 Ubuntu 22.04 上不起作用,大概是因为 cgroups v2 更新所致:

sudo cgcreate -a $USER:$USER -g memory:myGroup -t $USER:$USER
sudo cgset -r memory.max=500M myGroup
sudo cgset -r memory.swap.max=0 myGroup
cgexec -g memory:myGroup id

失败:

cgroup change of group failed

如果我运行它就会起作用sudo

sudo cgexec -g memory:myGroup id

但是然后命令以 的身份运行root,而我希望它以当前用户的身份运行。

答案1

我读过Linux 内核文档并找到以下内容(重点是我的):

cgroup.procs

所有 cgroup 上都存在的读写换行分隔值文件。...
可以
写入 PID,以将与 PID 关联的进程迁移到 cgroup。写入者应满足以下所有条件。

  • 它必须对“cgroup.procs”文件具有写权限。
  • 它必须对源和目标 cgroups 的共同祖先的“cgroup.procs”文件具有写访问权限。

...

在这个场景中,共同祖先是/。所以我让cgroup.procs根组可写:

sudo chmod o+w /sys/fs/cgroup/cgroup.procs

现在我可以cgexec以任何非 root 用户身份使用。但不知道是否存在任何安全隐患。

答案2

要解决此问题,您需要通过修改内核的启动参数将主机系统启动到 CGroupV1 模式,其中包括: systemd.unified_cgroup_hierarchy=false

sudo nano /etc/default/grub

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1 systemd.unified_cgroup_hierarchy=false"

sudo update-grub
sudo reboot

答案3

我曾经在 cgroups v1 中运行过一些资源密集型工具cgexec。我不太确定 cgroups v2 是否支持此功能;至少我无法让它工作。

在花费大量时间研究之后,我终于找到了在 Ubuntu 22.04 + cgroups v2 中顺利运行的方法。

1. 创建一个 cgroupeurope并(就我而言)调整权限

$ cd /sys/fs/cgroup/
$ sudo mkdir europe create

$ ls -ld europe
drwxr-x--- 2 root root 0 out 28 22:50 europe
$ sudo chmod a+rx europe
$ ls -ld europe
drwxr-xr-x 2 root root 0 out 28 22:50 europe

如果不改变权限,我会遇到两件事:没有 sudo 就无法在组内 cat 东西,然后systemd-cgtop --depth 1返回Failed to refresh: Permission denied

2. 将 CPU 限制为 3 核,将 RAM 限制为 16G

我有多个可用的控制器(cgroup.controllers),但只有沿子树传递的控制器是memorypids所以我添加了缺失的cpu控制器。

$ cat cgroup.controllers                       // all available
cpuset cpu io memory hugetlb pids rdma misc
$ cat cgroup.subtree_control                   // for subgroups
memory pids
$ sudo bash -c 'echo '+cpu' > cgroup.subtree_control'
$ cat cgroup.subtree_control                   // now includes CPU
cpu memory pids

$ cat europe/cgroup.controllers                // can confirm in subgrp
cpu memory pids

现在限制 CPU 和 RAM:

$ cat europe/memory.max
max
$ cat europe/cpu.max
max 100000

$ echo '16G' | sudo tee europe/memory.max
16G
$ echo '300000 100000' | sudo tee europe/cpu.max
300000 100000

$ cat europe/memory.max
17179869184
$ cat europe/cpu.max
300000 100000

3. 运行一些东西

我们可以将 PID 添加到europe/cgroup.procs然后在组中执行europe

我不是启动进程然后添加其 PID,而是添加终端窗口的 PID。然后,该 shell 中运行的所有内容都将在组中执行。

打开另一个终端:

$ cat /sys/fs/cgroup/europe/cgroup.procs

$ echo $$ | sudo tee /sys/fs/cgroup/europe/cgroup.procs
25982

$ cat europe/cgroup.procs
25982
26104
$ cat europe/cgroup.procs
25982
26105
$ cat europe/cgroup.procs
25982
26106

第一个 PID 是指代终端(echo $$在 bash 中匹配),第二个 PID 是命令,cat这就是为什么每次我运行命令时第二个 PID 都不同。

4. 不需要时删除群组

$ cat /sys/fs/cgroup/europe/cgroup.procs
$ sudo rmdir /sys/fs/cgroup/europe

如果仍有进程,europe/cgroup.procs我们会收到错误。在此示例中,关闭上一步中添加到组中的终端。

答案4

您可以像这样cgexec组合:su

sudo cgexec -g memory:myGroup -- su -c 'exec id' $USER

或者简单地使用-s

sudo cgexec -g memory:myGroup -- su -s /usr/bin/id $USER

但后者会将$SHELL变量改写为程序本身。

相关内容