Создание метода клонирования LXC-контейнеров

от автора

Немножко предыстории

В конце прошлого года, когда пришло время начинать писать диплом, я наткнулся на статью пользователя am83. Так как я крайне неравнодушен к виртуализации, хотелось придумать что-то относящееся к этой теме. И тут у меня родилась идея по поводу использования общей файловой системы для создания метода, который бы позволил сэкономить дисковое пространство при клонировании контейнеров LXC.

Итак, на основе статьи, написанной am83, я проделал несколько шагов для создания общей файловой системы.

Создание основы файловой системы для контейнеров

Устанавливаем основные компоненты, которые понадобятся для создания общей файловой системы, командой:

$ apt-get install debootstrap lxc lxc-templates lxctl cgroup-lite rsync 

Далее включим две управляющие опции.
В конфигурации сети включим сетевой мост для контейнеров:

$ nano /etc/init/lxc-net.conf USE_LXC_BRIDGE="true" 

А для автозапуска контейнеров при старте системы включим:

LXC_AUTO="true" 

В файле lxc.conf, командой:

$ nano /etc/init/lxc.conf 

Далее отредактируем конфигурационный файл:

$ nano /etc/default/lxc 

И добавим в него следующие строки:
Введем переменную:

$ lxcRoot="/lxc" 

Создадим каталог /lxc:

$ mkdir -p ${lxcRoot} 

Создаем место где хранятся контейнеры и информация по их настройкам, а также место кеширования данных дистрибутивов для ускорения создания множества контейнеров:

$ mkdir /${lxcRoot}/lxclib /${lxcRoot}/lxccache 

Удалим старый каталог:

$ rm -rf /var/lib/lxc /var/cache/lxc 

Создадим ссылки на каталоги:

$ ln -s /${lxcRoot}/lxclib /var/lib/lxc $ ln -s /${lxcRoot}/lxccache /var/cache/lxc 

Создаем базовый LXC-контейнер на основе Ubuntu с именем hName и с версией Trusty:

$ lxc-create -t ubuntu -n hName -r trusty 

Далее приступим к созданию неизменяемой части LXC-контейнера.
Переходим в каталог созданного контейнера:

$ cd /lxc/lxclib/hName/rootfs 

В нем создаем каталог с общей частью, назовем его common:

$ mkdir common 

Переносим в него неизменяемые каталоги:

$ mv bin lib lib64 sbin usr common/ 

Создаем символические ссылки на них:

$ ln -s common/bin $ ln -s common/sbin $ ln -s common/lib $ ln -s common/lib64 $ ln -s common/usr 

Создание контейнера LXC

После подготовки базового образа системы приступим непосредственно к созданию первого контейнера в системе. Назовем его просто «Node1»:
Создаем каталог для первого контейнера:

$ mkdir -p /lxc/lxclib/Node1/rootfs 

Переходим в него:

$ cd /lxc/lxclib/Node1/rootfs 

При помощи программы rsync копируем неизменяемую часть в первый контейнер:

$ rsync --exclude=/dev/* --exclude=/common/* -avz /lxc/lxclib/hName/rootfs/* ./ 

Далее для первого контейнера создаем два каталога для общей части и для устройств:

$ mkdir /lxc/lxclib/Node1/rootfs/common $ mkdir /lxc/lxclib/Node1/rootfs/dev 

Монтируем их при помощи программы Bind:

$ 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 

Копируем файл конфигурации и файл fstab из базового контейнера в первый:

$ cp /lxc/lxclib/hName/config /lxc/lxclib/Node1/ $ cp /lxc/lxclib/hName/fstab /lxc/lxclib/Node1/ 

Меняем имя в конфигурации первого контейнера на Node1, а также MAC-адрес:

$ nano /lxc/lxclib/Node1/config 

Метод клонирования

Скрипт, который я написал выглядит следующим образом:

#!/bin/bash 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 "создан" 

Сравнительные характеристики со стандартным методом lxc-clone

Что это нам дает?
Во-первых я хотел сэкономить дисковое пространство.
Узнаем размер, занимаемый на диске контейнером:

$ du –skh /lxc/lxclib/Имя_контейнера 

На рисунке видно, что объем, занимаемый базовым контейнером составляет 395 мегабайт, тогда как объем, занимаемый контейнером, клонированным моим методом, составляет всего 141 мегабайт:

Исходя из вышеперечисленных данных – экономия дискового пространства с каждого контейнера выходит порядка 65%. То есть при применении данного метода, например, на серверной ферме с сотнями контейнеров экономия дискового пространства весьма заметна.

Во-вторых, не слишком впечатляющая, но все же скорость копирования контейнера.
Стандартный способ клонирования выполняется командой:
Замерим скорость клонирования командой time.
Time – выводит на экран время выполнения (в секундах) запускаемой команды. Подставляется перед любой выполняемой командой.
На рисунках представлено время выполнения команды стандартным способом клонирования контейнеров и моим:

Исходя из вышеперечисленных данных видно, что время выполнения клонирования контейнера стандартным способом занимает более 12 секунд, тогда как время выполнения клонирования моим способом, занимает около 6 секунд.

В итоге

Возможно, мою идею и не стоит использовать в продакшене на предприятии, но мне видится использование сего метода на мини-компьютерах. Ведь, поднимая несколько контейнеров на sd-карте, экономия пару сотен мегабайт с одного контейнера будет неплохим выигрышем.

ссылка на оригинал статьи http://habrahabr.ru/post/227599/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *