Understanding Control Groups (cgroups)

Control Groups, more commonly called cgroups, were introduced back in 2010 in Red Hat Enterprise Linux 6. Originally, they were just an add-on feature, and a user had to jump through some hoops to manually create them. Nowadays, with the advent of the systemd init system, cgroups are an integral part of the operating system, and each process runs in its own cgroup by default.

With cgroups, processes run in their own kernel space and memory space. Should the need arise, an administrator can easily configure a cgroup to limit the resources that the process can use. This is not only good for security, but also for tuning system performance.

So, what is a cgroup? Well, it's really just a collection of processes that are grouped together for a particular purpose. Here's what you can do with cgroups:

  • Set resource limits: For each cgroup, you can set resource limits for CPU usage, I/O usage, and memory usage.
  • Perform different accounting functions: You can measure resource usage for each cgroup, which makes it easy to bill specific customers for the resources that they use.
  • Prioritize resources: You can set limits on a user who's hogging resources like crazy.
  • Freezing, checkpointing, and restarting: These functions are handy for troubleshooting. They allow you to stop a process, take a snapshot of the system state, and restore a system state from a backup.

There's not enough space to look at all of these functions, but that's okay. Right now, our primary interest is setting resource limits. With only some minor exceptions, things work the same on CentOS 7, CentOS 8, and Ubuntu 18.04. For now, we'll work with CentOS 8.

By default, each cgroup on the system has no defined resource limits. The first step in defining them is to enable accounting for CPU usage, memory usage, and I/O usage. We could do that by hand-editing the systemd service file for each service that we want to limit, but it's easier to just run a systemctl command, like so:

sudo systemctl set-property httpd.service MemoryAccounting=1 CPUAccounting=1 BlockIOAccounting=1

We've just turned on the accounting functions for the Apache web server on a CentOS 8 machine. (The command would be the same on an Ubuntu machine, except that we would have apache2.service instead of httpd.service.) Now, when we look in the /etc/systemd/system.control directory, we'll see that we've created an httpd.service.d directory. Within that directory are the files that turn on our accounting functions:

[donnie@localhost httpd.service.d]$ pwd
/etc/systemd/system.control/httpd.service.d
[donnie@localhost httpd.service.d]$ ls -l
total 12
-rw-r--r--. 1 root root 153 Oct 30 15:07 50-BlockIOAccounting.conf
-rw-r--r--. 1 root root 149 Oct 30 15:07 50-CPUAccounting.conf
-rw-r--r--. 1 root root 152 Oct 30 15:07 50-MemoryAccounting.conf
[donnie@localhost httpd.service.d]$

Inside each file, we can see two lines that modify the original httpd.service file in order to turn on accounting. For example, here's the one for CPUAccounting:

[donnie@localhost httpd.service.d]$ cat 50-CPUAccounting.conf 
# This is a drop-in unit file extension, created via "systemctl set-property"
# or an equivalent operation. Do not edit.
[Service]
CPUAccounting=yes
[donnie@localhost httpd.service.d]$

Now that we've enabled accounting for the Apache service, we can place some resource limits on it. (By default, there are no limits.) Let's say that we want to limit Apache to only 40% of CPU usage and 500 MB of memory usage. We'll set both limits with the following command:

[donnie@localhost ~]$ sudo systemctl set-property httpd.service CPUQuota=40% MemoryLimit=500M
[donnie@localhost ~]$

This command created two more files in the /etc/systemd/system.control/httpd.service.d/ directory:

[donnie@localhost httpd.service.d]$ ls -l
total 20
-rw-r--r--. 1 root root 153 Oct 30 15:07 50-BlockIOAccounting.conf
-rw-r--r--. 1 root root 149 Oct 30 15:07 50-CPUAccounting.conf
-rw-r--r--. 1 root root 144 Oct 30 15:18 50-CPUQuota.conf
-rw-r--r--. 1 root root 152 Oct 30 15:07 50-MemoryAccounting.conf
-rw-r--r--. 1 root root 153 Oct 30 15:18 50-MemoryLimit.conf
[donnie@localhost httpd.service.d]$

Let's cat one of them, just to see the format of the files:

[donnie@localhost httpd.service.d]$ cat 50-CPUQuota.conf 
# This is a drop-in unit file extension, created via "systemctl set-property"
# or an equivalent operation. Do not edit.
[Service]
CPUQuota=40%
[donnie@localhost httpd.service.d]$

We can allocate resources to other services in the same manner. For example, if this were a Linux-Apache-MySQL/MariaDB-PHP (LAMP) server, we could allocate a portion of the remaining CPU and memory resources to the PHP service, and the rest to the MySQL/MariaDB service.

LAMP is the bedrock for many popular Content Management Systems, such as WordPress and Joomla.

We can also place resource limits on user accounts. For example, let's limit Katelyn to 20% of CPU usage and 500 MB of memory usage. First, we need to get Katelyn's User ID number. We'll do that with the id command:

[donnie@localhost ~]$ id katelyn
uid=1001(katelyn) gid=1001(katelyn) groups=1001(katelyn)
[donnie@localhost ~]$

So, her UID is 1001. Let's enable accounting for her and set her limits:

[donnie@localhost ~]$ sudo systemctl set-property user-1001.slice MemoryAccounting=1 CPUAccounting=1 BlockIOAccounting=1

[donnie@localhost ~]$ sudo systemctl set-property user-1001.slice CPUQuota=20% MemoryLimit=500M

[donnie@localhost ~]

If we look in the /etc/systemd/system.control/user-1001.slice.d directory, we'll see the same set of files that were created for the httpd service.

I've already mentioned the difference between doing this on CentOS and Ubuntu; that is, certain services have different names on each distro. In this case, the service is httpd.service on CentOS and apache2.service on Ubuntu. Other than that, things work the same for both Ubuntu 18.04 and CentOS 8.

On CentOS 7, there's no system.control directory within the /etc/systemd directory. Instead, the httpd.service.d directory is created within the /etc/systemd/system directory. When I tried to set limits for Katelyn for the first again, again with UID 1001, CentOS 7 wouldn't allow me to do it until Katelyn logged in to activate her slice. Her files were created in the /run/systemd/system/user-1001.slice.d directory, which only contains ephemeral runtime files. So, unlike with CentOS 8, the files aren't persistent across reboots. This means that if you need to set user resource limits on CentOS 7, you need to be aware that they'll disappear once you reboot the machine.

There's a lot more to cgroups than what I have space to present here. But that's okay. In this section, we've looked at two ways cgroups can enhance security:

  • They provide process isolation.
  • Using them to limit resource usage can help prevent DoS attacks.

Next up, we'll take a brief look at the concepts of namespaces and namespace isolation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.213.238