Systemd і контейнери: знайомство з systemd-nspawn

PR-1505-3

Контейнеризація сьогодні — одна з найактуальніших тем. Кількість публікацій про таких популярних інструментах, як LXC або Docker, обчислюється тисячами, якщо не десятками тисяч.
У цієї статті б ми хотіли обговорити ще одне рішення-про якому публікацій на російською мовою поки що мало. Мова йде про systemd-nspawn   інструмент для створення ізольованих середовищ, який є одним з компонентів systemd. А закріплення systemd в якості стандарту в світі Linux — вже доконаний факт. У світлі цього факту є всі підстави вважати, що в найближчим часом сфера застосування systemd-nspawn істотно розшириться, і познайомитися з цим інструментом ближче варто вже зараз.


Systemd-nspawn: загальна інформація

Назва systemd-nspawn являє собою скорочення від namespaces spawn. Вже з цієї назви випливає, що systemd-nspawn управляє тільки ізоляцією процесів, але не може ізолювати ресурси (проте це можна зробити засобами самого systemd, що ще піде мова нижче).

З допомогою systemd-nspawn можна створити повністю изолированое оточення, в якому автоматично будуть змонтовані псевдофайловые системи /proc та /sys, а також створені ізольований loopback-інтерфейс і окремий простір імен для ідентифікаторів процесів (PID), всередині якого можна запускати ОС, засновану на ядрі Linux.

Спеціального сховища образів, як в Docker, в systemd-nspawn не існує. Для створення та завантаження образів можна використовувати будь-які сторонні інструменти. Підтримуються формати tar, raw, qcow2 і dkr (dkr — це образи для Docker; у документації до systemd-nspawn про це в явній формі ніде не написано, а її автори старанно уникають самого слова Docker). Робота з образами здійснюється на базі файлової системи BTRFS.

Запускаємо в контейнері Debian

Знайомство з systemd-nspawn почнемо з простого, але показового практичного прикладу. На сервері під управлінням OC Fedora ми створимо ізольоване оточення, який буде запущений ОС Debian. Все нижче приводяться приклади команд для Fedora 22 c systemd 219-ї версії; в інших дистрибутивах Linux і інших версіях systemd команди можуть відрізнятися.

Почнемо з встановлення необхідних залежностей:


# sudo dnf install debootstrap bridge-utils


Потім створимо файлову систему для майбутнього контейнера:


# sudo debootstrap --arch=amd64 jessie /var/lib/machines/container1/


&Nbsp;завершення всіх підготовчих робіт можна приступати до запуску контейнера:


# sudo systemd-nspawn -D /var/lib/machines/container1/ --machine test_container 


На консолі з'явиться запрошення гостьової операційної системи:


# root@test_container


Встановимо для неї пароля root:


# passwd
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully


Вийдемо з контейнера, натиснувши комбінацію клавіш Ctrl+]]] потім виконаємо наступну команду:


# sudo systemd-nspawn -D /var/lib/machines/container1/ --machine test_container -b


У ній присутній прапор -b (або --boot), який вказує, що при запуску екземпляра операційної системи контейнері потрібно виконати init з запуском всіх демонів.Цей прапор можна використовувати тільки в у разі, якщо в контейнері буде запущена система з підтримкою systemd.У іншому випадку завантаження системи не гарантується.

&Nbsp;завершення всіх зазначених операцій система запропонує ввести логін і пароль.
Отже, повноцінна ОС ізольованому оточенні запущена. Тепер потрібно налаштувати для неї мережа, Вийдемо з контейнера і створимо міст, через який він буде з'єднюватись з інтерфейсом на основному хості:


# sudo brctl addbr cont-bridge


Призначимо для цього моста IP-адреса:


# ip a a [IP-адреса] dev cont-bridge


Після цього виконаємо команду:


# sudo systemd-nspawn -D /var/lib/machines/container1/ --machine test_container --network bridge=cont-bridge -b


Для налаштування мережі можна також скористатися опцією --network-ipvlan, яка зв'яже контейнер з вказаними інтерфейсом на основному хості з допомогою ipvlan:


# sudo systemd-nspawn -D /var/lib/machines/container1/ --machine test_container -b --network-ipvlan=[мережевий інтерфейс]


Запускаємо контейнер як службу

З допомогою systemd можна налаштувати на автоматичний запуск при завантаженні контейнерів системи. Для цього додамо в директорію /etc/systemd/system ось такий конфігураційний файл:


[Unit]


Description=Test Container



[Service]


LimitNOFILE=100000


ExecStart=/usr/bin/systemd-nspawn --machine=test_container --directory=/var/lib/machines/container1/ -b --network-ipvlan=[мережевий інтерфейс] 


Restart=always



[Install]


Also=dbus.service


Прокоментуємо наведений фрагмент. У секції [Description] ми просто вказуємо ім'я контейнера. У секції [Service] ми спочатку задаємо ліміт на кількість відкритих файлів у контейнері (LimitNOFILE), потім вказуємо команду на запуск контейнера з необхідними опціями (ExecStart). Вказівка Restart=always означає, що контейнер потрібно перезавантажити випадку «падіння». У секції [Install] вказується додатковий юніт, який повинен бути доданий в автозапуск на хості (в нашому випадку це система межпроцессного взаємодії D-Bus).

Збережемо зміни в конфігураційному файлі виконаємо команду:


# sudo systecmctl start test_container


Запускати контейнер як службу можна і іншим, більш простим способом. У systemd є заготівля конфігураційного файлу для автоматичного запуску контейнерів, поміщених у директорію /var/lib/machines. Активувати запуск на базі цієї заготовки можна з допомогою наступних команд:


# sudo systemctl enable machine.target


