libcgroup
|
SPDX-License-Identifier: LGPL-2.1-only
Copyright (c) 2023 Oracle and/or its affiliates.
_Author: Tom Hromatka <tom.h.nosp@m.roma.nosp@m.tka@o.nosp@m.racl.nosp@m.e.com>_
The goal of this document is to outline the steps required to create a systemd scope and a child cgroup hierarchy using the libcgroup command line tools.
The following steps are encapsulated in a C example using the libcgroup C APIs.
The following steps are encapsulated in a libcgroup automated test.
high-priority
cgroup should be guaranteed at least 1GB of RAMlow-priority
cgroup should be hard-limited to 2GB of RAMmedium-prioirty
cgroup should have a soft memory limit of 3 GBhigh-priority
cgroup should be able to consume 60% of CPU cyclesmedium-priority
cgroup should be able to consume 30% of CPU cycleslow-priority
cgroup should be able to consume 10% of CPU cyclesCreate a delegated scope cgroup
This will create a transient, delegated scope. The -c
flag instructs libcgroup to create a systemd scope; libcgroup then instructs systemd that this hierarchy is delegated, i.e. it is to be managed by another process and not by systemd. The -S
flag notifies libcgroup that we want mycompany.scope/database.slice
to be the default base path in libcgroup; this will significantly help in reducing typing in follow-on commands. The -g
flag tells libcgroup to create a cgroup named mycompany.slice/database.scope
and enable the cpu and memory controllers within it.
Systemd should automatically remove scopes with no active processes running within them. So, the first step would be to kill any processes in the scope, wait to see if systemd removes the scope, and then try the cgcreate
operation again.
Remove all processes in the scope $ for PID in $(cgget -nvb -r cgroup.procs mycompany.slice/database.scope); do sudo kill -9 $PID;done
The above command could be simplified as for PID in $(cgget -nv -r cgroup.procs /); do sudo kill -9 $PID;done
, but introduces some risk. If there is a typo or the default scope path isn't set, then unconditionally killing processes in /
could be catastrophic.
Sometimes systemd's internal list of scopes gets out of sync with the filesystem. You can purge the database.scope
from its list by running the following commands
database.scope
from systemd's internal list sudo systemctl kill database.scope sudo systemctl stop database.scope
Create the child cgroups
But... but... I did everything right. Why can't I create the high-priority
child cgroup? This operation failed due to the no-processes-in-inner-nodes rule. Since a process, libcgroup_systemd_idle_thread
, resides in database.scope
, we are subject to the no-process-in-inner-nodes rule. The kernel will let us create a child cgroup, but it will fail when we try to enable controllers in database.scope
's cgroup.subtree_control
file. There are a few different ways to solve this failure; the easiest is probably to create a temporary cgroup under database.scope
and move the libcgroup_systemd_idle_thread
to this temporary cgroup. This allows database.scope
to operate as a legal inner node, and we can then create the entire hierarchy.
Temporarily disable the cpu and memory controllers at the scope level
Since we informed libcgroup that mycompany.slice/database.scope
is the default path, we can use /
. Otherwise, we would have had to specify the entire path. This pattern continues throughout this example.
sudo cgcreate -g :tmp sudo cgclassify -g :tmp $(cgget -nv -r cgroup.procs /)
sudo cgset -r cgroup.subtree_control="+cpu +memory" /
Now we can finally get back to creating our child cgroups
high-priority
cgroup should be guaranteed at least 1GB of RAM low-priority
cgroup should be hard-limited to 2GB of RAM sudo cgset -r memory.max=2G low-priority
medium-prioirty
cgroup should have a soft memory limit of 3 GB sudo cgset -r memory.high=3G medium-priority
The high-priority
cgroup should be able to consume 60% of CPU cycles sudo cgset -r cpu.weight=600 high-priority
Note that I've (somewhat arbitrarily) chosen a total cpu.weight
within database.scope
to be 1000. Thus, to meet the 60% requirement, we need to allocate 600 shares to the high-priority
cgroup.
medium-priority
cgroup should be able to consume 30% of CPU cycles sudo cgset -r cpu.weight=300 medium-priority
low-priority
cgroup should be able to consume 10% of CPU cycles sudo cgset -r cpu.weight=100 low-priority
cgclassify
to move the process(es) to the appropriate cgroupscgexec
to place the application in the desired cgroupcgrulesengd
to automatically move processes to the correct cgroupslibcgroup_systemd_idle_thread
tmp
cgroup sudo cgdelete -g :tmp
This document outlines the steps for creating a delegated systemd scope and configuring its child cgroups on a cgroup v2 system. Systemd and libcgroup provide powerful tools to simplify these steps.