Статья 2 из 10, в которой речь пойдёт об LXC и создании второго контейнера, используя другие шаблоны и параметры.
В статье LXC 1.0: Первый Ubuntu контейнер легко и просто создали первый контейнер p1 с помощью шаблона по умолчанию ubuntu. Но LXC поддерживает больше систем, чем просто Ubuntu. На данный момент поддерживаются Alpine Linux, Alt Linux, Arch Linux, busybox, CentOS, Cirros, Debian, Fedora, OpenMandriva, OpenSUSE, Oracle, Plamo, sshd, Ubuntu Cloud и Ubuntu.
Шаблоны можно найти в /usr/share/lxc/templates. Все шаблоны обладают дополнительными опциями, которые можно узнать по ключу --help после вызова lxc-create. Только нужно применять -- , чтобы разделять опции lxc-create и опции шаблона.
Написание дополнительных шаблонов несложно. Это просто исполняемые файлы, часто, но не обязательно, это shell скрипты, которые понимают набор стандартных аргументов и выполняют rootfs в нужном пути.
В связи с недостающими инструментами не все дистрибутивы Linux могут самозагружать (Bootstrapping) любой дистрибутив. Разработчики LXC заинтересованы в улучшении ситуации, даже если используются странные трюки как в Fedora. Если есть не работающая комбинация хост + гость, то патчи приветствуются!
Но хватит болтать, давайте двигаться дальше.
sudo lxc-create -t oracle -n p2 -- -a i386
Но скорее всего установка провалится, так как нет rpm и yum. Установите их и попробуйте снова. После установки нужных пакетов rpm и после создания контейнера, можно запустить его:
sudo lxc-start -n p2
Приглашение в систему просто просит ввести - логин root и пароль root.
Контейнер запущен без ключа -d поэтому для возврата в хост-shell придётся завершить работу контейнера. Нельзя отсоединиться (detach) от контейнера, который был запущен не в фоне с ключом -d.
Теперь стоит задаться вопросом - почему два шаблона Убунту? Обычный шаблон ubuntu, который использовался до сих пор, создавал контейнер "линукс с нуля" через debootstrap. Шаблон ubuntu-cloud скачивает подготовленный облачный образ и запускает его. Образ включает в себя cloud-init и поддерживает стандартные облачные метаданные.
Какой шаблон лучше использовать - дело вкуса. Шаблон ubuntu может быстро работать, если репозитория расположены на быстрых локальных зеркалах. И главное, что шаблоны используют кэш. Для данной архитектуры первоначальное создание контейнера может быть медленным, но последующие будут использовать локальную копию из кэша и всё будет происходить быстрее.
Как сделать, чтобы контейнер автоматически стартовал при загрузке хоста? Долгое время в Убунту и других дистрибутивах использовались init скрипты и симлинки в /etc/, но совсем недавно была реализована автозагрузка в upstream'е.
Как реализована сейчас автозагрузка контейнера? Каждый контейнер описывается своим конфигурационным файлом в /var/lib/lxc/имя-контейнера/config, в котором можно видеть строки
ключ = значение
Все значения можно прочесть в lxc.conf(5).
Значения, связанные с автостартом контейнера:
Когда стартует хост-машина, init скрипт lxc-autostart запустит все контейнеры, у которых не указана группа, в правильном порядке и через определённое ими время, но в конфиге контейнера указано lxc.start.auto=1.
Чтобы показать работу механизма автостарта. Поправим /var/lib/lxc/p1/config и внесём:
lxc.start.auto = 1
lxc.group = ubuntu
В /var/lib/lxc/p2/config внесём:
lxc.start.auto = 1
lxc.start.delay = 5
lxc.start.order = 100
После перезагрузки хост-машины, только контейнер p2 стартанёт автоматически, так как он указан без группы. lxc.start.order не играет сейчас никакой роли, так как стартующий контейнер сейчас один, но будет 5 секундная задержка перед стартом p2.
Можно проверить, какие контейнеры автоматически стартуют, с помощью sudo lxc-ls --fancy
NAME STATE IPV4 IPV6 AUTOSTART --------------------------------------------------------------------------------- p1 RUNNING 10.0.3.128 2607:f2c0:f00f:2751:216:3eff:feb1:4c7f YES (ubuntu) p2 RUNNING 10.0.3.165 2607:f2c0:f00f:2751:216:3eff:fe3a:f1c1 YES
Можно с консоли управлять контейнерами, используя lxc-autostart и параметры start, stop, kill, reboot для любого контейнера, имеющего в его конфиге lxc.start.auto=1.
Для примера, команда sudo lxc-autostart -a
запустит все контейнеры, имеющие lxc.start.auto=1, игнорируя значение lxc.group. В нашем случае с двумя контейнерами p1 и p2, сначала произойдёт запуск контейнера p2, из-за его приоритета order=100, но с задержкой в 5 секунд. Потом стартанёт p1.
Если нужно перезагрузить все контейнеры из группы Ubuntu, а у нас в примере это только p1, то командуем sudo lxc-autostart -r -g ubuntu
Ключ -L позволит увидеть какие контейнеры это затронет и как будет происходить автозапуск, но в реальности ничего не будет выполнено, что удобно при отладке.
Иногда контейнер активно не используется, а его периодический старт и выключение занимают определённое время. Есть возможность вместо выключения/включения контейнера использовать заморозку.
sudo lxc-freeze -n имя-контейнера
замораживает все процессы в контейнере, так что они не тратят такты, отведённые им планировщиком. Однако процессы продолжают существовать и потреблять ОЗУ.
sudo lxc-unfreeze -n имя-контейнера
позволит разморозить процессы в нужном вам контейнере.
По умолчанию в Ubuntu выделяется по одному veth устройству на контейнер, который соединён в сетевой мост с lxcbr0 на хосте и на нём запущен dnsmasq dhcp сервер.
Такой схемы обычно хватает большинству, но можно реализовать и более сложное, если это необходимо. Например, несколько сетевых интерфейсов внутри контейнера или проброс физического сетевого интерфейса хоста прямиком в контейнер.
Все сетевые возможности LXC можно узнать в lxc.conf(5), но один пример можно привести.
lxc.network.type = veth
lxc.network.hwaddr = 00:16:3e:3a:f1:c1
lxc.network.flags = up
lxc.network.link = lxcbr0
lxc.network.name = eth0
lxc.network.type = veth
lxc.network.link = virbr0
lxc.network.name = virt0
lxc.network.type = phys
lxc.network.link = eth2
lxc.network.name = eth1
Контейнер будет иметь 3 интерфейса:
Последние 2 интерфейса не имеют MAC адреса и сетевых флагов (network.flags), поэтому они будут получать при загрузке данного контейнера всегда разные MAC адреса и данные интерфейсы нужно самим поднимать после старта контейнера.
При условии, что используется ядро 3.8 и выше, можно использовать инструмент lxc-attach. Его основной задачей является дать shell внутри запущенного контейнера: sudo lxc-attach -n p1
Можно сразу выполнять команду в контейнере, используя sudo lxc-attach -n p1 -- restart ssh
Более опасный и мощный приём - sudo lxc-attach -n p1 -e -s 'NETWORK|UTSNAME'
.
Где,
-e, --elevated-privileges - не сбрасывать привилегии, перед запуском команды внутри контейнера. Нужно применять с осторожностью.
-s, --namespaces - указать пространства имён, к которым нужно подсоединиться. Разрешены MOUNT, PID, UTSNAME, IPC, USER и NETWORK.
Мы получим shell, говорящий нам root@p1, благодаря UTSNAME. Выполнив ifconfig -a, получим список сетевых интерфейсов контейнера. НО все остальные команды будут "от хоста". Ключ -e не даст ограничениям cgroup, apparmor применяться к любым процессам внутри данного shell. Чем это и опасно! Но время от времени, может быть полезным для запуска программ, расположенных в хост системе, но внутри контейнера с его сетью и пространством имён PID.
Вход в контейнер, запуск программ и выход из контейнера это всё замечательно, но что насчёт доступа к устройствам, подключённым к хосту?
По умолчанию, LXC пресекает такой доступ, используя devices cgroup как фильтрующий механизм. Можно изменить конфигурацию контейнера, разрешив доступ к нужным устройствам и перезапустить контейнер.
Но для разовых вещей есть удобный инструмент lxc-device. Для примера, sudo lxc-device add -n p1 /dev/ttyUSB0 /dev/ttyS0
добавит (mknod) /dev/ttyS0 в контейнер с тем же типом, старшим (major), младшим (minor) числами под именем /dev/ttyUSB0 и добавит разрешающие записи cgroup.
Предыдущая статья LXC 1.0: Первый Ubuntu контейнер.
Следующая статья LXC 1.0: Продвинутое использование контейнера.
Дополнительные материалы:
Серия статей LXC 1.0. от Стефана Грабера.
LXC и Vagrant. 13 причин использовать Ubuntu Server. Часть 3.
Вход в систему Unity Greeter может аутентифицировать в системе, находящейся в LXC контейнере.