RHEL/CentOS 7 service resource management with cgroups24 May 2015
The Linux control groups (cgroups) is one of my favourite tools when I need to set up how system resources are shared between running applications. With cgroups we can limit and prioritize access to CPU, memory and I/O devices (and even more).
Version 7 of RHEL and CentOS brought us the new
/sbin/init replacement - systemd, with all its err… inevitable changes. One area, where these changes can be confusing at first sight, is cgroups configuration. The old way of configuring it, by means of editing several
/etc/cg*.conf files is still available but no longer recommended.
So how to handle
cgroups on RHEL/CentOS 7? Read up.
Imagine we have a service called
foo.service that eats up a lot of CPU time. We’d like to limit its access to the CPU, so that other services executed on the same machine can be more responsive. We also have an important
bar.service, where we want to have most CPU time assigned.
Lets take a look at the configuration of our imaginary
We can see the service configuration file is
/etc/systemd/system/foo.service. Now let’s take a peek inside to see what this service really does:
Seeing how this service just runs
sha1sum, we can expect it will cause a slight load on the system. Let’s run the service and confirm this:
Indeed, since this command will eat up all the available CPU time, the other important processes and services might starve for CPU time. Let’s make sure this never happens (with cgroups).
At this point, in RHEL/CentOS 6, we’d have to set up a new cgroup and assign processes of a given service to it. With systemd it no longer necessary to create the cgroup manually. Instead, systemd introduces a new concept of
slice, which is used to manage resources of a group of processes. Most services are placed in
system.slice. Note that
systemctl status command already informed us, that
foo.service belongs to
Several other slices are present on a default system installation:
If we wanted to just know the slice name of
foo.service we could use:
So, configuring cgroups with systemd is possible either through modifying slice parameters, of service parameters. In most circumstances, where service is simple and consists of one systemd unit, it is enough to modify the properties of a given service unit.
CPUShares property modifies the value of cgroups
cpu.shares controller, which is used to limit (or rather prioritise) the CPU usage. The default “neutral” value of
cpu.shares is 1024. Setting high value increases the “priority” (i.e. causes more CPU time to be assigned to a given process).
Of course, CPUShares is not the only property we could modify. The
systemd.resource-control(5) man page has more information about cgroups-related parameters that you can pass to
Note that this change is persistent and the value of
cpu.shares will also be set to 250 upon the next
foo.service start. If we wanted this change to be temporary, we could use
--runtime parameter to
Setting the property caused additional file
90-CPUShares.conf to be created under
/etc/systemd/system/foo.service.d. This file contains parameters to be appended to the configuration of
foo.service unit. Actually applying the change requires reloading
systemd and restarting
Now let’s see if the
sha1sum process really has
cpu.shares controller value assigned properly.
Now, let’s increase the
cpu.shares controller value for our other service, the
And… let’s compare how much CPU time are processes belonging to our two services eating:
As you can see, the
md5sum process, as started by
bar.service is happily executing, taking 95% of our CPU time, while
sha1sum, as executed by
foo.service slowly eats away CPU taking only 5%.
By the way, Red Hat provides an excellent documentation on this topic: Red Hat Enterprise Linux 7 Resource Management Guide.
In the next article in this series, I will explain how to use systemd and cgroups to manage resource for processes that are not a part of a service. Stay tuned.