Обзор средств виртуализации и контейнеров в FreeBSD

BSD-системы всегда отличались консерватизмом, и в большинстве случаев это было им на пользу. Однако с аппаратной виртуализацией у них вышел промах — ее разработчики BSD-систем начали (и продолжают) внедрять позже всех остальных ОС. Относительно недавно вышла новая версия FreeBSD, в которой, в частности, заявлена улучшенная поддержка гипервизора bhyve и некоторые незначительные изменения в ПО контейнеризации Jail. Рассмотрим данные технологии подробнее.

Поддержка аппаратной виртуализации (в качестве хостовой системы) во FreeBSD появилась недавно — первое упоминание о bhyve встречается в новостях 2011 года. С одной стороны, в других ОС эта поддержка гораздо более зрела. С другой же — при разработке bhyve были учтены моменты, которые могли возникнуть, разрабатывайся он с нуля. Кроме того, чтобы не плодить сущности, в гостевых системах используется virtIO (как и в KVM и Xen).

А вот технология для создания контейнеров во FreeBSD существует с давних пор под названием Jail. В основе ее лежит группа системных вызовов (jail(), jail_get(), jail_set(), jail_remove() и jail_attach()). Вопреки распространенному мнению, в последних версиях FreeBSD они не вызывают chroot(), хотя и используют некоторые общие с данным системным вызовом процедуры. Из преимуществ Jail, помимо собственно изоляции, можно отметить также гибкое управление ресурсами с помощью RCTL (для включения данной функции, однако, требуется перекомпиляция ядра). Посмотрим, насколько удобно использовать данные технологии по сравнению с их аналогами из других ОС.

Установка FREEBSD НА BHYVE

Для использования данной системы виртуализации необходима версия FreeBSD не ниже 10 (а с процессором AMD — не ниже 11-CURRENT). Чтобы ее включить, нужно добавить следующие строки в файл boot/loader.conf:

После перезагрузки (или добавления данных модулей с помощью kldload) нужно создать бридж и интерфейс tap для поднятия сети в будущей виртуальной машине:

Затем объединяем tap0 и реальный интерфейс в бридж и запускаем его — в моем случае для этого потребовались следующие команды:

Создаем файл образа, куда будем ставить систему:

Затем либо качаем bootonly-образ, либо используем образ DVD, который ты применял при установке FreeBSD (файл устройства по неизвестным причинам для этих целей не подходит). Копируем скрипт, облегчающий запуск виртуальной машины, и редактируем в нем нужные параметры:

Скрипт довольно большой и делает следующее:

1. Проверяет, является ли вызывающий пользователь привилегированным.

2. Проверяет, загружен ли модуль vmm.ko.

3. Смотрит задаваемые опции.

4. Проверяет, является ли файл жесткого диска загрузочным образом.

5. Наконец, загружает с помощью bhyveload ядро FreeBSD и передает ему управление через bhyve.

О последнем этапе стоит рассказать подробнее. Поскольку bhyve пока не поддерживает ни BIOS, ни UEFI, а инициализировать виртуальное оборудование все же необходимо, для этого был сделан модифицированный загрузчик для FreeBSD. Аналогично есть и bhyve-модифицированный GRUB 2, служащий для загрузки иных систем. Но вот ты его отредактировал. Теперь можно и запускать:

Устанавливаем стандартным образом. Для нормального завершения работы нужно перезагрузиться и в приглашении loader’а набрать quit. Вместо использования файла образа можно взять функцию ZFS под названием zvol. Прежде всего создадим этот самый zvol:

Устанавливаем FreeBSD обычным путем, указав вместо файла образа zvol (в моем случае — /dev/zvol/zroot/fbsd), а метод разбиения «ZFS – Automatic Root-on-ZFS». После установки для запуска вводим примерно следующие две команды (так как скрипт не всегда корректно работает):

И работаем как обычно.

Режим совместимости с LINUX

