LXC за разработчик
Работейки върху повече или по-малко сложен проект, вие трябва да поддържате средата, необходима за правилното функциониране на системата. Често това води до ситуация, в която има толкова много пакети и зависимости, инсталирани на машината, че възникват много проблеми:
- средата става трудна за възпроизвеждане на друга машина (например нов разработчик);
- околната среда става крехка. Актуализирането на зависимости за някои спомагателни програми нарушава основния проект;
- околната среда е трудна за промяна. Бих искал да експериментирам с някаква библиотека, но поради опасността от прецакване със зависимостите, тази идея трябва да бъде изоставена.
На платформата Java тези проблеми са по-малко забележими поради разработените инструменти за управление на зависимостите, както и затвореността на платформата. В екосистемата на Java библиотеките C / C ++ не са много добре дошли. Всички популярни драйвери и библиотеки са написани директно на Java, така че няма проблеми с управлението на системните зависимости. А за управление на библиотеки в Java има много зрели инструменти.
На други PHP/Python платформи проблемът е по-актуален, въпреки че са налични инструменти като composer и virtualenv.
Но в една или друга степен тези проблеми са типични за всички платформи и единствената разлика е на какво ниво на сложност на системата ще започнете да изпитвате тези проблеми. Някъде по-рано, някъде по-късно.
Виртуализацията отчасти помага за решаването на проблема. Инсталирайки различни приложения в различни виртуални машини, вие ги изолирате едно от друго, като по този начин се спасявате от ненужни проблеми. Разделяй и владей, така да се каже. Виртуализацията също ви позволява да стандартизирате средата, в която работи приложението. По-лесна поддръжка на една операционна системапроизводителност на приложението от три.
Какво не е наред с VirtualBox?
VirtualBox е страхотна, цялостна система за виртуализация, която мога да препоръчам на всеки, който има нужда от нея. Но за мен пълната хардуерна виртуализация е излишна, тъй като в повечето случаи работя с една и съща операционна система - Linux.
С течение на времето формулирах своя списък с желания:
- Искам да мога бързо да създавам нови виртуални машини за експериментиране. Бърз като време и брой команди за въвеждане;
- Искам виртуалните машини да се зареждат бързо (1-2 секунди, не повече);
- Искам създаването на нова виртуална машина да не изисква стотици мегабайти на моя и без това не много голям SSD;
- Искам виртуалната машина да има нисък отпечатък на паметта, така че да е възможно да поддържате 5-6 работещи машини паралелно без значителни разходи за хост операционната система.
Използвайки разграничаващото изображение на VirtualBox, можете съвсем адекватно да затворите третата точка. Иначе това решение е като оръдие за врабчета.
Отчасти Vagrant ви позволява да решите проблема с автоматизирането на създаването на нови машини и тяхната първоначална конфигурация. Цената за това е липсата на поддръжка за различни изображения и в резултат на това много заето място за изображения на виртуална машина.
Решението, до което стигнах
Решението за мен беше LXC (Linux Containers). Това е система за виртуализация на ниво операционна система, която ви позволява да стартирате дъщерни операционни системи в хост операционната система, всяка от които има:
- собствена виртуална памет;
- собствена файлова система
- вашия мрежов стек.
В този случай ядрото остава от хост операционната система. Последният аспект за мен има 2 важни предимства:
- светкавично бързи скорости на зареждане и изключване (по-малко от 1 секунда);
- без допълнителни разходи за поддържане на отделно ядро за всяка виртуална машина (основно в паметта).
LXC също знае как да работи с BTRFS, който поддържа Copy-on-Write. Това ви позволява незабавно да копирате основното изображение на контейнера, което използвам като шаблон за създаване на нови, без да увеличавате количеството заето място на SSD.
Така затворих всичките 4 от моя списък с желания:
- контейнерът се създава с една команда, която се изпълнява за по-малко от секунда;
- контейнерът също се зарежда не повече от секунда;
- благодарение на BTRFS системните файлове, споделени между контейнерите, които са мнозинството, не се дублират на SSD;
- контейнерите са относително ефективни за паметта, което им позволява да работят във фонов режим без много проблеми за хоста.
Време за създаване (сек.) | 100 |
Какво имам в контейнерите?
Като цяло „шмурдяк за развитие“. В момента имам следните услуги в контейнери:
- MySQL, за тестване на приложения;
- MongoDB, по подобна причина;
- Jekyll, който използвам, за да напиша този блок;
- IPython, който напоследък използвам все повече и повече като безплатна алтернатива на Mathematica;
- няколко проекта с персонализирана среда за провеждане на интеграционни тестове, върху които работя.
Как да настроя LXC?
Тъй като работя на Mac OS X, все още имам нужда от междинна Linux виртуална машина и в резултат на това VirtualBox не изчезва никъде. Изберете по-малката от двете злини, какво да правите. Цялата верига изглежда таканачин:

