Контейнеры systemd

Контейнеры systemd

Введение

Сегодня поговорим о виртуализации на уровне ядра операционной системы и будут рассмотрены контейнеры systemd-nspawn которые помогут вам по максимуму использовать вычислительные ресурсы хоста и обеспечить безопасное функционирование приложений с помощью некоторых функциональных возможностей ядра Linux. В статье будет использоваться ОС Astra Linux, которая активно пробирается в отечественные компании.

Немного теории

Прежде, чем приступать к созданию контейнеров, рассмотрим, с помощью каких возможностей ядра мы можем выполнять виртуализацию.
Для начала стоит понимать что понятие контейнер - это условность. Ядро не знает ни о каких контейнерах. Ядро обладает определенным набором возможностей, которые позволяют в определенной степени ограничить процесс.

Основные средства для ограничения

На рисунке представлены основные средства, которые помогут ядру ограничить процесс

Приступаем к созданию контейнера systemd-nspawn

Устанавливаем необходимые пакеты  
apt install systemd-container debootstrap brctl

systemd-container - инструмент управления контейнерами.
debootstrap - инструмент, который установит базовую систему в подкаталог с уже установленной системой.
brctl - утилита понадобится нам для создания сетевого моста.

С помощью утилиты debootstrap создадим в директории  /var/lib/machines/[container-name] копию файловой системы, но перед этим посмотрим, какая система установлена на хосте с помощью файла /etc/os-release.
cat /etc/os-release

Узнав название версии (в нашем случае orel), указываем её и путь к хранилищу, где расположен дистрибутив нужной версии в аргументе команды  debootstrap, сменив перед этим пользователя на root.
debootstrap orel /var/lib/machines/my_first_container/ https://download.astralinux.ru/astra/stable/orel/repository

Исполнение команды

Если при скачивании из различных репозиториев возникают проблемы - обратитесь к материалу https://wiki.astralinux.ru/pages/viewpage.action?pageId=3276859

Запустим контейнер 
systemd-nspawn -D /var/lib/machines/my_first_container/
Затем следует сменить пароль суперпользователя 
passwd

Для выхода следует ввести комбинацию ctrl + ] ] ]

Далее перейдем к настройке конфигурационных файлов .nspawn.
Поиск файлов конфигурации осуществляется путем добавления суффикса .nspawn к имени машины контейнера, указанному с помощью параметра  --machine=  команды systemd-nspawn, или полученному из имени каталога ([container-name]), или файла образа. Этот файл сначала ищется в /etc/systemd/nspawn/ и /run/systemd/nspawn/. Если файла там нет, то он будет искаться рядом с файлом образа или в родителе каталога контейнера.
Доверенные файлы настройки помещаются в /etc/systemd/nspawn, а потенциально опасные в /var/lib/machines/ (рядом с образами контейнеров), где их влияние на безопасность ограничено (все настройки, которые могут повышать привилегии или предоставлять дополнительный доступ к ресурсам хоста, игнорируются).

Systemd-nspawn устанавливает контейнеру права доступа только для чтения к интерфейсам ядра, таким как /sys/, /proc/sys/ или /sys/fs/selinux/, тем самым ограничивая влияние контейнера на ядро.
Создадим файл конфигурации /etc/systemd/nspawn/my_first_container.nspawn
mkdir /etc/systemd/nspawn
nano my_first_container.nspawn

Файл конфигурации является юнитом systemd, так что синтаксис будет таким

[Секция]
Параметр = значение
Простейшей конфигурация представлена ниже 

Пример секции

В секции [Exec] параметр Boot сообщает процессу, что должна быть вызвана программа init и вызываться она должна как PID 1, вместо оболочки или программы, установленной пользователем.
В секции [Network] параметр Bridge ожидает от нас название сетевого моста (перед этим его нужно создать - команды приведены ниже)
Создаем мост, назначаем ему ip-адрес и включаем его
brctl addbr con_bridge
ip a a 192.168.10.5 dev con_bridge
ifconfig con_bridge up

Назначаем ip-адрес и поднимаем интерфейс в контейнеры 
ifconfig host0 up
ip a a 10.0.109.35/24 dev host0

Параметры VirthualEthernet и Private необходимы для функционирования виртуальных интерфейсов.
На рисунке приведена настройка сети в контейнере, как мы видим автоматически назначается интерфейс host0 для взаимодействия  с хост-машиной 

Настройка сети в контейнере

На хост машине создается виртуальный интерфейс vb-[container-name], который связан с сетевым мостом con-bridge

Создан виртуальный интерфейс

Можем убедиться в сетевом взаимодействии:

Сетевое взаимодействие

Как мы видим, теперь контейнер может взаимодействовать с хостом по сети 

Утилита machinectl предназначена для удобного управления контейнерами 

machinectl start [container-name]
С помощью этой команды контейнер запускается как служба

machinectl enable [container-name]
Контейнер будет запускаться при запуске хоста

machinectl list
Отображает запущенные контейнеры 

machinectl shell [container-name]
Позволяет запустить шел в контейнере


machinectl login [user] [container-name]
Позволяет войти в контейнер под учетной записью которая присутствует в контейнере 

Далее настройка зависит от назначения контейнера и Systemd-nspawn предоставляет гибкую настройку контейнеров:

  • Ограничение ресурсов выделяемых контейнеру
  • Присутствует поддержка подсистемы безопасности SELinix
  • Snapshot и temporary snapshot
  • Volatile mode

Подробнее обо всех возможностях можно узнать из документации https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html 

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

Контейнеры:

  • LXC
  • Rocket
  • Firecracker
  • Sysbox

Гипервизоры:

  • Docker
  • LXD
  • OpenVZ
  • Containerd

Контейнеры нашли применение в песочницах, приведу несколько решений:

  • Firejail
  • NSJail
  • Snappy
  • Subuser

Спасибо за внимание, интересующие вас вопросы задавайте в комментариях.