Установка и настройка LXC в Ubuntu 22.04

Установка и настройка LXC под Ubuntu 22.04. Непривилегированные контейнеры.

Перед настройкой LXC рекомендуется выполнить базовую настройку Ubuntu.

Воспользуйтесь инструкцией для настройки nvidia в LXC

UID и GID Maping

Убедитесь, что у вас корректно настроены map uig и gid. Mapping нужен для того, чтобы запускать непривелигированные контейнера. Т.е. root в контейнере на хост машине будет работать с ID 100000, а не 0. Соостветственно файлы в контейнеры будут иметь владельца, начиная с 100000.

nano /etc/subuid

lxc:100000:65536
lxd:100000:65536
root:100000:65536

nano /etc/subgid

lxc:100000:65536
lxd:100000:65536
root:100000:65536

Для удобства вы можете добавить пользователя lxc-root, чтобы в htop видеть процессы запущенные в lxc

groupadd -r --gid 100000 lxc-root
useradd -r -M --uid 100000 -g lxc-root lxc-root

Установка LXC

aptitude install lxc

Установите права доступа, чтобы корректно запускались контейнеры:

chown lxc-root:root /var/lib/lxc
chmod 755 /var/lib/lxc

Также вам потребуется настроить UID для LXC. Пропишите в конце файла следующие строки, выполнив команду nano /etc/lxc/default.conf

lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536

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

Рекомендуется использовать сеть 172.30.0.1/24. Более подробный список указан в списке сетей.

В файле /etc/default/lxc-net пропишите

USE_LXC_BRIDGE="true"
LXC_BRIDGE="lxcbr0"
LXC_ADDR="172.30.0.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="172.30.0.0/24"
LXC_DHCP_RANGE="172.30.0.2,172.30.0.254"
LXC_DHCP_MAX="253"
LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf
#LXC_DOMAIN="lxc"

Создайте файл /etc/lxc/dnsmasq.conf и пропишите в нем:

port=53
listen-address=172.30.0.1
resolv-file=/etc/resolv.conf
domain-needed

Если у вас уже запущен dnsmasq на 53 порту, то можно изменить порт на 53172

port=53172

Включите драйвера br_netfilter

echo overlay >> /etc/modules-load.d/docker.conf
echo br_netfilter >> /etc/modules-load.d/docker.conf

Перенос папки на другой диск

К примеру, вам нужно перенести папку lxc в /srv. 

Перед переносом папки, остановите все контейнеры.

Создайте папку lxc в srv

mkdir /srv/lxc
chown lxc-root:root /srv/lxc
chmod 755 /srv/lxc

перенесите все содержимое из папки /var/lib/lxc в /srv/lxc