За да опростим по-нататъшния разказ, нека дефинираме терминологията:
- хост - Mac OS X, който се инсталира директно на лаптопа;
- VM - хардуерно виртуализиран Ubuntu, който работи под VirtualBox на Mac OS X;
- контейнер – LXC контейнер, който се намира на виртуализиран Ubuntu под VirtualBox в къщата, която Джак построи.
Накратко, процедурата за подготовка на "полигон" за контейнеризиране е следната:
- инсталирайте VirtualBox;
- създайте нова виртуална машина със следните функции:
- два мрежови интерфейса: NAT и Host-only network. Първият е необходим за достъп до интернет, вторият, за да може виртуалната машина да бъде достъпна от хоста;
- два HDD. Първият е директно под операционната система, вторият е за съхраняване на изображения на контейнери. Вторият твърд диск ще бъде означен като BTRFS. Теоретично можете да минете с един HDD на BTRFS. Проверката на ефективността на такава схема остава на съвестта на читателя.
- поставете любимия си Ubuntu на виртуалната машина. Използвах 14.04 сървър;
След успешна инсталация трябва да инсталирате всички необходими пакети на Linux.
Подготовка на BTRFS том
За бързо клониране на контейнер без дублиране се нуждаем от BTRFS том. Ако сте свързали два твърди диска към VM, вторият ще бъде достъпен под името /dev/sdb. Създайте файлова система върху него:
След като командата завърши успешно, добавете запис към /etc/fstab, така че томът да се монтира автоматично към /var/lib/lxc (директорията по подразбиране с LXC контейнерни изображения) при стартиране на системата.
В този фрагмент трябва да промените UU >blkid :
Вместо UU > можете да използвате /dev/sdb. Първият вариант е за предпочитанетъй като UUID не зависи от реда, в който блоковите устройства са регистрирани в системата.
Настройка на мрежата на VM
Според мен най-удобният начин за организиране на мрежово взаимодействие между хост и виртуални машини за задачи по разработка е следният. Всяка виртуална машина и всеки контейнер има два интерфейса:
- eth0 - който е NATed и осигурява машинен достъп до Интернет;
- eth1 - който е свързан към мрежата Host-only VirtualBox и осигурява връзката на всички виртуални машини помежду си и с хоста.
Имайте предвид, че инструкциите в тази статия разчитат на интерфейсите, конфигурирани с тези имена ( eth0 за NAT и eth1 за мрежа само за хост).
За да могат контейнерите да имат достъп до мрежата само за хост на VirtualBox, мрежовият мост трябва да бъде конфигуриран през eth1. Това се прави във файла /etc/network/interfaces.
Имайте предвид, че eth1 е коментиран нарочно.
Създаване и конфигуриране на базов контейнер
За бързото създаване на контейнери е необходимо да се подготви базово копие, което да се клонира. Това става с командата:
Ще отнеме известно време на системата да изтегли необходимите пакети от интернет и да подготви базовото изображение на контейнера.
Сега трябва да препратим интерфейсите, които сме конфигурирали на VM към LXC. Редактирайте /etc/default/lxc-net:
Избрах мрежата 192.168.10.0/24 произволно, това решение може безопасно да бъде променено въз основа на вашия контекст.
Също така е необходимо да се провери дали и двата интерфейса са правилно хвърлени в основния контейнер и също така правилно конфигурирани вътре в контейнера. За да направите това, първо се уверете, че файлът /var/lib/lxc/base/config съдържа следните редове:
второ,проверете дали интерфейсите са конфигурирани в /var/lib/lxc/base/rootfs/etc/network/interfaces.
Интерфейсът eth0 вътре в контейнера е деактивиран за мен, тоест контейнерът няма достъп до интернет, когато се зарежда. Причините са чисто лични-параноични. Ако това не работи за вас, разкоментирайте реда auto eth0. Включвам интернет, когато трябва:
Стартиране на основния контейнер
Контейнерът вече е готов за работа. Командите lxc-* се използват за работа с контейнери. Първият и най-простият извежда списък с контейнери, както и техния статус:
Имайте предвид, че всички LXC команди трябва да се изпълняват като root. Възможно е да работите с контейнери като непривилегирован потребител, но това е малко по-сложно. За да стартирате контейнера, просто стартирайте:
Първата команда ще стартира контейнера, а втората ще стартира обвивката в пространството от имена на този контейнер. Воала, вие сте в контейнер. Съветвам ви винаги да предавате превключвателя -d на lxc-start, в противен случай текущият ви терминал ще бъде свързан към терминала на контейнера и единственият начин да го развържете е да изгасите контейнера.
На този етап е препоръчително да проверите дали всички системни помощни програми, от които се нуждаете в ежедневната си работа (например curl, strace, sar и други), са инсталирани и ако не, инсталирайте ги.
Клониране и стартиране на дъщерни контейнери
За да създадете бързо нов контейнер, въведете следната команда:
Ако сте конфигурирали всичко правилно, контейнерът ще бъде клониран моментално. На моята машина това отнема десетки милисекунди!
Свързване към контейнер и спирането му
За да се свържете с контейнера, можете да използвате следната команда:
Тази команда ще стартира обвивката по подразбиране в контейнера. От тази черупка вече стеможете да правите каквото ви е необходимо: да инсталирате софтуер, да конфигурирате самия контейнер и т.н. Същата команда може да се използва за стартиране на произволни процеси в контейнер:
Друга полезна команда е lxc-start-ephemeral. Позволява ви да стартирате контейнер, който ще бъде унищожен веднага щом бъде спрян. Много е удобно да го използвате по следния начин:
В този случай се създава нов временен контейнер с произволно име въз основа на основния контейнер. Веднага след като излезете от черупката, свързана с него, контейнерът се унищожава. За различни видове малки експерименти, това е всичко.
Фина настройка на средата
За да може цялата тази схема не само да работи, но и да работи удобно, инсталирам допълнително Avahi и OpenSSH.
Инсталиране и конфигуриране на Avahi
За да можем да адресираме машините по име и да не търсим техните IP адреси, ние задаваме Avahi както на виртуалната машина, така и в основния контейнер. Това е реализация на протокола mDNS, който се поддържа и в Mac OS X (Bonjour).
Във файла /etc/avahi/avahi-daemon.conf в основния контейнер пишем:
Към същия файл във виртуалната машина:
Ние също пишем в /etc/default/avahi-daemon и на двете машини:
Не забравяйте да рестартирате avahi-daemon след промените:
Сега всеки хост ще бъде достъпен със своето име (вижте име на хост) в зоната .local. Например, контейнер с име foo би бил наличен като foo.local.
Инсталиране и конфигуриране на SSH
Обикновено използвам OpenSSH, за да администрирам цялата тази бъркотия. За да направите това, OpenSSH е инсталиран на виртуалната машина и в основното изображение на контейнера:
Уверете се, че /etc/ssh/sshd_config има:
Добавете вашия публичен ключ към базовото изображение и виртуалната машина,за да не се налага постоянно да въвеждате парола:
След това конфигурираме SSH клиента на хоста за лесен достъп до виртуалната машина и контейнерите. За това в
Това задава потребителското име по подразбиране и предпочитания метод за удостоверяване. Заедно с факта, че Avahi автоматично съобщава имената на домейни на контейнерите на всички, за да стигнете до контейнера с име foo, сега е достатъчно да въведете командата:
Управлявайте контейнери от хоста
Командите lxc-* са налични за управление на контейнери на виртуална машина. Още веднъж ще дам кратък списък от тях (можете да получите пълния списък, като напишете lxc- в конзолата на виртуалната машина и натиснете Tab):
- lxc-start - стартиране на контейнера;
- lxc-stop - спиране на контейнера;
- lxc-clone - клониране на контейнер;
- lxc-destroy - изтриване на контейнер;
- lxc-attach - свързване към конзолата на контейнера / стартиране на процеса в пространството на имената на контейнера;
- lxc-ls - списък с контейнери и техните статуси;
- lxc-start - стартиране на контейнера;
- lxc-wait - ви позволява да изчакате, докато контейнерът влезе в определено състояние (например стартира).
За да изпълните тези команди, първо трябва да влезете във виртуалната машина на Ubuntu. Не винаги е удобно, не винаги е удобно. Затова добавих към
/.bashrc за Bash) следните редове:
Сега 5-те посочени команди са налични на хоста.
Послеслов
Веригата би била много по-проста, ако основната ми операционна система беше Linux. В този случай няма нужда от междинен VirtualBox и става възможно да се изпълняват GUI приложения в контейнери. Със сбора на факторите Mac OS X работи по-добре за мен като компромисно решение както за работа, така и за лични задачи. Следователно човек трябва да се примиритакава матрьошка.