FreeBSD поддерживает частичную совместимость с Linux, что позволяет запускать некоторые Linux-приложения. Фактически режим совместимости представляет собой реализацию Linux ABI и системных вызовов. Для установки слоя совместимости нужно выполнить следующую команду:

Затем загрузить модуль, отвечающий за ABI и подмонтировать linprocfs:

Все. Можно использовать некоторые программы, написанные для Linux.

BHYVE: Установка LINUX

Для установки Linux потребуется установить grub2-bhyve:

Затем нужно скачать образ дистрибутива (я взял CentOS 7) и создать файл device.map и образ диска.

Содержимое device.map:

Запускаем grub-bhyve и набираем соответствующие команды для загрузки ядра:

Здесь нужно объяснить некоторые детали. Поскольку bhyve пока не поддерживает графический режим, нужно запустить установку в текстовом, для чего и передаем ядру параметр text. Кроме того, команда boot ядро, конечно, в память загружает — но управление не передает. Для передачи же управления используется следующая команда:

Разберем опции:

  • A — генерировать таблицы ACPI (в которых хранится, например, количество процессоров);
  • H — реализует инструкцию HLT в виртуальном CPU. Если эту опцию не указать, реальный процессор будет загружен на 100%;
  • P — приостанавливает VCPU по получении им инструкции PAUSE;
  • множество опций -s конфигурируют слоты PCI. После первой запятой указывается, какое устройство будет эмулироваться или пробрасываться. После второй указывается конфигурация для данного устройства — так, в примере выше для virtio-blk указан путь к образу. При необходимости для сетевого интерфейса таким же способом можно указать MAC-адрес;
  • l — предназначено для маппинга COM-портов;
  • c — количество виртуальных процессоров;
  • m — память.

Помимо указанных, есть еще и дополнительные опции:

  • C — включать память гостевой ОС в файлы дампа;
  • e — принудительно завершать работу bhyve, если гостевая ОС обращается к неэмулируемым портам ввода-вывода, — что полезно для целей отладки;
  • p vcpu:hostcpu — привязать указанный VCPU к CPU хостовой машины;
  • U uuid — уникальный идентификатор в структуре SMBIOS System Information. Если его не указать, генерируется на основе имени хоста хостовой системы и имени виртуальной машины;
  • w — игнорировать обращения к нереализованным регистрам MSR, что опять же полезно для отладки;
  • W- спользовать в эмулируемой системе старую систему прерываний (MSI) вместо более новой (MSI-X);
  • x — использовать в гостевой системе режим x2APIC;
  • Y — отключить генерацию MPTable.

После загрузки запустится Anaconda в самом что ни на есть текстовом режиме (даже без использования ncurses — просто черно-белый терминал, навевающий ностальгические мысли о временах DOS). Установка более чем стандартна. После ее завершения нас выбросит во FreeBSD — bhyve не умеет перезагружаться. Для дальнейшей работы нужно завершить работу bhyve, снова запустить grub-bhyve и вновь использовать ту же команду:

Выбираем нужный пункт и передаем управление командой bhyve с соответствующими опциями. Но что, если нужно подключаться к консоли и отключаться от нее? В этом случае можно использовать нуль-модемное устройство, для которого прежде всего необходимо загрузить модуль ядра nmdm:

Затем в опции -l указываем вместо stdio /dev/nmdm0A и подключаемся к нему:

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

Настройка JAIL

FreeBSD поддерживает также аналог LXC — Jail. Мы будем рассматривать его вкупе с ZFS. Создадим ФС:

Вторая команда создает сжатую ZFS, а третья — собственно ту ФС, куда мы будем его развертывать и откуда затем клонировать. Скачиваем файлы FreeBSD 10.1 и распаковываем их:

Сделаем некоторую базовую настройку (скопируем resolv.conf, поставим пароль, создадим каталог /usr/home и симлинк /home, установим обновления):

