Виртуализация с использованием jail во FreeBSD

Виртуализация — очень полезная штука, когда надо поле для экспериментов, нет физических серверов и поломать рабочий сервер ой как не хочется. Для этих целей вполне можно использовать JAIL — средство виртуализации во FreeBSD, когда внутри одного физического сервера, создаются ещё виртуальные FreeBSD, внутри которых можно экспериментировать и это не повлияет на основную ОС. Выполнив всё, как в статье ниже, мы создадим виртуальную машинку с FreeBSD на борту, в которой можно будет устанавливать любой софт из портов, как это происходит на обычном физическом сервере. Приступим.

Создаём переменную www.srv01.ru (имя, на самом деле, произвольное) окружению /mnt/pools/dsk02/jails/srv01 (Это директория, где у меня будет храниться виртуальная машина. Исправьте на вашу.). Использовать точки в директориях не советую, тоесть для примера не используйте www.server.com, а пишите просто server
setenv srv01 /mnt/pools/dsk02/jails/srv01

если создали не правильно окружение, удалить можно так:
unsetenv srv01

создаём эту директорию:
mkdir -p $srv01

создаём мир в jail’е:
cd /usr/src
make buildworld

Мне выдало:
===> games/fortune/strfile (obj,depend,all,install)
cd: can’t cd to /usr/src/games/fortune/strfile
*** Error code 2
Stop in /usr/src.
*** Error code 1
Stop in /usr/src.
*** Error code 1
Stop in /usr/src.

Такая ошибка вышла скорее всего из-за того, что я при установке FreeBSD не ставил исходники игр. Здесь 2-а пути решения:
1) В /etc/make.conf добавить строку:
NO_GAMES=
тоесть отказаться от исходников игр или

2) Обновится через cvsup.
Пойдём правильным путём — тоесть обновимся через cvsup.
ee /usr/src/stable-supfile

туда вписываем:
*default host=cvsup5.ru.freebsd.org
*default base=/var/db
*default prefix=/usr
*default release=cvs tag=RELENG_8_2
*default delete use-rel-suffix
*default compress
src-all

Здесь не забываем поменять tag=RELENG_8_2 на актуальную в данное время стабильную версию FreeBSD.

Далее:
cd /usr/src/

И обновляемся:
csup -g -L 2 stable-supfile

ждём пока обновится и повторяем:
make buildworld

долго собирается. По окончании увидим:
--------------------------------------------------------------
>>> World build completed on Sat Jun 11 18:14:34 MSD 2011
--------------------------------------------------------------

Далее:
make installworld DESTDIR=$srv01
make distribution DESTDIR=$srv01
mount -t devfs devfs $srv01/dev

Физические интерфейсы у меня:
ifconfig

re0: flags=8843 metric 0 mtu 1500
options=389b
ether 00:21:91:0b:74:59
inet 10.36.1.9 netmask 0xffffff00 broadcast 10.36.1.255
media: Ethernet autoselect (1000baseT )
status: active
plip0: flags=8810
metric 0 mtu 1500
lo0: flags=8049 metric 0 mtu 16384
options=3
inet 127.0.0.1 netmask 0xff000000

10.36.1.9 — ip физического сервера, на котором всё и разворачиваем.

Редактируем /etc/rc.conf, дописав:
#Параметры для всех jail:
#Автостарт jail
jail_enable="YES"
#Физический сетевой интерфейс(см командой ifconfig)
jail_interface="re0"
#devfs и procfs монтируем
jail_devfs_enable="YES"
jail_procfs_enable="YES"
#Разрешаем root'у клетки менять имя хоста
jail_set_hostname_allow="YES"

#В примере мы запускаем только одну клетку - srv01
#Если надо больше, то перечисляем их через запятую
#Например:
#jail_list="srv01,srv02,srv03"
#jail_srv01_hostname="www.srv01.ru"
#jail_srv02_hostname="www.srv02.ru"
#jail_srv03_hostname="www.srv03.ru"
#jail_srv01_ip="10.36.1.11"
#jail_srv02_ip="10.36.1.12"
#jail_srv03_ip="10.36.1.13"
#jail_srv01_rootdir="/dir/jail/10.36.1.11"
#jail_srv02_rootdir="/dir/jail/10.36.1.12"
#jail_srv03_rootdir="/dir/jail/10.36.1.13"

