Getting started with Cgroups

Managing a single process resources running on top of an operating system is not a trivial task. While solutions like Docker or Virtual Machines could completely isolate your process, I was recently looking for a simpler and more straightforward solution at operating system level.

Then I discovered cgroups which is a kernel tool to limit resource usage per user-defined groups. The resources I was mostly interested in are CPU and RAM, but there is also an option to limit the IO usage of a process. To run a new process with limited resources you basically have to remember two things:

  1. Define the cgroup resource limits
  2. Run your process within the croup like:
sudo cgexec -g cpu:root -g memory:root COMMAND

In my ubuntu server I used the stress tool to generate some load in the machine so I could actually check if the resource limits being applied.

Here are the steps I followed for the cgroups installation:

Install cgoup-bin

sudo apt-get install cgroup-bin

Create a custom group for your process

mount {
       cpu = /cgroup/cpu;
       cpuacct = /cgroup/cpu;
       memory = /cgroup/memory;
}

group dataparser {
        # Set the cpu and memory limits for this group
        cpu {
                cpu.shares = 500;
        }
        memory {
                memory.limit_in_bytes = 40G;
        }
}

Setting cgroup limits

sudo mkdir /cgroup/cpu/dataparser
sudo mkdir /cgroup/memory/dataparser
#Limit CPU usage to 50%
echo 500 > /cgroup/cpu/dataparser/cpu.shares
# Limit RAM to 40G
echo 40000000000 > /cgroup/memory/dataparser/memory.limit_in_bytes

Mount the cgroups

sudo mount -t cgroup -o cpu,cpuacct cpu /cgroup/cpu/
sudo mount -t cgroup -o memory memory /cgroup/memory/

Create the cgroup with the resource limits

sudo cgcreate -a dataparser:dataparser -t dataparser:dataparser -g cpu:dataparser

Test limits using stress tool

At that point the CPU and RAM usage of you process should never exceed the limits you defined! I found stress tool really useful in this part.

sudo cgexec -g cpu:dataparser -g memory:dataparser stress --cpu 20 --vm 50 --vm-bytes 10G

Extra commands

list mounted cgroups

lscgroup

deleted all cgroups (use with caution)

sudo cgclear

load configuration file

sudo cgconfigparser -l /etc/cgconfig.conf

Of course you could define which users can run processes within each cgroup and also which users can modify resource limits. These options are mostly useful in a multiuser environment with multiple croups defining different resource limits. You can find more information here. I also have to mention here that Docker is using the same trick with croups inside containers to manage the recourses.

Got more questions or comments? Drop me a private message.