Продовжуємо наш цикл статей про контейнеризації. Якщо перші дві статті (1 і 2) були присвячені теорії, то сьогодні ми поговоримо про цілком конкретному інструменті і про особливості його практичного використання. Предметом нашого розгляду буде LXD (скорочення від Linux Container Daemon), створений канадцем Стефаном Грабі з компанії Canonical.
В рамках цієї статті ми обмежимося лише коротким введенням в LXD: порівняємо його з Docker, наведемо інструкцію по встановленню та налагодженню, а також продемонструємо базові можливості управління контейнерами.
LXD і Docker
При цьому cфера застосування у двох інструментів зовсім різна: якщо Docker призначений для запуску в контейнерах додатків, то LXD - для запуску повноцінних операційних систем.
У публікаціях Canonical відзначається, що LXD-контейнери можуть працювати в 10 разів швидше, ніж традиційні віртуальні машини на базі KVM.
У LXD зроблена спроба вирішити цілий ряд проблем, з якими доводиться стикатися при роботі з іншими інструментами контейнеризації: продуманий механізм динамічного управління ресурсами, розширені можливості міграції контейнерів (в тому числі і в режимі реального часу), усунуті проблеми безпеки. У порівнянні з Docker у LXD набагато ширше можливості переконфігурації контейнерів.
LXD оснащений відкритим API; є клієнти для різних мов програмування. Створено плагін для OpenStack. що дозволяє управляти контейнерами за допомогою клієнта Nova.
Встановлення та налаштування
Тут і далі ми будемо описувати особливості роботи c LXD на матеріалі Ubuntu 16.04. У цій ОС LXD включений в офіційні репозиторії і встановлюється стандартним способом:
Стефан Грабі в своїй статті рекомендує в якості бекенд для зберігання контейнерів використовувати файлову систему ZFS. Щоб працювати з ZFS, потрібно встановити відповідні пакети:
створення контейнера
Для першого знайомства з LXD цілком підійде локальний репозиторій (local). Запустимо в контейнері ОС Ubuntu 16.04:
В результаті виконання цієї команди LXD створить на базі вказаного способу контейнер і запустить його.
Запустити в цьому контейнері командну оболонку можна за допомогою команди:
Якщо потрібно просто створити контейнер, але не запускати його, досить виконати команду:
Для подальшого запуску і зупинки контейнера використовуються команди lxc start і lxc stop.
LXC надає хороші можливості для управління контейнерами «на льоту». Ось так, наприклад, можна помістити створений на основному хості файл всередину контейнера:
Можна зробити і зворотну операцію - завантажити файл з контейнера на основний хост
Можна і редагувати файли в контейнері безпосередньо:
Основні команди для створення і запуску контейнерів ми вже розглянули; бажаючих дізнатися більше відсилаємо до докладної статті Стефана Грабі.
управління ресурсами
Управління ізольованими оточеннями немислимо без контролю ресурсів: ми повинні надати контейнеру достатню кількість ресурсів для роботи і в той же час бути впевненими в тому, що контейнери не буде споживати зайвих ресурсів, порушуючи тим самим роботу решти системи.
У LXD можна виділяти контейнерів ресурси за допомогою спеціального набору команд:
Більш детально почитати про управління ресурсами можна в цій статті.
Робота зі снапшотов
У LXD є можливість створення снапшотов і відновлення контейнерів з снапшотов. Подивимося, як це працює на практиці (приклад узятий з інтерактивного туторіал LXD).
Внесемо деякі зміни в уже створений нами контейнер container1:
Зробимо снапшот цього контейнера і назвемо його, наприклад, new:
Спробуємо що-небудь «поламати» в нашому першому контейнері:
Поcле цього запустимо в ньому в ньому командну оболонку:
Виконаємо команду exit і повернемося на основний хост. Відновимо роботу контейнера container1 з снапшотов:
Запустимо командну оболонку у відновленому контейнері:
Все працює так само, як раніше!
У наведеному вище прикладі ми розглянули так звані stateless-снапшоти В LXD є й інший тип снапшотов - stateful, в яких зберігається поточний стан всіх процесів в контейнері. З stateful-снапшотов пов'язані ряд цікавих і корисних функцій.
Щоб створювати stateful-снапшоти, нам знадобиться встановити програму CRIU (CheckPoint / Restore in Userspace). C її допомогою можна зберегти поточний стан всіх процесів, а потім відновити їх хоч на поточній, хоч на іншій машині.
В Ubuntu 16.04 утиліта CRIU встановлюється за допомогою стандартного менеджера пакетів:
Після цього можна переходити до створення снапшотов:
У деяких ситуаціях такі снапшоти можуть виявитися дуже корисними. Уявімо собі, наприклад, що нам потрібно перезавантажити сервер, на якому запущені один або кілька контейнерів. Щоб після перезавантаження не запускати все заново, а продовжити з перерваного місця, досить виконати:
На базі stateful-снапшотов реалізований механізм «живий» міграції контейнерів, який поки що знаходиться в кілька «сиром» стані.
висновок
Природно, в рамках однієї статті розповісти про всі функції LXD навряд чи можливо. Для бажаючих дізнатися більше наводимо кілька корисних посилань:
Продовжуємо цикл статей про механізми контейнеризації. Минулого разу ми говорили про ізоляцію процесів за допомогою механізму «просторів імен» (namespaces). Але для контейнеризації однієї лише ізоляції ресурсів недостатньо. Якщо ми запускаємо будь-яка програма в ізольованому оточенні, ми повинні бути впевнені в тому, що цього додатка виділено достатньо ресурсів і що воно не буде споживати зайві ресурси, порушуючи тим самим роботу решти системи. Для вирішення цього завдання в ядрі.