I find it quite amusing to explore the basic principles of some complex stuff. Here’s something I stumbled upon: Namespaces and Control Groups in Linux. Both are two powerful features of Linux kernel, that together form the foundation of containerization. To think of ubiquitous Docker originating from such mechanisms!
Namespaces
First things first, Kernel maintains data structures for various system resources, such as process tables, network interfaces, mount points, etc. These resources can be organized, grouped together by using Namespaces.
When a new namespace is created, a fresh instance, of the associated resource’s data structure is also set up. Also, whenever a process is created, it gets assigned to a namespace or to more than one.
By placing a process inside specific namespaces, the system can control and isolate the resources this process sees. For instance, a process in its own network namespace will have its own network interfaces, routing tables, and firewall rules.
This isolation forms the foundation of containerization. When you run a container, you’re essentially running a process (or group of processes) in a set of isolated namespaces, making it appear as though they’re running on their own independent system.
Namespaces by themselves are simply kernel-level data structures. They were presented first on Linux Kernel, on 2002. They are of different types, corresponding to the resource type, e.g. Mount namespaces, Network namespaces, User namespaces etc. A Linux system starts out with a single namespace of each type, used by all processes. Processes then can create additional namespaces and also join different namespaces.
List which namespaces a process belongs to:
ls -l /proc/[PID]/ns/
Each process has a directory under /proc that represents its state in the system. Within this directory, the ns/ subdirectory contains one entry for each namespace the process is a member of.
Control Groups (cgroups)
While namespaces focus on isolation, cgroups, another key mechanism, are about limiting and monitoring resource usage. They ensure that processes within a particular cgroup cannot consume more resources than allocated to that cgroup, e.g., memory, CPU time, or I/O bandwidth.
The simplest flow:
Create a new cgroup, with the purpose of controlling CPU resources.
mkdir /cgroup/cpu/testgroup
Now we can set the resource limits. E.g. we can restrict the CPU usage to 50%: (By default, every process will get 1024 shares of CPU.)
echo 512 > /cgroup/cpu/testgroup/cpu.shares
Let’s add a process to this group. Replace PID with your process id.
echo [PID] > /cgroup/cpu/testgroup/tasks
To see which processes fall under a cgroup:
cat /cgroup/cpu/testgroup/tasks