Expertus metuit
LXC в Debian
Опубликовано 2014-01-23 в 11:10

Инструкции по разворачиванию LXC на Debian-машине. Всё рассчитано на Debian Stable (Debian 12 Bookworm на момент написания статьи) и версию lxc 5.0.x.

LXC (LinuX Containers, http://linuxcontainers.org/) — это система виртуализации на уровне операционной системы, по сути нечто вроде продвинутого chroot. Удобно использовать для разработки и тестирования софта. Здесь рассматривается работа с lxc только средствами пакета lxc, а другие — например, через libvirt — нет.

Устанавливается стандартным образом в debian:

$ sudo apt install lxc

В Ubuntu (да, пакет называется lxc1):

$ sudo apt install lxc1

После установки проверяем:

$ sudo lxc-checkconfig
Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-4.19.0-5-amd64
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled

--- Control groups ---
Cgroups: enabled

Cgroup v1 mount points:
/sys/fs/cgroup/systemd
/sys/fs/cgroup/cpuset
/sys/fs/cgroup/cpu,cpuacct
/sys/fs/cgroup/freezer
/sys/fs/cgroup/blkio
/sys/fs/cgroup/pids
/sys/fs/cgroup/net_cls,net_prio
/sys/fs/cgroup/memory
/sys/fs/cgroup/devices
/sys/fs/cgroup/rdma
/sys/fs/cgroup/perf_event

Cgroup v2 mount points:
/sys/fs/cgroup/unified

Cgroup v1 clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled, not loaded
Macvlan: enabled, not loaded
Vlan: enabled, not loaded
Bridges: enabled, not loaded
Advanced netfilter: enabled, not loaded
CONFIG_NF_NAT_IPV4: enabled, not loaded
CONFIG_NF_NAT_IPV6: enabled, not loaded
CONFIG_IP_NF_TARGET_MASQUERADE: enabled, not loaded
CONFIG_IP6_NF_TARGET_MASQUERADE: enabled, not loaded
CONFIG_NETFILTER_XT_TARGET_CHECKSUM: enabled, not loaded
CONFIG_NETFILTER_XT_MATCH_COMMENT: enabled, not loaded
FUSE (for use with lxcfs): enabled, loaded

--- Checkpoint/Restore ---
checkpoint restore: enabled
CONFIG_FHANDLE: enabled
CONFIG_EVENTFD: enabled
CONFIG_EPOLL: enabled
CONFIG_UNIX_DIAG: enabled
CONFIG_INET_DIAG: enabled
CONFIG_PACKET_DIAG: enabled
CONFIG_NETLINK_DIAG: enabled
File capabilities:

Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

Иногда вы можете увидеть в этом выводе User namespace: missing, но сделать с этим ничего нельзя, придётся так жить, если не хотите пересобирать ядро и отказываться от XFS, в новых ядрах проблема уже исправлена.

Дальше устанавливаем другие нужные пакеты:

$ sudo apt install debootstrap

Следующий шаг опциональный, он нужен, только если команда mount | grep cgroup не возвращает ничего. Но обычно в нём нет необходимости.

Дописываем в /etc/fstab строчку для автоматического монтирования файловой системы cgroup1 (и сразу же монтируем):

$ sudo -i
# echo "cgroup  /sys/fs/cgroup  cgroup  defaults  0   0" >> /etc/fstab
# mount /sys/fs/cgroup

Теперь можно создавать контейнеры (указываем название контейнера первым аргументом и название шаблона в аргументе -t):

$ sudo lxc-create myfirstcontainer -t debian
debootstrap is /usr/sbin/debootstrap
Checking cache download in /var/cache/lxc/debian/rootfs-stable-amd64 ... 
Downloading debian minimal ...
I: Target architecture can be executed
I: Retrieving InRelease 
I: Checking Release signature
I: Valid Release signature (key id 4D64FEC119C2029067D6E791F8D2585B8783D481)
I: Retrieving Packages 
I: Validating Packages 
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
I: Checking component main on http://deb.debian.org/debian...
I: Retrieving adduser 3.134
I: Validating adduser 3.134
I: Retrieving apt 2.6.1
... много таких запросов ...
I: Configuring libc-bin...
I: Configuring ca-certificates...
I: Base system installed successfully.
Download complete.
Copying rootfs to /var/lib/lxc/myfirstcontainer/rootfs...ln: failed to create symbolic link '/var/lib/lxc/myfirstcontainer/rootfs/etc/mtab': File exists
Generating locales (this might take a while)...
  en_US.UTF-8... done
  en_US.UTF-8... done
Generation complete.
Failed to disable unit, unit hwclock.sh.service does not exist.
update-rc.d: error: cannot find a LSB script for hwclockfirst.sh

Current default time zone: 'Asia/Krasnoyarsk'
Local time is now:      Thu Nov 28 23:45:41 +07 2024.
Universal Time is now:  Thu Nov 28 16:45:41 UTC 2024.

Скачанные пакеты кешируются и далее используются при других вызовах.

В ранних версиях LXC нужно было обязательно использовать аргумент -n для указания имени контейнера, теперь это необязательно, lxc- команды принимают название контейнера первым аргументом. Но -n по-прежнему можно использовать.

Создать контейнер можно в интерактивном режиме, указав шаблон download:

$ sudo lxc-create myfirstcontainer -t download
Downloading the image index

---
DIST    RELEASE ARCH    VARIANT BUILD
---
almalinux       8       amd64   default 20241127_23:08
almalinux       8       arm64   default 20241127_23:08
almalinux       9       amd64   default 20241127_23:08
almalinux       9       arm64   default 20241127_23:08
alpine  3.17    amd64   default 20241127_13:00
...
... десятки вариантов
... 
ubuntu  jammy   amd64   default 20241127_07:42
...
ubuntu  oracular        armhf   default 20241127_07:42
voidlinux       current amd64   default 20241127_17:10
voidlinux       current arm64   default 20241127_17:10
---

Distribution:
ubuntu   <<<< вводим это
Release:
jammy   <<<< вводим это
Architecture:
amd64   <<<< вводим это


Downloading the image index
Downloading the rootfs
Unpacking the rootfs

---
You just created an Ubuntu jammy amd64 (20241127_07:42) container.

To enable SSH, run: apt install openssh-server
No default root or user password are set by LXC.

Или можно указать сразу параметры нужного контейнера (в данном случае ubuntu 22.04 "jammy" amd64):

$ sudo lxc-create myfirstcontainer -t download -- --dist ubuntu --release jammy --arch amd64
Using image from local cache
Unpacking the rootfs

---
You just created an Ubuntu jammy amd64 (20241127_07:42) container.

To enable SSH, run: apt install openssh-server
No default root or user password are set by LXC.

Сами контейнеры создаются в каталоге /var/lib/lxc/, в нём по одному каталогу для каждого контейнера, имя каталога совпадает с названием контейнера.

Контейнер создан, можно его запускать:

# lxc-start myfirstcontainer

К запущенному контейнеру можно подключиться так:

$ sudo lxc-attach myfirstcontainer

Выйти из этого режима можно стандартной командой exit.

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

% sudo lxc-attach myfirstcontainer passwd

Остановка контейнера:

$ sudo lxc-stop myfirstcontainer

Полное уничтожение контейнера:

$ sudo lxc-destroy myfirstcontainer

Настройка сети

В прошлых версиях lxc после установки сеть нужно было настраивать вручную, но сейчас этого уже не нужно — автоматически создаётся пустой bridge-адаптер lxcbr0. Этот адаптер прописан в настройках по умолчанию для новых контейнеров в файле /etc/lxc/default.conf. В принципе такая схема уже годится для нормального использования: в новых контейнерах сразу будет доступна сеть, но доступа снаружи хостовой машины до контейнеров не будет.

По умолчанию используется режим сети veth, при котором для каждого контейнера создаётся пара виртуальных сетевых интерфейсов (один внутри контейнера, другой снаружи).

Если вы используете на хостовой машине connman для конфигурации сети, то для корректной работы сети в контейнерах нужно запретить connman управлять veth-интерфейсами (в противном случае connman будет их конфигурить и ломать маршрутизацию). Для этого отредактируйте файл /etc/connman/main.conf, найдите строчку типа такой:

# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb,ve-,vb-

раскомментируйте и допишите в конце через запятую veth, в итоге должно выглядеть так:

NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb,ve-,vb-,veth

Перезагрузите connman:

$ sudo systemctl restart connman

──────────────────

Контейнер получает адрес из приватной сети типа 10.0.3.208, по нему он доступен с хостовой машины, однако снаружи хостовой машины достучаться до контейнера не получится.

Есть несколько способов организовать доступ. Например, добавить системный интерфейс в bridge и настроить veth на его использование, в этом случае в контейнере можно будет получить адрес в той же подсети, что и хостовая машина. Об этом подробно написано на сайте debian: https://wiki.debian.org/LXC/SimpleBridge#Host_device_as_bridge.

Другой способ — через iptables организовать проброс порта до конкретного сервиса. Например, проброс порта 2222 хостовой машины до порта 22 (ssh) контейнера с адресом 10.0.3.208:

$ sudo iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 10.0.3.208:22

Если адрес хостовой машины 192.168.64.3, то получить доступ до ssh-сервера контейнера можно командой:

$ ssh -p 2222 192.168.64.3

Поддержка и обслуживание

Дальше команды россыпью для сопровождения lxc-виртуалок.

Список всех виртуалок

$ sudo lxc-ls -f
NAME                        STATE    IPV4  IPV6  GROUPS  AUTOSTART  
------------------------------------------------------------------
debian-jessie-i386-testing  STOPPED  -     -     -       NO         
myfirstcontainer-i386       STOPPED  -     -     -       NO         
ubuntu-12.04-i386-drupal    STOPPED  -     -     -       NO         
ubuntu-12.04-i386-sample    STOPPED  -     -     -       NO         

Рестарт сетевой поддержки LXC

Это нужно делать после изменений в /etc/default/lxc-net, например.

shell-session $ sudo service lxn-net restart ~

Потом ещё допишу, если какие идеи или проблемы возникнут.

Links

Примечания

История изменений

  • 2014-01-23 — первая версия
  • 2015-05-05 — актуализация и проверка работоспособности примеров
  • 2018-04-20 — актуализация и проверка
  • 2019-09-25 — актуализация до debian buster и проверка
  • 2024-11-30 — актуализация до debian bookworm, проверка, переписан раздел про сеть

  1. cgroup расшифровывается как control group, подробнее — в википедии

  2. Я сделал шаблон на основе файла из стандартного пакета lxc, а помимо выбора архитектуры также включил в него установку некоторых дополнительных приложений (например, vim, file и других). 

Комментарии

Гость: Максим | 2015-08-29 в 06:00

Спасибо за статью. Как пробросить 22 порт ssh'a через NAT не подскажите?

Sergey Stolyarov | 2015-08-29 в 13:49

Без внешнего сервиса, думаю, никак.

Гость: serg | 2014-04-19 в 09:39

Отличная статья. Но как всегда есть недочет. И хочется узнать где создается файл lxc-network.xml а то совсем запутался. И какие еще варианты настройки сети возможны....

Текст комментария (допустимая разметка: *курсив*, **полужирная**, [ссылка](http://example.com) или <http://example.com>) Посетители-анонимы, обратите внимение, что более чем одна гиперссылка в тексте (включая оную из поля «веб-сайт») приведёт к блокировке комментария для модерации. Зайдите на сайта с использованием аккаунта на twitter, например, чтобы посылать комментарии без этого ограничения.
Имя (обязательно, 50 символов или меньше)
Опциональный email, на который получать ответы (не будет опубликован)
Веб-сайт
© 2006—2024 Sergey Stolyarov | Работает на pyrengine