Creating a method for cloning LXC containers

A little background

At the end of last year, when it was time to start writing a diploma, I came across an article from user am83 . Since I am extremely partial to virtualization, I wanted to come up with something related to this topic. And then I had an idea about using a common file system to create a method that would save disk space when cloning LXC containers.

So, based on an article written by am83, I took several steps to create a common file system.
Creating a file system framework for containers

We install the basic components that will be needed to create a common file system using the command:
$ apt-get install debootstrap lxc lxc-templates lxctl cgroup-lite rsync

Next, enable two control options.
In the network configuration, enable the network bridge for containers:
$ nano /etc/init/lxc-net.conf

And for autorun containers at system startup, enable:

In the lxc.conf file, with the command:
$ nano /etc/init/lxc.conf

Next, edit the configuration file:
$ nano /etc/default/lxc

And add the following lines to it:
We introduce a variable:
$ lxcRoot="/lxc"

Create the / lxc directory:
$ mkdir -p ${lxcRoot}

We create a place where containers and information on their settings are stored, as well as a place to cache distribution data to speed up the creation of many containers:
$ mkdir /${lxcRoot}/lxclib /${lxcRoot}/lxccache

Delete the old directory:
$ rm -rf /var/lib/lxc /var/cache/lxc

Create links to directories:
$ ln -s /${lxcRoot}/lxclib /var/lib/lxc
$ ln -s /${lxcRoot}/lxccache /var/cache/lxc

Create a basic Ubuntu-based LXC container with the name hName and with the Trusty version:
$ lxc-create -t ubuntu -n hName -r trusty

Next, let's start creating the immutable part of the LXC container.
Go to the directory of the created container:
$ cd /lxc/lxclib/hName/rootfs

In it, create a directory with a common part, call it common:
$ mkdir common

We transfer immutable directories to it:
$ mv bin lib lib64 sbin usr common/

We create symbolic links to them:
$ ln -s common/bin
$ ln -s common/sbin
$ ln -s common/lib
$ ln -s common/lib64
$ ln -s common/usr

Creating an LXC Container

After preparing the basic image of the system, we proceed directly to the creation of the first container in the system. We simply call it “Node1”:
Create a directory for the first container:
$ mkdir -p /lxc/lxclib/Node1/rootfs

Go to it:
$ cd /lxc/lxclib/Node1/rootfs

Using the rsync program, copy the immutable part to the first container:
$ rsync --exclude=/dev/* --exclude=/common/* -avz /lxc/lxclib/hName/rootfs/* ./

Next, for the first container, create two directories for the common part and for the devices:
$ mkdir /lxc/lxclib/Node1/rootfs/common
$ mkdir /lxc/lxclib/Node1/rootfs/dev

We mount them using the Bind program:
$ mount --bind /lxc/lxclib/hName/rootfs/dev /lxc/lxclib/Node1/rootfs/dev
$ mount --bind /lxc/lxclib/hName/rootfs/common /lxc/lxclib/Node1/rootfs/common
$ mount -o remount,ro /lxc/lxclib/Node1/rootfs/common

Copy the configuration file and the fstab file from the base container to the first:
$ cp /lxc/lxclib/hName/config /lxc/lxclib/Node1/
$ cp /lxc/lxclib/hName/fstab /lxc/lxclib/Node1/

Change the name in the configuration of the first container to Node1, as well as the MAC address:
$ nano /lxc/lxclib/Node1/config

Cloning method

The script that I wrote is as follows:
echo "Введите имя нового контейнера: "
read Container
cp -a /lxc/lxclib/Node1 /lxc/lxclib/${Container}
mount --bind /lxc/lxclib/hName/rootfs/dev /lxc/lxclib/${Container}/rootfs/dev
mount --bind /lxc/lxclib/hName/rootfs/common /lxc/lxclib/${Container}/rootfs/common
mount -o remount,ro /lxc/lxclib/${Container}/rootfs/common
sed -i 's/Node1/'$Container'/g' /lxc/lxclib/${Container}/config
echo "Новый контейнер с именем" $Container "создан"

Comparative characteristics with the standard lxc-clone method

What does this give us?
Firstly, I wanted to save disk space.
We find out the size occupied by the container on the disk:
$ du –skh /lxc/lxclib/Имя_контейнера

The figure shows that the volume occupied by the base container is 395 megabytes, while the volume occupied by the container cloned by my method is only 141 megabytes:

Based on the above data, saving disk space from each container is about 65%. That is, when applying this method, for example, on a server farm with hundreds of containers, disk space savings are very noticeable.

Secondly, not too impressive, but still the speed of copying the container.
The standard cloning method is performed by the command:
Measure the cloning speed with the time command .
Time - displays the execution time (in seconds) of the run command. Substitutes any executed command.
The figures show the execution time of the command in the standard way of cloning containers and mine:

Based on the above data, it can be seen that the execution time of cloning a container in the standard way takes more than 12 seconds, while the execution time of cloning in my way takes about 6 seconds.


Perhaps my idea should not be used in production at the enterprise, but I see the use of this method on mini-computers. Indeed, raising several containers on an sd card, saving a couple of hundred megabytes from one container will be a good gain.

Also popular now: