Fight for resources, part 3: Memory is not enough

    Continuing to learn Control Groups (Cgroups) in Red Hat Enterprise Linux 7. Let's do the memory. You remember that there are two adjustments for allocating CPU time: CPUShares for adjusting relative shares and CPUQuota for limiting a user, service or virtual machine (VM) in absolute values ​​(percent) of processor time. Moreover, both of these adjustments can be used simultaneously. For example, if a user has a CPU quota of 50%, then his CPU ball will also be taken into account until he completely chooses his quota of 50% of CPU time.

    As for the RAM, systemd offers only one way to adjust, namely ...

    The amount of memory that can be allocated to a user or service. Suppose we want to limit the user mrichter to 200 MB of RAM. If you remember, its UID is 1000, so we enter the following command:

    systemctl set-property user-1000.slice MemoryLimit = 200M

    Now mrichter wants to check his boundaries and starts stress testing utility stress, which begins to consume memory intensively. And stress very quickly gives an error:

    The system log shows that the stress was simply interrupted by the OOM (Out Of Memory) Killer.

    Here it is important to pay attention to this: by default, the limit on RAM only applies to resident memory. That is, if the process can go to the paging file ("swap"), then it will bypass the established limit. In our example, stress took off because it exceeded the limit on resident memory.

    And if we do not want the program to merge into a swap?

    This is, in general, easy to ban. Well, or relatively easy ... In general, you have to climb somewhere.

    There are some cgroup settings that cannot be reached via the systemctl command or through unit files. However, these settings can be changed on the fly through the files in the / sys / fs / cgroup / folder. Here is how, for example, the cgroup of the user mrichter looks in part of the memory:

    The file responsible for how much memory can go into a swap is quite obviously called memory.swappiness. Let's see what's inside:

    If you happen to play with the kernel settings and the swap subsystem, then you will immediately see here the default value of the swappiness parameter. If you change it to zero, the RAM controller for the user mrichter will generally forbid him to use a swap.

    By the way, here you can see the memory statistics for the user mrichter:

    The value of the hierarchical_memory_limit parameter is the same MemoryLimit that we set with the systemctl command. The hierarchical_memsw_limit parameter is the total limit (resident memory and memory in a handout file). We have banned mrichter from using the paging file, so the value of this parameter is so weird.

    Now about the problems of the approach just described:

    • You can make changes to these files only when the user mrichter has logged into the system. Until he enters, his cgroup will be inactive.
    • These settings are not saved after a reboot. Moreover, they will be lost if mrichter relogs.

    The pam_exec script will help with these problems (see for more details ).

    Here is the script we will create in the / usr / local / bin folder:

    And then add his call to the last line of /etc/pam.d/sshd. As a result, this script will run every time a user logs in via ssh. That is why we check in the script that it is the user mrichter, before changing the settings.

    So, we cut off the user mrichter from the paging file.

    Of course, you can go even further and change the configuration files of the active cgroup on the fly, but for the time being we will postpone this risky business. However, the general method of how to change user settings, you caught.

    And with services is still easier. In the service unit file, you can use the ExecStartPost = directive to run a script that changes settings. For example, here’s how to change the foo service unit file to turn off swapping:

    Run foo - and no swapping:

    Well, for today, perhaps, this shamanism is enough from us.

    But before we finish, let's look at the documentation on cgroup, where you can find information about all these hidden settings of the regulators. You can install the kernel-doc package on your computer, as I did by downloading it from the rhel-7-server-rpms repository.

    After installation, open the / usr / share / docs folder corresponding to your kernel, and go to the cgroups folder, which contains the latest information on all regulators.

    Next time we'll talk about input and output. And, by the way, we’ve almost come to finding out how cgroups led to the emergence of containers (in fact, cgroups are a key component of containers in the Red Hat Enterprise Linux and Red Hat OpenShift Container Platform).

    Also popular now: