LXC для локальной разработки программного обеспечения

О чем это я

Со временем на рабочей машине разработчика может скопиться целая масса всякого нужного и не нужного софта, библиотек и сервисов. Например, если Вы веб-разработчик, то в разное время, помимо, например, php или ruby (а иногда и то и другое и третье, коли Вы «полиглот»), на машине может появиться mysql, postgresql, mongodb, redis, rabbitmq, apache, nginx и в придачу куча разных библиотек, используемых вышеперечисленным софтом, и это с учетом того, что перечислено далеко не все, что может понадобится разработчику в процессе работы над проектами.

Не знаю как Вам, а мне такой бардак не нравится, более того, в моей практике приходится иметь дело не только с зоопарком софта, но еще и с обилием версий этого софта, как пример: сегодня я работаю над проектом, использующим php 5.4 + postgres 9.3, завтра латаю дыры в дремучем legacy, которое работает поверх php 5.2 и mysql 5.1, послезавтра вообще ковыряю библиотеку на ruby или python. На боевом сервере работать не комильфо, так что желательно иметь локальную версию не только приложения, но и его окружения.

В свое время я неоднократно обращался к виртуализации, как к средству решения двух проблем: чистота базовой системы (с прицелом на обновление дистрибутива, меньше хлама — проще обновиться) и серверное окружение максимально приближенное к боевому. Использовал VirtualBox (сначала GUI, потом в связке с Vagrant). Несмотря на то, что в целом я решал вышеозвученные проблемы, присутствовало некоторое ощущение чужеродности такого решения, использование Vagrant упростило разворачивание и автоматизацию этого процесса, но сам Vagrant при этом тащил по зависимостям ruby и некоторые библиотеки, наличие которых нарушало «чистоту» (тут конечно я в некотором роде перегибаю, но что поделать, перфекционизм болезнь неизлечимая). Потом появились «нативные» решения, среди которых и LXC. Долгое время я откладывал попытки опробовать и внедрить в рабочий процесс использование этого способа виртуализации, но, в итоге, созрел.

Для тех, кто не совсем в курсе, Википедия подсказывает: «LXC (англ. Linux Containers) — система виртуализации на уровне операционной системы для запуска нескольких изолированных экземпляров операционной системы Linux на одном узле. LXC не использует виртуальные машины, а создает виртуальное окружение с собственным пространством процессов и сетевым стеком. Все экземпляры LXC используют один экземпляр ядра операционной системы.»

Остановил свой выбор на LXC, так как для работы мне более чем достаточно контейнера, в котором я смогу развернуть нужную мне версию операционной системы и установить необходимый софт. Заранее хочу отметить, что от использования Docker отказался сразу в виду того, что он и так работает поверх LXC, а предлагаемый в нагрузку overhead мне в общем-то не нужен, так как от инструмента управления контейнерами мне нужен минимум и LXC этот минимум предоставляет.

Итак по порядку.

Стратегия

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

  • для разработки нового софта: 1 контейнер — 1 сервис.
  • для воссоздания боевого окружения уже существующего приложения — 1 контейнер для всего
  • код находится на хосте под управлением git|mercurial|subversion (нужное подчеркнуть)

Более того, если существующее приложение просто нуждается в доработке и не имеет проблематичной специфики в боевом серверном окружении, то для него подойдет первый вариант, просто нужно разместить компоненты в нужных контейнерах и связать их по сети через виртуальный интерфейс, что на практике является просто записью ip адресов в конфигурационном файле приложения.

Как пример: приложение является обычным интернет-магазином, реализованном на коробочной cms (допустим opencart), работает одинаково на версиях php от 5.2 до 5.6 и mysql от 5.1 до 5.6, версия nginx и(или) apache тоже роли не играют. В данной ситуации достаточно разместить код в контейнер с установленным php и веб-сервером, а дамп базы залить в контейнер с БД, в настройках БД в этом контейнере достаточно дать разрешение на соединение по сети, после старта контейнеров приложение будет доступно по ip адресу того контейнера, в котором развернуты php и apache|nginx.

При этом исходный код приложения совсем не обязательно размещать непосредственно в контейнере, LXC позволяет монтировать директории хоста внутрь контейнера. Если продолжить пример с opencart, то локально код магазина у меня размещен в директори /home/gwinn/Sources/php/cms/opencart, в контейнере же эта директория примонтирована в /srv/opencart, так что я вполне спокойно работаю с кодом без необходимости лезть внутрь контейнера.

При необходимости запустить код в консоли проблемы тоже нет, открыв консоль, достаточно вызвать команду:

sudo lxc-attach -n container_name

и все, Вы все в той же нативной консоли, в какой привыкли работать каждый день.

Набор контейнеров с определенными версиями програмного обеспечения позволяют в перспективе комбинировать уже созданые контейнеры для решения новых задач, если для их решения нет необходимости прибегать с специфичным настройкам.

Более того, возможность клонировать контейнеры позволяет создать «симуляцию» распределенной системы в рамках одного хоста без каких либо серьезных ограничений со стороны операционной системы.

Установка LXC

В качестве хоста я использую Fedora, в качестве гостя — обычно Debian, если нет необходимости в конкретной версии конкретного дистрибутива.
Установим и быстренько настроим пару контейнеров для простого веб-приложения, где кроме php и postgresql нам особо ничего не понадобится:

sudo dnf install lxc* libvirt libvirt-daemon debootstrap bridge-utils redir
sudo systemctl start libvirtd

Проверим наличие виртуального моста:

brctl show

Если видим что-то типа:

bridge name bridge id   STP enabled interfaces
virbr0    8000.52540049bd93 yes   vethK8WPM2

То все нормально, можно продолжать, в противном случае перезагрузка должна решить проблему отсутствия моста.

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

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

sudo lxc-create -t debian -n postgres

После того, как будет создан контейнер, нам нужно немного поправить конфигурацию запуска:

sudo vim /var/lib/lxc/postgres/config
lxc.network.type = veth
lxc.network.link = virbr0 # по умолчанию lxcbr0, изменить на virbr0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:4c:b7:a7
lxc.include = /usr/share/lxc/config/debian.common.conf
lxc.arch = amd64
lxc.rootfs = /var/lib/lxc/postgres/rootfs
lxc.utsname = postgres

Чтобы каждый раз не менять пункт конфигурации lxc.network.link можно сделать следующее:

sudo sed -i s/lxcbr0/virbr0/g /etc/lxc/default.conf

Теперь запустим контейнер:

sudo lxc-start -n postgres

Зайдем в контейнер как root:

sudo lxc-attach -n postgres

И уже находясь внутри установим, настроим и запустим postgres:

apt install postgresql postgresql-client postgresql-contrib postgresql-filedump

В pg_hba.conf добавляем следующее (trust используется для упрощения):

# с учетом того, что ip контейнера 192.168.122.6
host    all    all    192.168.122.1/32    trust

В postgresql.conf добавляем:

listen_address = '*'

Теперь собственно достаточно запустить сервис:

service postgresql start

и готово, можно коннектиться по адресу 192.168.122.6:5432, ниже видео процесса создания контейнера:

Для второго контейнера, где будет жить php в связке с nginx, нужно, по сути, воспроизвести все те же операции, за исключением специфики настройки самих php и nginx и монтирования директории с исходниками:

lxc.rootfs = /var/lib/lxc/php/rootfs
lxc.utsname = php
lxc.mount.entry=/home/gwinn/Sources/php /var/lib/lxc/php/rootfs/srv none bind,create=dir 0 0

На этом базовая настройка завершена, дальше только полировка настроек и автоматизация процесса, но это уже чисто субъективный процесс, так что в рамках этой статьи я его пожалуй освещать не стану.

LXC для локальной разработки программного обеспечения

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

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