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

в 13:50, , рубрики: linux, 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 мегабайт:

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

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

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

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

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

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

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

В итоге

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

Автор: Klimy

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js