# mv ~/test_container /var/lib/machines/test_container


# sudo systemctl enable systemd-nspawn@test_container.service


Управління контейнерами: утиліта machinectl

Контейнерами можна управлятися з допомогою утиліти machinectl. Коротко розглянемо її основні опції.

Вивести список всіх наявних у системі контейнерів:


# sudo machinectl list


Переглянути інформацію про статус контейнера:


# sudo machinectl status test_container


Увійти в контейнер:


# sudo machinectl login test_container


Перезавантажити контейнер:


# sudo machinectl reboot test_container


Зупинити контейнер:


# sudo machinectl poweroff test_container


Остання команда спрацює, якщо у контейнері встановлено ОС, сумісну з systemd. Для операційних систем, що використовують sysvinit, потрібно скористатися опцією terminate.
Ми розповіли лише про самих базових можливості утиліти machinectl; з детальною інструкцією щодо її використання можна ознайомитися, наприклад, тут.

Завантаження образів

Вище ми вже говорили, що з допомогою systemd-nspawn можна запускати образами будь-яких інших форматів. Проте є одна важлива умова: робота з образами можлива тільки на базі файлової системи BTRFS, яку потрібно примонтувати до каталозі /var/lib/machines:


# sudo dnf install btrfs-progs


# mkfs.btrs /dev/sdb


# mount /dev/sdb /var/lib/machines


# mount | grep btrfs



dev/sdb on /var/lib/machines type btrfs (rw,relatime,seclabel,space_cache)


Якщо немає вільного диска, BTRFS можна зробити і у файлі.
У більш нових версіях systemd можливість завантаження образів підтримується «з коробки», і монтувати BTRFS не потрібно.

Спробуємо завантажити образ Docker:


# sudo machinectl pull-dkr --verify=no library/redis --dkr-index-url=https://index.docker.io


Запуск контейнера на базі завантаженого образу здійснюється просто:


# sudo systemd-nspawn --machine-redis


Перегляд логів контейнера

Інформація про всі події, що відбуваються всередині контейнерів, записується в логи. Налаштування логгирования можна встановлювати безпосередньо при створенні контейнера з допомогою опції
--link-journal, наприклад:


# sudo systemd-nspawn -D /var/lib/machines/container1/ --machine test_container -b-link-journal=host


Наведена команда вказує, що логи контейнера будуть зберігатися з на основному хості в каталозі /var/log/journal/machine-id. Якщо ж виставити опцію --link-journal=guest, то вся логи будуть зберігатися в контейнері каталозі /var/log/journal/machine-id на основному хості буде створена символическиая посилання в директорії c аналогічним адресою. Опція --link-journal буде працювати тільки в у разі, якщо в контейнері буде запущена система з systemd. В іншому випадку коректне логгирование не гарантується.

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


# journalctl -u <ім'я контейнера>.service


У journalctl передбачена можливість перегляду логів подій всередині контейнера.
Для цього використовується опція -M (наводимо лише невеликий фрагмент виводу):


# journalctl -M test_container



Sep 18 11:50:21 octavia.localdomain systemd-journal[16]: Runtime journal is using 8.0 M (max allowed 197.6 M, trying to leave 296.4 M free of 1.9 G available <E2><86><92> current limit 197.6 M).


Sep 18 11:50:21 octavia.localdomain systemd-journal[16]: Runtime journal is using 8.0 M (max allowed 197.6 M, trying to leave 296.4 M free of 1.9 G available <E2><86><92> current limit 197.6 M).


Sep 18 11:50:21 octavia.localdomain systemd-journal[16]: Journal started


Sep 18 11:50:21 octavia.localdomain systemd[1]: Starting Slices.


Sep 18 11:50:21 octavia.localdomain systemd[1]: Reached target Slices.


Sep 18 11:50:21 octavia.localdomain systemd[1]: Starting Remount Root and Kernel File Systems...


Sep 18 11:50:21 octavia.localdomain systemd[1]: Started Remount Root and Kernel File Systems.


Sep 18 11:50:21 octavia.localdomain systemd[1]: Started Various fixups to make systemd work better on Debian.


Виділення ресурсів

Основні особливості systemd-nspawn ми розглянули. Залишився один важливий момент: виділення контейнерів ресурсів. Як вже зазначалося вище, systemd-nspawn ресурси не ізолює. Обмежити споживання ресурсів для контейнера можна з допомогою systemctl, наприклад:


# sudo systemctl set-property <ім'я контейнера> CPUShares=200 CPUQuota=30% MemoryLimit=500M


Обмеження ресурсів для контейнера можна прописати і в юніт-файлі, в секції [Slice].

Висновок

Systemd-nspawn   інструмент цікавий і перспективний. У серед безперечних плюсів варто виділити:

  • тісну інтеграцію з іншими компонентами systemd;
  • можливість роботи з образами в різних форматах;
  • відсутність необхідності встановлювати будь-які додаткові пакети або накладати латки на ядро.


Звичайно, говорити про повноцінному використанні systemd-nspawn в продакшне поки що рано: інструмент поки що знаходиться в «сирому» стані і підходить тільки для тестування і експериментів. Однак за міру подальшого поширення systemd варто чекати і удосконалення systemd-nspawn.

Природно, що в рамках оглядової статті неможливо розповісти абсолютно про все. У коментарях вітаються будь-які питання, зауваження і доповнення.
Якщо ми упустили якісь деталі або не розповіли про якихось цікавих можливості systemd-nspawn   напишіть, і  обов'язково доповнимо наш огляд.
А якщо хтось із вас користується systemd-nspawn, запрошуємо поділитися досвідом.

Читачів, які з тих чи інших причин не можуть залишати коментарі тут, запрошуємо в наш блог.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.