FreeBSD Jails 101: краткое руководство по поднятию первой клетки

Дисклеймер: если у вас машина с FreeBSD стоит за отдельным роутером, который раздаёт IP-адреса, является маршрутизатором и всё такое — вам сюда. Я же описываю случай, когда сама машина с FreeBSD является роутером для клеток.


Собственно, условия разворачивания такие:

  • Хост является маршрутизатором и провайдером NAT-а для клеток. Внешний роутер отсутствует.
  • Клетки являются автономными и не имеют общих файловых систем. Это спорное решение для некоторых, и каждая клетка-сервис будет занимать 500 мегабайт на жёстком диске минимум, но при этом каждая клетка обновляется автономно. В данной установке принцип «понимать, что обновляешь» важнее автоматизации обновлений.
  • Хост установлен на root с ZFS. Староверы с U-word FS идут в хэндбук.
  • Всё происходит на FreeBSD 11.2-RELEASE.

Для начала добавляем в /etc/rc.conf следующие данные:

gateway_enable="YES"
cloned_interfaces="tap0"
ifconfig_tap0="inet 192.168.99.1 netmask 255.255.255.0"
jail_enable="YES"

Первая строка включает маршрутизацию на хосте, вторая добавляет колонизуемый интерфейс tap0, третья задаёт этому интерфейсу IP-адрес и маску подсети, ну а последняя включает сервис клеток.

Теперь создаём ZFS-датасет, в котором будут лежать все клетки (допустим, /usr/jails/):

zfs create -o compression=lz4 -o mountpoint=/usr/jails zroot/jails

Далее — создаём ZFS-датасет, в котором будет храниться наша шаблонная клетка. Таких шаблонных клеток можно создать несколько, в зависимости от необходимых задач. Внимание, если вы ещё не в курсе — клетки работают исключительно с FreeBSD!

zfs create -o compression=lz4 -o mountpoint=/usr/jails/11-2-amd64 zroot/jails/11-2-amd64

Здесь 11-2-amd64 — имя клетки. Оно может быть любым, в зависимости от ваших предпочтений. Здесь — имя по версии и архитектуре FreeBSD внутри шаблонной клетки.

Теперь можно скачать базовую установку для FreeBSD и распаковать её (поддержку lib32 и сборки из портов мы оставим за пределами данного руководства):

cd /usr/jails
fetch https://mirror.yandex.ru/freebsd/releases/amd64/11.2-RELEASE/base.txz
tar -xf base.txz -C /usr/jails/11-2-amd64

Следующий шаг — создание конфигурационного файла клеток /etc/jail.conf. Он достаточно стандартен:

exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
path = "/usr/jails/$name";
interface = "tap0";
allow.raw_sockets = 1;

# Шаблонная клетка. После настройки этот блок можно закомментировать.
11-2-amd64 {
    host.hostname = "template";
    ip4.addr = "tap0|192.168.99.250/24";
    allow.chflags = 1;
    allow.socket_af = 1;
}

Вверху — общие параметры для всех клеток. Они достаточно стандартны. Стоит обратить внимание на allow.raw_sockets = 1 — без этой опции ping, traceroute и половина прочих сетевых утилит работать не будет.

Далее идёт секция с индивидуальной настройкой нашей шаблонной клетки:

  • в первой строке задаётся хостнейм
  • во второй — адрес на интерфейсе tap0
  • в третьей — разрешается suid-бит для файлов внутри клетки (по умолчанию это запрещено, разрешать после настройки шаблона для других клеток необязательно)
  • в четвёртой — разрешаются любые сокеты для любых протоков (тоже запрещено по умолчанию, тоже после настройки скорее всего нафиг не будет нужно)

Если хочется изучить побольше опций, man jail.conf поможет (на английском языке).

Создаём клетку:

jail -c 11-2-amd64

Клетка запущена и готова к настройке. В процессе выполнения этой команды возможна ругань на «missing hostname»: игнорируем смело, в клетке всё будет нормально. Теперь мы можем войти в клетку:

jexec 11-2-amd64 sh

Единственное, что надо сделать на этом этапе — поднять ssh внутри клетки, что делается командой:

sshd_enable="YES"

По умолчанию рут-логин по ssh выключен. Или включите его, или создайте пользователя для входа.

Следующим шагом будет включение NAT для клеток. Воспользуемся PF для этого. Включаем его в rc.conf:

pf_enable="YES"
pf_rules="/etc/pf.conf"
pflog_enable="YES"
pflog_logfile="/var/log/pf.log"

Перед запуском напишем правила маршрутизации. Для простой конфигурации достаточно этого варианта:

ext_if="re0"
jails_if="tap0"
jails_nr="{192.168.99.0/24}"

nat on $ext_if from $jails_nr to any -> ($ext_if)

О том, как более-менее безопасно настроить PF, я расскажу в другой заметке. Перед включением файрвола обязательно выполните команду pfctl -vnf /etc/pf.conf и посмотрите её результат! После удовлетворения результатом выполняйте service pf start: в этот момент вас может выкинуть из SSH-сессии, это нормально.

После запуска файрвола можно или перезагрузиться, или сделать service jail restart 11-2-amd64, и после этого зайти на свою шаблонную клетку по SSH. Для того, чтобы увидеть, какой IP-адрес и хостнейм у каждой из запущенных в системе клеток сейчас есть, существует команда jls.

После настройки шаблонной клетки выключите (закомментируйте) её, перезагрузитесь, а затем выполните следующие магические пассажи:

# О ZFS, ты так хорош…
# создаём датасет для новой клетки, допустим, это будет storage
zfs create -o compression=lz4 -o mountpoint=/usr/jails/storage zroot/jails/storage
# Копируем шаблонную клетку в новую клетку.
zfs send zroot/jails/11-2-amd64 | zfs recv -F zroot/jails/storage

После копирования ФС создаём в файле конфигурации /etc/jail.conf секцию для новой клетки:

storage {
    host.hostname = "storage";
    ip4.addr = "tap0|192.168.99.25/24";
}

Командой service jail start storage теперь можно поднять новую клетку для настройки и установки своих сервисов.

По умолчанию при перезагрузке все клетки запускаются последовательно согласно порядку в /etc/jail.conf. Для того, чтобы это изменить, можно добавить в /etc/rc.conf следующую запись:

jail_list="mysql storage"

После чего все клетки, которые не указаны в этом списке, запускаться не будут, а все клетки в списке будут запускаться согласно порядку в нём: в данном случае первым запустится MySQL, а потом — storage.

Поделиться
Отправить
24 августа   FreeBSD   Инструкции
1 комментарий
d7w

О, Jail’ы. Ностальгия по FreeBSD. Боюсь сказать — я сделал по работе коммерческий хостинг на jail’ах лет десять назад, очень нравилась технология. Сейчас слабо актуальна из-за Docker для мейнстрима и LXC для приверженцев традициям.
«Не имеют общих файловых систем» — я решал проблему дубликации в то время с помощью unionfs. Наверное сейчас можно решить проблему дедубликацией на уровне zfs, но я давно не в теме и мне кажется, что для этого уровня нужно слишком много ресурсов. Плюс не знаю, работает ли это для раздельных датасетов.

Владимир Ходаков

Сейчас слабо актуальна из-за Docker для мейнстрима и LXC для приверженцев традициям.

Нахуй Докер. Блоатварь ещё та, особенно в связке с кубернетесами — уже успел нажраться этим -_- Для стандартных юзкейсов Докер норм, шаг влево, шаг вправо — всё идёт по пизде.

«Не имеют общих файловых систем» — я решал проблему дубликации в то время с помощью unionfs. Наверное сейчас можно решить проблему дедубликацией на уровне zfs, но я давно не в теме и мне кажется, что для этого уровня нужно слишком много ресурсов. Плюс не знаю, работает ли это для раздельных датасетов.

Я не считаю дубликацию проблемой. В моём сетапе каждая клетка по сути исполняет не запускалку одного бинаря, а целое окружение под приложение, и в этом окружении я хочу контролировать всё, включая момент, когда я буду обновлять базовую систему. А пару актуальных решений для дедупликации, ежели таковая нужна, содержит в себе FreeBSD Handbook уже.

Популярное