cgroup V1 设置在 cgroup V2 中不起作用

cgroup V1 设置在 cgroup V2 中不起作用

我有一个 cgroup 设置,主要用于限制 rsync 和 Firefox 的内存使用。这是一个手动设置(不涉及 systemd),每次启动后我都会从 Makefile 运行它(是的,我知道这不是很好,但是 systemd 学习起来很麻烦)。

今天,当我从 ubuntu 21.04 升级到 22.04 时,意外后果定律确保我的 cgroup 设置不再起作用,可能是因为 cgroup V2 现在是标准。

在我看来,/sys/fs/cgroups 中的文件层次结构已经发生了变化。例如,我以前有用户 reik

/sys/fs/cgroup/内存/自定义/reik-2048M

我使用 Makefile 代码片段创建了该脚本,并生成了以下脚本

MEM=2048M
sudo cgcreate -a reik -t reik -g memory:/custom/reik-$(MEM)
sudo cgset -r memory.limit_in_bytes=$(MEM) custom/reik-$(MEM)
sudo cgset -r memory.memsw.limit_in_bytes=$(MEM) custom/reik-$(MEM)

然后我可以运行如下程序

%gexec --sticky -g 内存:custom/reik-2048M 某个程序

使用 cgroup v2 时,memory.blah 变量名称已经改变,我认为我已经修复了这个问题,如下所示

sudo cgcreate -a reik -t reik -g memory:/custom/reik-2048M
sudo cgset -r memory.max=2048M custom/reik-2048M
sudo cgset -r memory.swap.max=2048M custom/reik-2048M

但是现在,如果我尝试运行任何程序(比如 ls),就会出现错误,如下所示

% cgexec --sticky -g memory:custom/reik-2048M ls
cgroup change of group failed

有一点似乎不同,那就是文件层次结构中不再包含 /memory/ 组件,也就是说,创建的路径只是

/sys/fs/cgroup/custom/reik-2048M

我只能做到这些了。我正在寻找我在这里做错的事情的想法。我还查找了有关如何将 cgroup v1 命令转换为 cgroup v2 的文档,但没有找到任何非常具体的内容。

答案1

总结:

systemd-run --user -G -P -d -p MemoryMax=2G -p MemorySwapMax=2G ls

这将使用指定的设置和命令动态创建一个 .service。(对于 .service 单元,相同的设置将进入 [Service] 部分。)这会--user使其在您自己的服务管理器下运行,而不是在系统范围的服务管理器下运行。

可以通过systemd-run (或在真实的 .service 单元中) 创建~/.config/systemd/user/foo.slice和使用预定义的 cgroup :--sliceSlice=

[Slice]
MemoryMax=2G
MemorySwapMax=2G

# systemd-run --user --collect --slice=foo.slice --pty --shell

(关于 systemd 的切片命名的注意事项:破折号是层次分隔符,即foo-bar.slice是 的子项foo.slice。)

在我看来,/sys/fs/cgroups 中的文件层次结构已经发生了变化。[…] 有一点似乎不同,那就是文件层次结构中不再包含 /memory/ 组件,也就是说,创建的路径只是

是的,这在很大程度上解释了为什么它是 cgroups“v2”。新的 cgroups 系统不再有单独的每个控制器树 - 所有内容都只有一个树,子树通过其cgroup.controller文件启用特定的控制器(cgcreate 自动执行此操作)。

但是,在我的测试中,CGROUP_LOGLEVEL=debug错误消息表明内核不允许将 PID 移入新的 cgroup。我不确定原因,但最有可能的原因是,您没有遵守 cgroup.c 中的“应被授权迁移到共同祖先”规则 - 在这种情况下,唯一的共同祖先是根/cgroup,而您没有权限。

(systemd-run 并不直接执行进程,而是要求进程systemd --user执行它,因此源 cgroup 和目标 cgroup 都属于共同的祖先,[...]/[email protected]归您的 UID 所拥有,因此通过了迁移检查。)


这导致了另一个值得一提的区别——在 v2 模型中,cgroup 可以有任务或者但不能同时存在两个子组,所以你不能实际上将任何进程移入祖先 cgroup;上一段使用“授权迁移”严格是指对共同祖先具有写权限cgroup.procs

相关内容