
Во-первых, взгромоздить кучу виртуальных машин прямо на свой ноутбук.
А во-вторых, раскурить одну виртуализацию внутри другой.
Речь пойдет про использование контейнеров LXC, причем внутри другой виртуальной машины.
WTF! На кой это нужно?
Прежде всего, для экспериментов с различными инструментами:
- Распределенные базы данных, файловые системы, параллельные вычисления и т.д.
- Системы управления инфраструктурой (типа Chef, Puppet, Fabric и т.п.)
- Тестирование и сборка в разных окружениях
- Ваш вариант (пишите в комментариях)
При этом хочется иметь доступ к этой лаборатории всегда, вне зависимости от доступности интернета. Ну почему бы где-нибудь в дороге не раскурить какой-нибудь Hadoop? :-)
Думаю, эта заметка будет полезна как тем, у кого на десктопе Windows или Mac OS X, так и тем, у кого Linux (часть про LXC).
Задача
Запустить на среднем ноутбуке 10-20 виртуальных машин, которые
– могут ходить в интернет (через NAT)
– видят друг друга и хост-компьютер (то есть, наш ноут)
– доступны с хост-компьютера (то есть по ssh можно зайти на любую из этих виртуальных машин)
Решение
- На компьютере (с Windows или Mac OS X) запустить VirtualBox
- Установить на нем Linux
- Внутри Linux-а наделать кучу LXC-контейнеров с независимыми Linux-ами
Собственно, на этом можно было бы поставить точку.
Ниже приведена просто пошаговая шпаргалка (использовался Ubuntu), как все это настроить быстро.
1. Устанавливаем VirtualBox и систему на виртуальную машину
Здесь особо и описывать нечего.
После установки системы — не забыть поставить Guest Additions.
2. Настраиваем сетевые интерфейсы в VirtualBox
У виртуальной машины должно быть два сетевых интерфейса:
- Тип подключения NAT (он создается по умолчанию). Через него наши виртуалки смогут ходить в интернет (например, чтобы скачивать пакеты).
- Тип подключения Host-only networking (по-русски это называется «Виртуальный адаптер хоста»).
Важно! Нужно разрешить «Promiscuous mode» («Неразборчивый режим») на Host-only интерфейсе. Это позволит контейнерам видеть хост-машину и друг друга.

