I have a systemd service that occasionally needs to run an external tool in a sub-process.
Because the tool is sometimes memory intensive, the service runs the tool in a dedicated cgroup using a cgexec shell command:
cgexec --sticky -g memory:<cgroup> <command>
Previously, this service was running on Ubuntu 20.04 which uses cgroups v1. I’m now migrating this service to Ubuntu 24.04 which uses cgroups v2.
The above method no longer seems to work. Here is the error message I commonly get:
cgroup change of group failed
I’ll get into possible solutions from previous answers next, but may main question is this: Is there a canonical way for a systemd service to spawn a sub-process that uses an alternate cgroup using cgroups v2?
From what I understand from previous discussions, my problem may stem from the permissions for the cgroup.procs
file in the common ancestor of the cgroup for the service and the cgroup targeted by the cgexec’s -g
option. In my case, I believe this would be the cgroup.procs
for the root cgroup.
The top answer from discussion #1: Using cgroups v2 without root suggests using cgcreate
to create a group under the correct slice. In their example, they’re using a user.slice. In mine it would be something like this:
cgcreate -a service-user:service-user -t service-user:service-user -g memory:system.slice/foo.service/tool
This doesn’t seem to work because the cgroups created under system.slice seem to be ephemeral, being removed when the service stops.
The top answer from discussion #2 suggests making the root cgroup.procs
other-writable (e.g., sudo chmod o+w /sys/fs/cgroup/cgroup.procs
). This does actually seem to work, but there was an open question about security.