LXC 1.0: Второй контейнер.
Статья 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).
Значения, связанные с автостартом контейнера:
- lxc.start.auto = 0 (выключено) или 1 (включено)
- lxc.start.delay = 0 (задержка в секундах до автостарта контейнера)
- lxc.start.order = 0 (приоритет контейнера, чем выше значение, тем раньше стартует контейнер)
- lxc.group = group1,group2,group3,… (членами каких групп является контейнер)
Когда стартует хост-машина, 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 интерфейса:
- eth0 (обычный veth) будет соединён в сетевой мост c lxcbr0.
- eth1 — это проброшенный физический интерфейс eth2 хоста. Когда контейнер стартанёт, eth2 исчезнет в хост-машине.
- virt0 ещё одно veth устройство, соединёное в мост с virbr0 хоста.
Последние 2 интерфейса не имеют MAC адреса и сетевых флагов (network.flags), поэтому они будут получать при загрузки данного контейнера всегда разные MAC адреса и данные интерфейсы нужно самим поднимать после старта контейнера.
Присоединение (Attach).
При условии, что используется ядро 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.
Дата последней правки: 2014-03-12 09:20:19
2 из 10, в которой речь пойдёт об LXC и создании второго контейнера, используя другие шаблоны и параметры. «>
LXC на SE 1.6
Есть SE 1.6, установлены все пакеты, требуемые для LXC. Настройки сети сделаны по мануалу. Возникло несколько вопросов:
1. При создании контейнера не находятся скрипты checkroot.sh, umountfs, hwclockfirst.sh, если с последним понятно (попытка действий со службами, которых нет), то про первые два непонятно почему так. Код ниже, в п.2.
2. При создании контенера не подтягивается sources.list корректно:
$ sudo lxc-create -t astralinux-se -n container-2 debootstrap является /usr/sbin/debootstrap Checking cache download in /var/cache/lxc/astra/rootfs-smolensk-amd64 . Copying rootfs to /var/lib/lxc/container-2/rootfs. Generating locales (this might take a while). en_US.UTF-8. done ru_RU.UTF-8. done Generation complete. update-rc.d: error: cannot find a LSB script for checkroot.sh update-rc.d: error: cannot find a LSB script for umountfs update-rc.d: error: cannot find a LSB script for hwclockfirst.sh Current default time zone: 'Etc/UTC' Local time is now: Thu Oct 17 08:39:09 UTC 2019. Universal Time is now: Thu Oct 17 08:39:09 UTC 2019. Пол:1 file:/mnt/iso smolensk InRelease Игн:1 file:/mnt/iso smolensk InRelease Пол:2 file:/mnt/iso2 smolensk InRelease Игн:2 file:/mnt/iso2 smolensk InRelease Пол:3 file:/mnt/iso smolensk Release Игн:3 file:/mnt/iso smolensk Release
Здесь нужно добавить, что репозиторий обоих дисков лежит на физически другой машине в виде iso и примонтирован в fstab по nfs. Конфиг sources.list:
deb file:///mnt/iso smolensk contrib main non-free deb file:///mnt/iso2 smolensk contrib main non-free
192.168.250.11:/mnt/iso /mnt/iso nfs,iso9660 user,noauto 0 0 192.168.250.11:/mnt/iso2 /mnt/iso2 nfs,iso9660 user,noauto 0 0
$ sudo apt-get update Пол:1 file:/mnt/iso smolensk InRelease Игн:1 file:/mnt/iso smolensk InRelease Пол:2 file:/mnt/iso2 smolensk InRelease [5 258 B] Пол:2 file:/mnt/iso2 smolensk InRelease [5 258 B] Пол:3 file:/mnt/iso smolensk Release [5 014 B] Пол:3 file:/mnt/iso smolensk Release [5 014 B] Чтение списков пакетов… Готово
/bin/bash: /usr/sbin/pdp-init-fs: Нет такого файла или каталога
$ sudo lxc-start -n container-2 lxc-start: monitor.c: lxc_monitor_open: 218 Failed to connect to monitor socket. Retrying in 10 ms. lxc-start: monitor.c: lxc_monitor_open: 218 Failed to connect to monitor socket. Retrying in 50 ms. lxc-start: monitor.c: lxc_monitor_open: 218 Failed to connect to monitor socket. Retrying in 100 ms. lxc-start: monitor.c: lxc_monitor_open: 223 Failed to connect to monitor socket: Connection refused. lxc-start: tools/lxc_start.c: main: 366 The container failed to start. lxc-start: tools/lxc_start.c: main: 368 To get more details, run the container in foreground mode. lxc-start: tools/lxc_start.c: main: 370 Additional information can be obtained by setting the --logfile and --logpriority options.
Полный вывод во вложении log.txt. Пакеты все установлены с дисков SE, сторонние репозитории не использовались.