Lab: Docker Namespaces and Control Groups (Cgroups)
Image Credit: https://medium.com/@mrdevsecops/namespace-vs-cgroup-60c832c6b8c8
What Are Namespaces?
- Definition: Namespaces are a feature in the Linux kernel that isolate various aspects of system resources. They ensure that processes in one namespace are independent and invisible to processes in another.
- Purpose: To provide isolation, creating a self-contained environment for processes, which is a core part of containerization.
Real-World Example:
Imagine a hotel with multiple rooms. Each room is isolated with its own keys, furniture, and guests. Guests in one room cannot directly interact with another room. Similarly, namespaces isolate processes within their "container rooms."
Types of Namespaces:
-
PID Namespace (Process IDs):
- Isolates process IDs.
- Each container has its own process numbering, starting from PID 1.
- Example: A container's process may appear as PID 1 inside the container but could be PID 1000 on the host.
-
Network Namespace:
- Provides isolated networking for containers.
- Each container can have its own virtual network interface, IP address, and routing.
- Example: A container might have a private IP (e.g., 192.168.1.10) while the host uses 10.0.0.1.
-
Mount Namespace:
- Controls file system access and isolation.
- Containers can have specific mount points without seeing or affecting the host's mounts.
- Example: A container may only access
/app
without visibility into/home
on the host.
-
User Namespace:
- Separates user IDs and group IDs between host and container.
- A user can appear as
root
(UID 0) inside a container but remain a regular user on the host. - Example: Running a containerized app as
root
inside the container without elevated privileges on the host.
What Are Control Groups (Cgroups)?
Image Credit: https://medium.com/@mrdevsecops/namespace-vs-cgroup-60c832c6b8c8
- Definition: Cgroups are another Linux kernel feature that manages resource allocation and limits for processes.
- Purpose: To prevent one container from monopolizing system resources (like CPU, memory, or disk I/O).
Real-World Example:
Think of a shared gym in an apartment complex. Each apartment (container) gets a fixed time slot (CPU) and limited equipment usage (memory). This prevents one tenant from hogging all the resources.
Key Cgroup Features:
-
Memory Limiting:
- Sets a maximum memory a container can use.
- Example: A container limited to 512MB of RAM cannot use more, even if the host has more memory.
-
CPU Throttling:
- Restricts CPU usage for a container.
- Example: A container assigned 50% of CPU will use only half of a core.
-
Process Limits:
- Controls the number of processes a container can run.
- Example: A container allowed to spawn only 10 processes cannot create the 11th process.
Why Are Namespaces and Cgroups Important?
- Isolation: Namespaces ensure processes and resources are kept separate, mimicking virtual environments.
- Resource Control: Cgroups ensure fair allocation of system resources, avoiding scenarios where one container affects others.
Hands on Lab
Explore Namespaces
-
Open a terminal and list namespaces for the current process:
ls -l /proc/self/ns
-
Observe the types of namespaces available.
-
Start a basic container:
docker run --rm -it alpine sh
-
Inside the container, check process IDs:
ps -ef
-
Get and list the namespaces of a container's main process:
-
Now, execute the following script to inspect the namespaces of running containers:
docker ps -q | while read container_id; do pid=$(docker inspect -f '{{.State.Pid}}' "$container_id") if [ -d "/proc/$pid/ns" ]; then ls -l "/proc/$pid/ns" else echo "Namespace for PID $pid not found" fi done
-
Observe how the namespace IDs differ between the host and the container, ensuring isolation.
Share Namespaces Between Host and Container
- Run a container sharing the host's process namespace:
docker run --rm -it --pid=host alpine sh
- Inside the container, list processes:
ps aux
- Notice how the processes from the host are visible inside the container.
Explore Cgroups
-
Run a container with a process limit.
docker run --rm --pids-limit 2 alpine sh -c "while true; do sleep 1 & done"
Observe how the container prevents you from creating more processes.
-
Run a container with memory and CPU limits:
docker run --rm --memory=256m --cpus="0.5" alpine sh -c "yes > /dev/null"
-
Open another terminal and monitor the resource usage:
docker stats
Observe how resource usage is constrained within the defined limits.
Summary
- Namespaces provide isolation, allowing each container to operate as if it has its own environment.
- Cgroups manage resources, ensuring containers don't exhaust system resources.
- These features are essential to Docker's lightweight virtualization.
Additional Reference:
- https://medium.com/@mrdevsecops/namespace-vs-cgroup-60c832c6b8c8