3. Настраиваем сетевые интерфейсы
В гостевой системе нужно сконфигурировать bridge-интерфейсы. Они нам потребуются для работы сети в контейнерах. Для этого нужно установить пакет bridge-utils (
# apt-get install bridge-utils
) и внести изменения в файл /etc/network/interfaces (см. man bridge-utils-interfaces).Должно получиться что-то похожее:
Было | Стало |
---|---|
auto eth0 iface eth0 inet dhcp |
auto br0 iface br0 inet dhcp bridge_ports eth0 bridge_fd 0 auto br1 iface br1 inet static address 192.168.56.2 netmask 255.255.255.0 bridge_ports eth1 bridge_fd 0 |
Перезапускаем виртуальную машину чтобы убедиться, что оба интерфейса внутри виртуальной машины поднимаются, сама виртуальная машина доступна по адресу 192.168.56.2 (через Host-only интерфейс) и внутри неё доступен интернет (через NAT-интерфейс).
4. Монтируем файловую систему cgroup
Для работы LXC-контейнеров нужна служебная файловая система cgroup. Точка монтирования не важна - можно смонтировать куда угодно.
Добавляем строчку в /etc/fstab:
cgroup /var/local/cgroup cgroup defaults 0 0
и монтируем
mkdir /var/local/cgroup
mount cgroup
В Ubuntu 11.10 (oneiric) cgroup руками монтировать не нужно. Пакет lxc зависит от пакета cgroup-lite, который монтирует cgroup в /sys/fs/cgroup/ |
5. Устанавливаем пакеты для работы с LXC
apt-get install lxc
apt-get install debootstrap
Пакет lxc содержит утилиты для управления и скрипты для создания контейнеров. Пакет debootstrap — это утилита, которая скачивает нужные пакеты и разворачивает минимальную базовую систему (ubuntu или debian). Кроме того, есть пакет febootstrap — он скачивает и разворачивает Fedora.
Самый быстрый способ изучить lxc: набрать lxc- и нажать два раза "Tab" |
6. Создаем первый LXC-контейнер
В каталоге /usr/lib/lxc/templates/ есть файлы вида
lxc-debian
, lxc-natty, lxc-oneiric
, lxc-fedora
и т.п. Это так называемые «шаблоны». На самом деле это скрипты, которые создают соответствующее рабочее окружение.Создаем контейнер (c Ubuntu 11.04)
lxc-create -n node01 -t natty
Наш контейнер появится в каталоге /var/lib/lxc/node01/.
Во создаваемом окружении у пользователя root пароль "root". Не забудьте поменять!
В Ubuntu 11.10 (oneiric) пакет lxc посвежее: шаблону "ubuntu" можно передать параметры, в том числе желаемую версию дистрибутива. Чтобы узнать, какие параметры принимает шаблон, выполните lxc-create --template ubuntu --help |
7. Настраиваем сеть в контейнере
7.1. Сетевые интерфейсы
В конфигурационном файле контейнера не хватает параметров сети – их нужно добавить руками. Потом можно будет использовать шаблонный конфиг или просто клонировать контейнер.
Открываем файл
vi /var/lib/lxc/node01/config
и добавляем такие строчки (ставим нужные нам MAC- и IP-адреса):
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0 <- это реальный интерфейс
lxc.network.name = eth0 <- это интерфейс внутри контейнера
lxc.network.hwaddr = ac:de:48:00:00:01
lxc.network.ipv4 = 10.0.2.101/24
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br1
lxc.network.name = eth1
lxc.network.hwaddr = ac:de:48:00:ff:01
lxc.network.ipv4 = 192.168.56.101/24
Здесь
10.0.2.101/24
– это сеть, которая обычно используется для NAT-интерфейсов в VirtualBox. Через этот интерфейс контейнер будет выходить в интернет.192.168.56.101/24
– это наша Host-Only сеть. Через этот интерфейс контейнер будет общаться с локальной сетью и другими контейнерами.Рекомендую устанавливать MAC-адрес и IP-адрес вручную. Это делать не обязательно, но удобно. Например, когда нужно послушать сетевой трафик. Я во всех номерах ставлю одинаковую последнюю цифру (node01 – 10.0.2.101 – ac:de:48:00:00:01).
Обратите внимание, файл конфигурации интерфейсов /etc/network/interfaces внутри контейнера не нужно трогать. Интерфейсы достаточно настроить снаружи.
7.2. DNS в контейнере
Добавляем что-нибудь осмысленное в /etc/resolv.conf, чтобы заработал DNS:
echo "nameserver 8.8.8.8" > /var/lib/lxc/node01/rootfs/etc/resolv.conf
Для локального разрешения адресов можно обойтись /etc/hosts. Файл /etc/hosts можно сделать общим для всех контейнеров, если смонтировать его с опцией bind.8. Запускаем и проверяем контейнер
Запускаем контейнер
lxc-start --logfile /tmp/lxc-node01.log --logpriority DEBUG --name node01
Заходим (root/root) и проверяем, что сеть доступна во все стороны.
Чтобы запустить контейнер в фоновом режиме надо добавить ключ "--daemon" |
9. Клонируем контейнеры
Для клонирования контейнеров достаточно скопировать его целиком
cp -a node01 node02
и поправить конфигурационные файлы (пути, MAC- и IP-адреса):
vi node02/config
vi node02/fstab
vi node02/rootfs/etc/hostname
Начиная с версии lxc 0.7.5 появилась утилита lxc-clone. Она корректно правит пути и hostname, но IP-адреса все равно нужно отредактировать руками |
10. Автозапуск контейнеров
В пакет lxc входит скрипт /etc/init.d/lxc, который запускает определенные контейнеры при старте системы. В файле /etc/default/lxc нужно перечислить, какие контейнеры запускать. Этот скрипт ожидает, что конфигурационные файлы контейнеров лежат в /etc/lxc и имеют расширение *.conf.
Я просто наделал симлинков:
/var/lib/lxc/nodeXX/config -> /etc/lxc/nodeXX.conf
11. Как еще можно облагородить эту кухню
- Написать скрипты, которые автоматизируют рутину по созданию контейнеров (шаблонный конфиг, установка IP-адресов, создание пользователей, настройка ssh по ключам и т.п.)
- Установить прокси apt-cacher-ng, чтобы не качать одни и те же пакеты по нескольку раз
- Смонтировать каталоги и файлы (с помощью опции bind), так чтобы некоторые файлы были общими
- Поставить контейнеры под управление libvirt (Я не пробовал. Возможно, это тема для отдельной заметки)
- Попробовать aufs для запуска “наложенных” (overlay) контейнеров, когда неизменяемые файлы могут быть общими для всех контейнеров (а также утилиту lxc-start-ephemeral).