|
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.