Linux Containers with LXC: Some Best Practices

I am going to show you the best ways of using LXC to create Linux containers. You’ll thank me.

Hypervisor Virtualization and where Container Virtualization fits:

Container virtualization (also known as Operating System Virtualization) is an important player among the many types of virtualization technology currently available. If we look at traditional hypervisor virtualization in Linux, we’ll see an entire Operating System running as a guest OS on top of a host OS using some kind of hypervisor like Xen. This approach places a considerable load on backend hypervisor to isolate the Guest OS completely by emulating the underlying hardware.

Paravirtualization was a development that requires a guest OS to be modified in order to gain more direct communication with the host system hardware. This provides an edge in terms of performance over full virtualization. However, modification in guest OS presents a substantial limitation because not all of the Operating Systems we may want to run as guests will be available as Open Source.
Linux Container
Container virtualization, as we discuss, is much lighter and more efficient than traditional hypervisors. In this form of virtualization, virtual machines are carved out of host Operating Systems sharing the same OS kernel. These carved VM’s are referred to as Containers.

Containers basically provide encapsulation for a set of processes to run in isolation from the rest of the system. The applications running inside containers act as if they are running on a separate environment or OS with its exclusive set of resources. A good example of container’s usefulness is having two websites running in two different containers requiring two different versions of PHP installed and running. Containers ensure that the two different PHP versions co-exist on the system without conflict.
Linux Container
Since Containers do not involve the intensive overhead of guest Operating Systems and support hypervisor, more applications can run on a host OS compared to any other virtualization approach. Moreover, booting and restarting container applications is much faster than doing the same with VMs. This approach almost guarantees less downtime.

Containers, an isolated view:

Containers provide an isolated view of the system resources to the applications. In order to provide this contained view to the applications, Containers use some of the kernel features called namespaces, cgroups and chroot to carve off a contained area. An end result is a virtual machine without the hypervisor. Containers are a smart method of attaining isolation and resource control.

We’ll briefly look into these kernel features and then move to lxc which combines these features and provides an effective tool to create and manage Containers.

Namespaces:

Namespaces allow you to isolate an application view of the Operating System in various ways. Namespaces, in other words, provide processes with a virtual view of their operating environments. Or you can say that they provide a process with their own view of an operating system. This offers you your own little view of an OS, like user ID networking and process tree.

Cgroup: To shape how the resources are consumed in the container, you can isolate and shape things like CPU usage memory usage disk IO, network IO, and other methods.

Creating and Managing Containers Using Lxc:

Lxc an acronym for Linux containers is a lightweight virtualization technology that implements the containment concept in Linux. It interfaces with kernel namespaces, cgroups, and other features to create and manage containers. As it uses kernel features to realize containment, we receive near-native performance with Lxc compared with other virtualization technologies that simply emulate the hardware.

Let’s go through a basic set of commands in Lxc which is useful for creating, starting, and destroying containers. This will help you gain a better understanding of container environments.

We have Lxc installed on our Ubuntu system kernel version: The below set of commands were tried on Ubuntu and there may be slight deviation if you try them on other Linux flavors.

Once Lxc package is installed in the system we can get a list of Lxc commands.

Linux Container
These commands can be used for creating, starting, stopping, connecting, destroying containers in addition to various other utilities. Now, as Lxc is installed and we have Lxc commands at our disposal, let’s verify the environment making sure everything is fine using lxc-checkconfig.

This command checks the current kernel for Lxc support.

Linux Container
In the output to the command, we see separate section for namespaces, which are used for isolation, while cgroups are used for resource allocation. If everything looks fine, create Linux containers.

Lxc is nice enough to provide templates which can be used for creating root file system for containers. These templates are allotted on a per distribution basis. All the available Lxc templates can be found at
/usr/share/lxc/templates

Linux Container
Let’s create a container named “dummyContainer” using one of these templates.

sudo lxc-create –n <container name> -t <template-name>.
sudo lxc-create –n dummyContainer -t busybox.

Linux Container
Now we have a dummyContainer ready. Since containers are completely isolated it should have an Operating System, supporting libraries, and the application code. Once the container is created we can check the containers root file system stored under /var/lib/lxc.

Here we have a folder titled with the Linux container’s name. Inside that, we have 2 items.

Linux Container
One is the configuration file for this Linux container. The other is the directory holding the containers root file system. The configuration file contains the default settings for how the container will function. We can modify this config file as per our needs. For now, we’ll leave the default setting. Once everything is configured and the root file system for the container is created we can start our dummyContainer.

sudo lxc-start –d  –n <container name>. (-d is for running in background)
sudo lxc-start –d  –n dummyContainer

Let’s list the running process to see if the newly created container is there. ps –xaf  will list all the set of process running.
Linux Container
As we can see the container process is running in the host OS. And since there is isolation via namespaces container has its own little view of the world. We have a view of the containers isolated view.

lxc-info –n <container-name>
lxc-info –n dummyContainer

Linux Container
We immediately see dummyContainer running, its process ID, and its resource consumption list. Let’s login into the container and see the isolated view.

sudo lxc-console –n <container-name>
sudo lxc-console –n dummyContainer.

Username and password is the same as was prompted when we created the container, which is root/root (Please check the snapshot attached with lxc-create).

Once we login into the container, let’s check the process list by running ps –aux. We’ll see a limited set of process running.  The host OS process is not seen from the container while the host OS will show all the process running in containers as they are actually running on host OS with isolated namespaces.

Linux Container
The host OS can manipulate the containers live because this is simply a process to the host OS.

With this, we have a fairly good understanding of what lxc is, and why containers are fast compared to traditional virtualization.
Finally, we’ll stop the container with:

sudo lxc-stop –n <container-name>
sudo lxc-stop –n dummyContainer.

You learned ways of creating our own containers and managing them using lxc. Of course, there are more enhanced services available, like Docker, that create and manage containers but my intention was to illustrate the internals and concepts behind containers provisioning. I hope this blog was helpful in understanding the basics of containers provisioning. Feel free to comment about this post below. Never stop learning. We don’t.

Cloud Academy