Создадим снапшот текущего «чистого» Jail.

Конфигурируем шаблон дальше. Создадим в Jail следующий файл — /etc/make.conf:

# Использовать PKFNG для сборки портов

# Делает возможным использование в Jail дерева портов хостовой системы (через проброс их с помощью mount)

# Количество одновременных потоков make

В файле /etc/rc.conf (в Jail) должно быть примерно следующее:
# Не запускаем sendmail

# Очищаем временные каталоги

# Syslog не будет принимать входящие подключения

# Выключаем RPCBIND

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

Здесь p0 — номер условного «патча».
На хостовой же системе создаем файл /etc/jail.conf следующего содержания:

# Глобальные параметры
# Действие, выполняемое перед запуском песочниц. В данном случае пробрасывается каталог /usr/ports хостовой системы. Обрати внимание — триггеры exec.prestart и exec.poststop выполняются на хостовой системе

# Скрипты в Jail, выполняемые во время запуска и остановки

# После остановки отмонтируем проброшенную файловую систему

# Сбрасываем в Jail почти все переменные окружения

# Монтируем в Jail devfs

# Файл в формате fstab, описывающий, какие ФС монтировать в Jail

# Запрещаем монтирование в самом Jail

# Параметры подстановки
# Путь к корню основан на имени Jail

# Тестовый Jail

# Устанавливаем имя хоста для Jail

# Включаем отдельный сетевой стек (требуется, чтобы ядро было скомпилировано с опцией VIMAGE)

Затем создаем на основе того снапшота, что был ранее сделан, клон:

И в /etc/rc.conf добавим строчку (если нужно, чтобы созданные Jail запускались автоматически):

Для запуска же определенного Jail вручную набираем команду:

где test — запускаемая песочница.
Чтобы запустить какую-нибудь программу в песочнице, используем следующие команды:

Первая команда показывает список запущенных песочниц, вторая же запускает в песочнице с указанным ID заданную программу. Останавливают их аналогично запуску, только вместо аргумента start пишем stop.

Тонкая настройка JAIL. Интересный особенности

Конфигурация, приведенная выше, конечно же, может использоваться и на практике. Тем не менее всех возможностей песочницы она не охватывает. Посмотрим, какие еще возможности имеются у данной технологии. Поскольку песочницы неразрывно связаны с ограничениями, соответственно, и разбирать будем данный функционал. Большинство параметров, настраиваемых в файле jail.conf, на самом деле являются параметрами sysctl (ветвь security.jail), поэтому описываемые ниже опции могут быть изменены также с помощью данной утилиты.

Параметр securelevel служит для ограничения securelevel в Jail. Отмечу, что значение данного параметра не может быть ниже, чем в хостовой системе (оно и понятно). Стоит напомнить, что ограничивает тот или иной уровень:

  • 0 — разрешено все; фактически это уровень по умолчанию;
  • 1 — запрещается изменение флагов файлов с помощью chflags, запись в файлы дисковых устройств (при смонтированных ФС) и в некоторые другие и загрузка модулей ядра (последнее, впрочем, в jail-окружении запрещено и так). Кроме того, запрещается вызов отладчика ядра;
  • 2 — помимо запретов предыдущего уровня, писать в файлы дисковых устройств может только системный вызов mount и запрещено изменять время больше, чем на секунду;
  • 3 — те же ограничения, что и на предыдущем, плюс запрет на изменение правил брандмауэра.

Параметр devfs_ruleset указывает, какой набор правил devfs будет применяться для контейнера. Везде пишут, что по умолчанию ни единого набора не применяется, — и при использовании команды /sbin/jail все верно. Однако в случае со стандартным скриптом запуска /etc/rc,d/jail это не так — применяется набор правил, заточенный специально для Jail и описанный в /etc/defaults/devfs.rules.