jail_list="srv01"

#Параметры клетки srv01
#Корень(/) для srv01
jail_srv01_rootdir="/mnt/pools/dsk02/jails/srv01"
#Имя хоста
jail_srv01_hostname="www.srv01.ru"
#IP хоста
jail_srv01_ip="10.36.1.11"
#Имя интерфейса
#jail_srv01_interface="re0"
#Монтировать devfs и procfs
jail_srv01_devfs_enable="YES"
jail_srv01_procfs_enable="YES"

jail_srv01_exec_start="/bin/sh /etc/rc"
jail_srv01_exec_stop="/bin/sh /etc/rc.shutdown"
jail_srv01_flags="-l -U root"

#Ещё вписываем туда же алиас c IP созданной клетки
ifconfig_re0_alias0="inet 10.36.1.11 netmask 255.255.255.0"

Далее выполняем, чтобы создать fstab в клетке:
touch /mnt/pools/dsk02/jails/srv01/etc/fstab

Побеспокоимся о ДНС:
ee /mnt/pools/dsk02/jails/srv01/etc/resolv.conf

вписываем dns-сервера, например (IP DNS-Сервера google):
nameserver 8.8.8.8

ещё создаём:
ee /mnt/pools/dsk02/jails/srv01/etc/rc.conf

с таким содержимым:
hostname="www.srv01.ru"
network_interfaces=""
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
sshd_enable="YES"

После этого в клетке будет запускаться ssh.

Для старта всех клеток, запускаем:
/etc/rc.d/jail start

для остановки соответственно:
/etc/rc.d/jail stop

Если надо запустить определённую клетку, то:
/etc/rc.d/jail start srv01

для остановки:
/etc/rc.d/jail stop srv01

Примечание 1:
клетка активируется, но при попытке подключиться по ssh на 10.36.1.11 мы попадаем на хост-машину, а не в jail.
Нам надо явным образом указать на хост-машине, на каком адресе слушать запрос ssh.

1) Если вы большой приверженец inetd.conf, то в /etc/rc.conf дописываем:
inetd_flags="-wW -a 10.36.1.9"

2) (Я делал этим способом) Если ssh запускается через inetd.conf , а желательно через /etc/rc.conf то закомментируем следующую строку в /etc/inetd.conf :
ssh stream tcp nowait root /usr/sbin/sshd sshd -i -4

А в /etc/rc.conf добавляем строку:
sshd_enable="YES"

запускаем sshd:
/etc/rc.d/sshd start

Перезапускаем inetd, чтобы отключить там ssh:
/etc/rc.d/inetd restart

Теперь при:
ps ax | grep ssh

увидим:
32351 ?? Is 0:00.03 sshd: administrator [priv] (sshd)
32355 ?? S 0:06.81 sshd: administrator@pts/0 (sshd)
89080 ?? Is 0:00.03 sshd: administrator [priv] (sshd)
89083 ?? I 0:00.01 sshd: administrator@pts/3 (sshd)
90744 ?? Is 0:00.00 /usr/sbin/sshd
90775 2 S+ 0:00.00 grep ssh

где
/usr/sbin/sshd — и есть запущенный демон ssh
В принципе, чтоб наверняка проверить, что мы теперь используем демон ssh, а не запускаем его супер-сервером inetd, можно перезагрузит сервер и вновь зайти на него по ssh. Если пускает, то всё в порядке.

Если ssh у вас и так запускался через /etc/rc.conf, то пропускаем Примечание 1 и идём дальше.

На хост-машине редактируем /etc/ssh/sshd_config , дописав туда:
ListenAddress 10.36.1.9

чтобы ssh слушался только на адресе 10.36.1.9 хост-машины и при попытке зайти на 10.36.1.11 мы попадали в клетку srv01.
перезапускаем sshd:
/etc/rc.d/sshd restart

Теперь можно заходить на 10.36.1.11 по ssh, но встаёт вопрос:»под каким пользователем?». Ни пользователя не создано, ни пароля root’a.