mv -f /var/lib/lxc/* /srv/lxc

Убедитесь что папка /var/lib/lxc пустая

ls -la /var/lib/lxc

 /etc/fstab пропишите строчку в конце

/srv/lxc    /var/lib/lxc    none    bind

Сделайте монтирование папки:

mount -a

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

Перенос контейнера на другой хост

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

lxc-stop название_контейнера

Создайте на другом сервере папку:

/var/lib/lxc/название_контейнера/

Перенесите контейнер через rsync:

rsync -aSsuh --info=progress2 --numeric-ids /var/lib/lxc/название_контейнера/ server:/var/lib/lxc/название_контейнера/

Установка контейнера

Установка контейнера LXC Centos 7:

lxc-create -t download -n test-centos -- --dist centos --release 7 --arch amd64

Установка контейнера LXC Ubuntu 18.04:

lxc-create -t download -n test-ubuntu -- --dist ubuntu --release bionic --arch amd64

Установка контейнера LXC Debian Jessie:

lxc-create -t download -n test-debian -- --dist debian --release jessie --arch amd64

Установка контейнера Alpine Linux 3.10:

lxc-create -t download -n test-alpine -- --dist alpine --release 3.10 --arch amd64

Список шаблонов: https://us.images.linuxcontainers.org/

Если выдает ошибку "ERROR: Unable to fetch GPG key from keyserver" то нужно прописать keyserver:

lxc-create -t download -n test-ubuntu-focal -- --dist ubuntu --release focal --arch amd64 --keyserver hkp://keyserver.ubuntu.com

Автозапуск контейнера

Чтобы настроить автоматическое включение контейнера, укажите следующие строки для файла /var/lib/lxc/<название контейнера>/config:

lxc.start.auto = 1
lxc.start.delay = 5 # Задержка, когда будет запущен контейнер

Если хотите, чтобы контейнер не запускался при старте, укажите 0

Ограничение ресурсов CPU

Иногда нужно ограничить cpu для контейнера. Чтобы это сделать, пропишите строчку в конфиге контейнера

# CPU Limit
lxc.cgroup.cpuset.cpus = 0,1

0,1 - означает запустить контейнер на 1м и 2м ядре.

Отключение AppArmor в LXC

Иногда AppArmor мешает контейнеру запуститься. Тогда в конце файла настроек контейнера /var/lib/lxc/<название контейнера>/config пропишите следующую строку

Прописывайте, только если контейнер не запускается.

lxc.apparmor.profile = unconfined

Команды для работы с контейнерами

Чтобы запустить контейнер выполните:

lxc-start название контейнера

Чтобы остановить контейнер выполните:

lxc-stop название контейнера

Чтобы подключиться к контейнеру под рутом:

lxc-attach название контейнера

Просмотреть список контейнеров и их IP адреса

lxc-ls -f

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

В конце файла настроек контейнера /var/lib/lxc/<название контейнера>/config укажите слоедующие параметры:

# Network configuration
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:6b:aa:11
lxc.net.0.ipv4.address = 172.30.0.10/24
lxc.net.0.ipv4.gateway = 172.30.0.1

172.30.0.10 - Это IP адрес контейнера
172.30.0.1 - Адрес шлюза
00:16:3e:6b:aa:11 - MAC Адрес должен быть уникальный
lxcbr0 - Имя LXC bridge. Обычно ставится автоматически

Настройка IP адреса для контейнера с Centos и Alpine Linux

Бывает, что первого способа не достаточно чтобы выдать IP адрес. Тогда нужно задать IP адрес в самом контейнере.

Способ для Centos и Alpine Linux:

Подключитесь к контейнеру через команду

lxc-attach название контейнера

Откройте файл /etc/network/interfaces

Вместо iface eth0 inet dhcp Пропишите:

iface eth0 inet static
        address 172.30.0.10
        netmask 255.255.255.0
        gateway 172.30.0.1

Выйдите из контейнера командой:

exit

Перезапустить контейнер:

lxc-stop название контейнера
lxc-start название контейнера

Настройка IP адреса для контейнера с Ubuntu

Подключитесь к контейнеру и откройте файл nano /etc/netplan/10-lxc.yaml и пропишите следующее содержимое

network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      dhcp6: no
      addresses: [172.30.0.20/24]
      gateway4: 172.30.0.1
      nameservers:
        addresses: [172.30.0.1]

Если IP адрес был задан в адресе конфига, то в netplan их можно не указывать.

Перезапустить контейнер:

lxc-stop название контейнера
lxc-start название контейнера

Настройка DNS

Подключитесь к контейнеру и удалите файл resolv

rm -f /etc/resolv.conf

И создайте его заново:

nano /etc/resolv.conf

nameserver 172.30.0.1

Установка SSH

С хоста. Сгенерируйте ключ ssh, если его у вас нет в домашней папке:

ssh-keygen

Установите ваш публичный сертификат в контейнер:

mkdir -p /var/lib/lxc/test-ubuntu/rootfs/root/.ssh/
cat ~/.ssh/id_rsa.pub >> /var/lib/lxc/test-ubuntu/rootfs/root/.ssh/authorized_keys
chown -R lxc-root:lxc-root /var/lib/lxc/test-ubuntu/rootfs/root/.ssh
chmod 700 /var/lib/lxc/test-ubuntu/rootfs/root/.ssh
chmod 400 /var/lib/lxc/test-ubuntu/rootfs/root/.ssh/authorized_keys

Подключитесь к контейнеру через консоль командой:

lxc-attach test-ubuntu

Установите SSH сервер в контейнере.

Для Ubuntu:

apt install openssh-server -y

Для Centos:

yum install openssh-server -y
systemctl enable sshd

Установите root пароль:

passwd

Завершите текущий сеанс в контейнере:

exit

Теперь вы можете подключиться к контейнеру через SSH:

ssh root@IP-адрес-контейнера

Проброс портов

Проброс портов нужен, чтобы расшарить контейнер в интернет. Иногда этого не требуется, например, если вы проксируете трафик через nginx. Делать нужно на хосте.

Чтобы пробросить порты, нужно установить и настроить iptables-persistent

При работе с iptables будьте осторожны.
Одно неверное движение и доступ к серверу может быть заблокирован !!!

После этого в файле /etc/iptables/rules.v4 и /etc/iptables/rules.v6 в секцию *nat нужно указать строчки

# Проброс SSH на 172.30.0.10
-A PREROUTING ! -i lxcbr0 -p tcp -m tcp --dport 22340 -j DNAT --to-destination 172.30.0.10:22

# Проброс HTTP на 172.30.0.10
-A PREROUTING ! -i lxcbr0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.30.0.10:80
-A PREROUTING ! -i lxcbr0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 172.30.0.10:443

# Проброс FTP на 172.30.0.10
-A PREROUTING ! -i lxcbr0 -p tcp -m tcp --dport 21 -j DNAT --to-destination 172.30.0.10:21
-A PREROUTING ! -i lxcbr0 -p tcp -m tcp --dport 30000:50000 -j DNAT --to-destination 172.30.0.10:30000-50000

и выполнить:

iptables-restore < /etc/iptables/rules.v4
ip6tables-restore < /etc/iptables/rules.v6
systemctl stop lxc
systemctl stop lxc-net
systemctl start lxc-net
systemctl start lxc

Настройка nested контейнера

Nested контейнер - это возможность запустить контейнер в контейнере. Например, если вам нужно будет запустить Docker внутри LXC контейнера, то нужно включить данную опцию.

Опция включается в файле конфига контейнера /var/lib/lxc/<название контейнера>/config

Раскоментируйте строчку:

#lxc.include = /usr/share/lxc/config/nesting.conf

Также может понадобится прописать параметр для монтирования файловой системы cgroup

lxc.mount.auto = cgroup-full:rw

Дополнительно:

  1. Настройка Centos 7 LXC контейнера с поддержкой nginx и php-fpm
  2. Докер в LXC
  3. Непривилегированные контейнеры
  4. Описание файла config
  5. Безопасность в LXC
  6. Список всех образов: https://us.images.linuxcontainers.org/