Expertus metuit
LXC в Debian
2014-01-23 11:10

Инструкции по разворачиванию LXC на Debian-мащине. Всё рассчитано на Debian Stable (Debian 10 Buster на момент написания статьи) и версию lxc 3.0.x.

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

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

$ sudo apt install lxc

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

$ 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

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

$ sudo lxc-create -n myfirstcontainer -t debian

lxc-create: No config file specified, using the default config /etc/lxc/default.conf
debootstrap is /usr/sbin/debootstrap
Checking cache download in /var/cache/lxc/debian/rootfs-squeeze-amd64 ... 
Downloading debian minimal ...
I: Retrieving Release 
I: Retrieving Release.gpg 
I: Checking Release signature
I: Valid Release signature (key id 0E4EDE2C7F3E1FC0D033800E64481591B98321F9)
....ещё 100500 строчек вывода....
update-rc.d: using dependency based boot sequencing
Root password is 'root', please change !
'debian' template installed
'myfirstcontainer' created

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

$ sudo lxc-create -n myfirstcontainer -t download
Setting up the GPG keyring
Downloading the image index

---
DIST    RELEASE ARCH    VARIANT BUILD
---
alpine  3.10    amd64   default 20190925_13:00
alpine  3.10    arm64   default 20190925_13:00
alpine  3.10    armhf   default 20190925_13:00
alpine  3.10    i386    default 20190925_13:00
alpine  3.10    ppc64el default 20190925_13:06
...
... десятки вариантов
... 
voidlinux       current arm64   default 20190924_17:10
voidlinux       current armhf   default 20190924_17:10
voidlinux       current i386    default 20190924_17:10
---

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


Downloading the image index
Downloading the rootfs
...

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

$ sudo lxc-create -n myfirstcontainer -t download -- --dist ubuntu --release bionic --arch amd64
Setting up the GPG keyring
Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

---
You just created an Ubuntu bionic amd64 (20190925_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 -n myfirstcontainer

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

$ sudo lxc-attach -n myfirstcontainer

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

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

% sudo lxc-attach -n myfirstcontainer passwd

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

$ sudo lxc-stop -n myfirstcontainer

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

$ sudo lxc-destroy -n myfirstcontainer

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

По умолчанию контейнер создаётся совсем без поддержки внешней сети, внутри нет никаких сетевых интерфейсов кроме lo, так что сейчас будем настраивать сеть. Для lxc есть несколько вариантов сети, здесь пока только один рассмотрим — через libvirt.

Сначала ставим нужные пакеты на хостовую систему (НЕ в контейнер!):

$ sudo apt install -y libvirt-clients libvirt-daemon-system iptables ebtables dnsmasq-base

Проверяем, что libvirt вообще работает (здесь и далее пользуемся программой управления virsh):

$ sudo virsh net-list --all
 Name      State      Autostart   Persistent
----------------------------------------------
 default   inactive   no          yes

$ sudo virsh net-info default
Name            default
UUID            db05966a-cd06-43ef-9add-4e5c9cd8a871
Active:         yes
Persistent:     yes
Autostart:      no
Bridge:         virbr0

Это сеть по умолчанию с названием default, но мы её использовать не будем (не стоит полагаться на настройки по умолчанию), а сделаем отдельную виртуальную сеть специально для lxc.

Все настройки сети определяются через xml-файл (uuid не указываем, он автоматически сгенерится при создании, содержимое сохраняем в файл /tmp/lxc-network.xml):

<network>
  <name>lxc-network</name>
  <bridge name="virbrlxc0" />
  <forward mode="nat" />
  <ip address="10.10.45.1" netmask="255.255.255.0">
    <dhcp>
      <range start='10.10.45.101' end='10.10.45.254'/>
    </dhcp>
  </ip>
</network>

В этом файле мы задаём диапазон автоматически выделяемых черех dhcp адресов примерно с середины диапазона, а первые адреса (10.10.45.2 ÷ 10.10.45.100) будут использоваться для ручного назначения изнутри контейнеров.

Добавляем постоянную сеть и включаем для неё автозапуск при старте системы:

$ sudo virsh net-define /tmp/lxc-network.xml
Network lxc-network defined from /tmp/lxc-network.xml
$ sudo virsh net-autostart lxc-network
Network lxc-network marked as autostarted

Файл /tmp/lxc-network.xml больше не нужен и его можно спокойно удалить.

Проверяем, что сеть добавилась:

$ sudo virsh net-list --all         
 Name          State      Autostart   Persistent
--------------------------------------------------
 default       inactive   no          yes
 lxc-network   inactive   yes         yes

И запускаем:

$ sudo virsh net-start lxc-network
Network lxc-network started

Проверяем, что сеть запустилась и что соответствующий интерфейс (virbrlxc0) поднялся:

$ sudo virsh net-list
 Name          State    Autostart   Persistent
------------------------------------------------
 lxc-network   active   yes         yes

$ ip addr show virbrlxc0
4: virbrlxc0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:6e:53:fa brd ff:ff:ff:ff:ff:ff
    inet 10.10.45.1/24 brd 10.10.45.255 scope global virbrlxc0
       valid_lft forever preferred_lft forever

Меняем дефолтный конфиг LXC, это файл /etc/lxc/default.conf, прописываем в него следующее (вместо строчки lxc.net.0.type = empty):

lxc.net.0.type = veth
lxc.net.0.flags = up
lxc.net.0.link = virbrlxc0

Теперь все новые контейнеры будут создаваться с такой сетью.

Если вы хотите добавить в уже существующий контейнер, откройте его конфиг (для нашего примера он находится в файле /var/lib/lxc/myfirstcontainer/config) и пишем в него вместо строчки lxc.network.type = empty:

lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = virbrlxc0
lxc.network.hwaddr = 00:FF:AA:00:00:01
lxc.network.ipv4 = 0.0.0.0/24

Останавливаем и снова запускаем контейнер, заходит внутрь и убеждаемся, что сеть есть (адрес выделился автоматически из указанного ранее диапазона 10.10.45.101 ÷ 10.10.45.254):

$ sudo lxc-attach -n ubuntu-18.04
[email protected]:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
6: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 3e:aa:76:f4:07:45 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.10.45.209/24 brd 10.10.45.255 scope global dynamic eth0
       valid_lft 3490sec preferred_lft 3490sec
    inet6 fe80::3caa:76ff:fef4:745/64 scope link
       valid_lft forever preferred_lft forever

Теперь можно как минимум apt-get update сделать.

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

Дальше команды россыпью для сопровождения 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         

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

Links

Примечания

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

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

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

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

Комментарии

Максим | 2015-08-29 в 06:00

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

| 2015-08-29 в 13:49

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

serg | 2014-04-19 в 09:39

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

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