Во FreeBSD поддерживаются также вложенные контейнеры. Для их использования надо установить параметр children.max, указывающий максимальное количество вложенных контейнеров. По умолчанию он равен нулю, то есть вложенные контейнеры создавать запрещается. Текущее же количество потомков можно посмотреть в переменной children.cur.

С помощью параметра enforce_statfs можно управлять видимостью точек монтирования. При установке его в 0 процесс может получать информацию обо всех точках монтирования. При установке в 1 — только о точках монтирования в самой песочнице. Значение же по умолчанию, 2, и вовсе ограничивает информацию подмонтированным корнем.

Параметры, начинающиеся с префикса «allow.», булевы и в подробном описании не нуждаются. Упоминания стоит разве что allow.raw_sockets — без указания данного параметра некоторые утилиты, такие как ping, работать не будут. Кроме того, стоит отметить, что при добавлении префикса no после «allow.» значение параметра инвертируется.

К примеру, allow.nomount запрещает какое-либо монтирование. Это свойство имеет смысл, если в секции параметров для всех контейнеров действие разрешено, но для определенного его необходимо запретить. По умолчанию почти везде стоит запрет — исключение составляет лишь allow.set_hostname.
Если нужно поставить в Jail более старую версию FreeBSD, необходимо будет установить переменную UNAME_r соответствующе данной версии — в противном случае некоторые программы могут отказаться работать.

CBSD

Для облегчения создания Jail’ов можно использовать набор утилит CBSD — удобный фронтенд для работы с контейнерами, последние версии которого к тому
же поддерживают и bhyve. Его особенности:

  • наличие готового репозитория — что делает пересборку FreeBSD необязательной;
  • поддержка ZFS;
  • экспорт/импорт контейнеров;
  • утилита конфигурирования в стиле bsdinstall.

И многое другое. Для установки нужно выполнить следующую команду:

После этого нужно его инициализировать:

Скрипт задаст с десяток вопросов, после чего можно будет запускать утилиту jconstruct-tui:

Появится текстовое диалоговое окно, в котором нужно указать параметры вновь создаваемой песочницы, такие как имя, IP-адрес, версия FreeBSD… После создания можно использовать следующую команду для запуска Jail:

У данного ПО есть еще множество возможностей, которые мы здесь описывать не будем. В целом функционал аналогичен раннему Docker — но, конечно, проекту до него еще расти и расти.

Заключение

Технологии виртуализации во FreeBSD производят двойственное впечатление. С одной стороны, да, они есть, и с их помощью можно даже что-то запускать. С другой же… Не будем сильно критиковать bhyve — в конце концов, это относительно недавняя разработка. Но помилуйте — даже абсолютно текстовые варианты ОС (которыми, к слову, обладают только *nix-подобные, да и то не все) устанавливать исключительно с использованием эмулируемого нуль-модемного соединения крайне неудобно. Хотя бы по той причине, что на другую виртуальную консоль не переключишься — а зачастую там появляется полезная информация. Помимо того, опции самой команды bhyve предназначены скорее для внутреннего применения его разработчиков, чем для повседневного использования в качестве средства виртуализации.

В случае с Jail дела обстоят получше — но тоже несколько отстают от аналогичных технологий в Linux. Ярчайший пример этого — во FreeBSD, начиная с версии 7.0, поддерживается такая возможность, как privileges, аналогичная capabilities в Linux. Однако, несмотря на то что сама реализация системных вызовов, относящихся к Jail, в своем исходном коде ими оперирует, интерфейса, позволяющего администратору контейнеров определить, какие именно привилегии будут доступны суперпользователю того или иного контейнера, не существует.

Таким образом, технологии аппаратной виртуализации во FreeBSD еще недостаточно стабильны, а контейнеры (как бы они ни назывались) выглядят хоть и рабочими, но немного старомодными — что, справедливости ради, никак не мешает их использовать.

Рейтинг материала
[Голосов: 0 Рейтинг: 0]
25 декабря 2015, 14:50

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

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