This article provides a Linux administrator perspective of Linux containers.
Short History
The container technology existed since 1970s in different forms, at that time it was called chroot. Chroot was used for isolating a process from other parts of the system so that a process escape won’t compromise the whole system.
Later, FreeBSD and Solaris introduced its own way of isolating processes.
The popular one introduced in 2005 on Linux space was OpenVZ, but that technology needs a patched Linux kernel. In 2006 Google developed cgroups (more details to follow), at that time it was called process containers.
In 2008, LXC or LinuX Containers came into the game and that was the complete implementation of Linux containers with the help of namespace and cgroups. The highlight was that, LXC could run on stock kernel; i.e., no custom patches were needed.
Fast-forward to 2013, the era of Docker started, and we all know that word for containers since then, just like Fridge for refrigerators. Let’s take a pause on the history for now and let’s dive into the core concepts of containers.
The Basics
Let’s start with what kind of problems the container technology solves;
Scenario 1
Problem:-
A Linux server hosts both a web server and a mail server, how can we make sure the mails sever or the web server won’t take all available CPU and Memory. So, the problem statement here is, how to restrict the CPU and Memory usage of a process?
Answer:-
Cgroups or Control Groups helps us to restrict the resource usage of a process or a group of processes. After a process starts, the process can be attached to a cgroup which is defined with specific resource limits.
Every time the process requests for memory or CPU, the cgroup will keep track of it (accounting) and take appropriate action when it hits the cgroup limits. When a process exceeds the memory limit, the OOM killer will kill the process. For CPU limit, the process will be throttled down to keep the CPU usage with in the cgroup limit.
Scenario 2
Problem:-
The web server is managed by team A and mail server is managed by team B. Both teams have dedicated users in the Linux system to do administrative tasks. But the organization doesn’t want them to see anything else other than the resources assigned to each team. For example, the processes running in the system can be visible to everyone if they execute “ps aux” command. How to restrict a user from listing processes other than the one owned by them?
Answer:-
Namespaces, that can isolate resources from other processes. When a process starts, that process gets attached to a namespace and resources present in that namespaces will be visible to the process starting in that namespace.
Scenario 3
Problem:-
The team that manages the web server needs access to the network related commands to do day to day monitoring/troubleshooting. But only root user can do that operation, but you don’t want to give root permission to the web server team. How can we give additional privileged permissions to a program without giving root access (SUID)?
Answer:-
Capabilities, is a way to assign additional permission to binaries.
The permissions start with prefix cap_
.
The cap_net_raw
permission allows a process to access OS sockets
.
No need to worry about capabilities for now. We will discuss that in details in a different article.
Scenario 4
Problem:- The web server team requires a specific ruby version and the mail server requires a different one for their own operations. The package manager can handle only one version for the whole system. This is the classic, “Matrix From Hell” dependency problem.
How can we solve the package dependencies of a software without affecting other processes running in the system?
Answer:-
Package the application and dependencies together and run the process from a virtual root file system (chroot). We will see how can we solve this dependency problem manually and then using docker later.
Scenario 5
Problem:-
The web server team wants to run multiple instances of web server to do vertical load balancing. How can we attach and detach individual web servers from a virtual load balancer running in the same Linux system?
Answer:-
We assume that the virtual load balancer need downstream IPs to redirect network traffic.
In our case, the process can run on it’s on namespace, but how we can isolate the networking.
Here comes the virtual Ethernet devices called, veth
.
We can create a veth pair and attach one virtual device to the namespace where the web server is running and the other end to the system.
We will discuss more about the virtual networking in a different article.
Conclusion
The problems and the answers we have seen for were resolved using the software called “container runtimes”. Few famous container runtimes are, Docker, LXC and ContainerD.
Using the runtimes, the normal users don’t have to manually set up container environments, instead the runtime will help the user to create the underlying settings to run a containerized application.
In the next session, we will install docker, create and run our first containerized application.
About the Author
Ansil Hameed Kunju
Ansil has more than a decade of experience in different IT domains. He is an expert in DevOps.His skill set includes Linux, GCP, AWS, VMware, Nutanix, Rancher, Docker, Git, Python, Golang, Kubernetes, Istio, Prometheus, Grafana, ArgoCD, Jenkins, StackStorm and other CNCF projects.