Зайти в созданную клетку можно не только по ssh на отдельный IP.
1) Сначала посмотреть список запущенных клеток:
jls
JID IP Address Hostname Path
4 10.36.1.11 www.srv01.ru /mnt/pools/dsk02/jails/srv01

и подключиться к нужной (в моём случае она одна):
jexec 4 tcsh
где
4 — JID клетки.

2) (Я делал этим способом) А можно выполнить команду не заходя в клетку. Обьясню на примере добавления пользователя в srv01.
jexec 4 adduser
здесь:
jexec — необходимая нам утилита
4 — JID клетки
adduser — команда добавления пользователя

итак выполняем команду для добавления пользователя:
jexec 4 adduser

отвечаем на попутные вопросы:
Username: administrator
Full name: administrator
Uid (Leave empty for default):
Login group [administrator]:
Login group is administrator. Invite administrator into other groups? []: wheel
Login class [default]:
Shell (sh csh tcsh nologin) [sh]:
Home directory [/home/administrator]:
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Enter password: вписываем_пароль
Enter password again: вписываем_пароль_повторно
Lock out the account after creation? [no]:
Username : administrator
Password : *****
Full Name : administrator
Uid : 1001
Class :
Groups : administrator wheel
Home : /home/administrator
Home Mode :
Shell : /bin/sh
Locked : no
OK? (yes/no): yes
adduser: INFO: Successfully added (administrator) to the user database.
Add another user? (yes/no): no
Goodbye!

и получаем нользователя «administrator» в клетке srv01, можно заходить по ssh:
ssh administrator@10.36.1.11 -p 22
вписываем пароль и попадаем в изоляцию.

набрав:
su -l
становимся суперпользователем.

Сразу меняем пароль суперпользователя:
passwd
Changing local password for root
New Password: вписываем_пароль
Retype New Password: вписываем_пароль_повторно

Примечание 2
Если что то не правильно создали, то даже остановив jail, удалить директорию srv01 вы не сможете.
Надо будет выполнить:
chflags -R noschg /mnt/pools/dsk02/jails/srv01/
rm -rf /mnt/pools/dsk02/jails/srv01/

Далее, чтобы не обновлять порты на каждой из виртуальных FreeBSD, мы примонтируем дерево портов хост-машины к машине srv01. Таким образом, достаточно будет обновлять только одно дерево.

На основной системе обновляем дерево портов:
cd /usr/src
ee /usr/src/ports-supfile

туда вписываем:
*default host=cvsup5.ru.freebsd.org
*default base=/var/db
*default prefix=/usr
*default release=cvs tag=.
*default delete use-rel-suffix
*default compress
ports-all

выполняем обновлеие дерева портов:
csup -g -L 2 ports-supfile

и можем его примонтировать к Jail’у (выполняем на основной машине):
mkdir /mnt/pools/dsk02/jails/srv01/usr/ports
mount_nullfs /usr/ports /mnt/pools/dsk02/jails/srv01/usr/ports

Директория /mnt/pools/dsk02/jails/srv01/usr/ports у меня находится на zfs, которая стартует после fstab, поэтому записывать туда строчку для автомонтирования бесполезно — ОС хост-машины не загрузится.
Поэтому я вставил строку:
mount_nullfs /usr/ports /mnt/pools/dsk02/jails/srv01/usr/ports

в /etc/rc.d/jail:
#!/bin/sh
#
# $FreeBSD: src/etc/rc.d/jail,v 1.43.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $
#

# PROVIDE: jail
# REQUIRE: LOGIN cleanvar
# BEFORE: securelevel
# KEYWORD: nojail shutdown

mount_nullfs /usr/ports /mnt/pools/dsk02/jails/srv01/usr/ports

# WARNING: This script deals with untrusted data (the data and
# processes inside the jails) and care must be taken when changing the
# code related to this! If you have any doubt whether a change

весь листинг копи-пастить не буду, он без изменений.
Таким образом /usr/ports будет монтироваться автоматически в /mnt/pools/dsk02/jails/srv01/usr/ports после перезагрузки физического ПК, дерево портов одно для всех, а значит и следить за его актуальностью проще.

Далее делаем все необходимые настройки…ставим необходимое ПО из портов и т.д.

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