[Перевод] Как установить и настроить LXD на Ubuntu

LXD позволяет создавать контейнеры и управлять ими. В статье разберём, как настроить LXD и использовать его для запуска Nginx в контейнере. А также рассмотрим, как перенаправить трафик из Интернета в контейнер, чтобы сделать пробную веб-страницу доступной.

Данный материал не претендует на самое современное правильное решение для продакшена, а больше формирует понимание работы контейнеров, существующих альтернатив Docker.

333dac95bc097ad1d143b9ea16cb607b.png

Вам понадобится

  • сервер под управлением Ubuntu 20.04;

  • не менее 5 ГБ блочного хранилища. В конфигурации блочного хранилища выберите Manually Format & Mount — это понадобится для хранения всех данных, связанных с контейнерами.

Примечание: начиная с Ubuntu 20.04, LXD официально доступен в виде snap-пакета. Snap-пакет можно установить в любой дистрибутив Linux, поддерживающий snap-пакеты. При запуске LXD snap-пакета рекомендуется использовать сервер с объёмом оперативной памяти не менее 2 ГБ. В таблице приведены общие характеристики LXD snap-пакета:

feature

snap package

доступные версии LXD

2.0, 3.0, 4.0, 4.x

требования к памяти

рекомендуется сервер с 2 ГБ оперативной памяти

политика обновлений 

можно отложить обновление LXD до 60 дней 

возможность обновления с другого формата

можно перейти с deb на snap

Шаг 1: подготовка среды для LXD

Прежде чем настраивать и запускать LXD, подготовим среду сервера. Для этого добавим пользователя sudo в группу lxd и настроим серверную часть хранилища.

Добавление учётной записи в lxd без полномочий суперпользователя

Добавим учётную запись без полномочий root в группу lxd с помощью команды adduser. В качестве аргументов команда adduser принимает учётную запись пользователя и группу Unix:

sudo adduser sammy lxd

Применим новые привилегии:

su sammy

Введём пароль и нажмём ENTER. Затем подтвердим, что наш пользователь добавлен в группу lxd:

id -nG

Должен получиться такой вывод:

sammy sudo lxd

Подготовка серверной части хранилища

Рекомендуемое хранилище для LXD — файловая система ZFS. Чтобы включить поддержку ZFS в LXD, сначала обновим список пакетов, а затем установим вспомогательный пакет zfsutils-linux:

sudo apt update
sudo apt install -y zfsutils-linux

Мы почти готовы запустить скрипт инициализации LXD. Но, прежде чем сделать это, определим и запишем имя устройства для блочного хранилища. Используем ls, чтобы проверить каталог /dev/disk/by-id/:

ls -l /dev/disk/by-id/

В этом примере полный путь к имени устройства — /dev/disk/by-id/scsi-0DO_Volume_volume-fra1–0:

Запишем полный путь к файлу для устройства хранения. Мы будем использовать его на следующем шаге при настройке LXD.

«Администрирование Linux. Мега»

Шаг 2: инициализация и настройка LXD

LXD доступен в виде snap-пакета в Ubuntu 20.04. Он поставляется предустановленным, но его нужно настроить.

Сначала убедимся, что LXD snap-пакет установлен. Команда snap list показывает установленные snap-пакеты:

snap list

Ubuntu 20.04 предустанавливает LXD 4.0.3, и он отслеживает канал 4.0/stable. LXD 4.0 поддерживается в течение пяти лет (до 2025 года). Он получает только обновления для системы безопасности:

Чтобы найти дополнительную информацию об установленном LXD snap-пакете, запустим snap info lxd. Мы сможем увидеть доступные версии, включая дату последнего обновления пакета.

Настройка параметров хранилища для LXD

Запустим процесс инициализации LXD с помощью команды sudo lxd init:

sudo lxd init

Сначала программа спросит, хотим ли мы включить кластеризацию LXD. Введём no и затем нажмём ENTER:

Следующие шесть подсказок относятся к пулу хранения. Дайте следующие ответы:

  • ENTER, чтобы настроить новый пул хранения.

  • ENTER, чтобы принять имя пула хранения по умолчанию.

  • ENTER, чтобы принять серверную часть хранилища zfs по умолчанию.

  • ENTER, чтобы создать новый пул ZFS.

  • yes, чтобы использовать существующее блочное устройство.

Наконец, введём полный путь к имени блочного устройства хранения (это то, что мы записали заранее. Должно быть что-то вроде: /dev/disk/by-id/device_name).

Ответы будут выглядеть следующим образом:

Настройка параметров сети для LXD

LXD спросит, хотим ли мы подключиться к серверу MAAS (Metal As A Server). MAAS — это программное обеспечение, благодаря которому сервер с «голым железом» выглядит и обрабатывается как виртуальная машина.

Мы запускаем LXD в автономном режиме, поэтому примем значение по умолчанию и ответим no:

Дальше нас попросят настроить сетевой мост для контейнеров LXD. Это позволит использовать следующие функции:

  • контейнеры автоматически получают частный IP-адрес;

  • контейнеры могут взаимодействовать друг с другом по частной сети;

  • контейнеры могут инициировать подключение к интернету;

  • контейнеры по умолчанию остаются недоступным из Интернета — мы не можем инициировать подключение из интернета и получить доступ к контейнеру, если явно не включим это. 

На следующем шаге разберём, как разрешить доступ к определённому контейнеру.

Когда нас попросят создать новый локальный сетевой мост, выберем yes:

Затем примем имя по умолчанию, lxdbr0:

Примем автоматический выбор диапазона частных IP-адресов для моста:

LXD задаст несколько вопросов. Когда он спросит, хотим ли мы управлять по сети, нажмём ENTER или ответим no:

На вопрос, хотим ли мы автоматически обновлять устаревшие образы контейнеров, нажмём ENTER или ответим yes:

Когда спросит, хотим ли мы просмотреть и сохранить только что созданную конфигурацию YAML, ответим yes, если хотим. В противном случае нажмём ENTER или ответим no:

Скрипт будет работать в фоновом режиме, чтобы не получать никаких выходных данных.

Мы настроили параметры сети и хранилища для LXD. Теперь можем перейти к созданию первого контейнера LXD.

Шаг 3: создание и настройка контейнера LXD

В LXD мы управляем контейнерами с помощью команды lxc, за которой следует действие: list, launch, start, stop  и delete.

Используем lxc list, чтобы посмотреть доступные установленные контейнеры:

lxc list

Поскольку это первый раз, когда команда lxc связывается с гипервизором LXD, она показывает информацию о том, как запустить контейнер. Наконец, она отображает пустой список контейнеров. Это ожидаемо, потому что мы ещё ничего не создали:

Создадим контейнер, который запускает Nginx. Для этого сначала используем команду lxc launch, чтобы создать и запустить контейнер Ubuntu 18.04 с именем webserver.

Создадим контейнер webserver. 18.04 в ubuntu:18.04 — это ярлык для Ubuntu 18.04. ubuntu: — идентификатор предварительно настроенного репозитория образов LXD. Также можем использовать ubuntu: bionic для имени образа:

lxc launch ubuntu:20.04 webserver

Поскольку мы впервые создаём контейнер, эта команда загрузит образ из интернета и кэширует его. Мы увидим такой вывод, как только новый контейнер завершит загрузку:

После запуска контейнера webserver  используем команду lxc list, чтобы отобразить информацию о нём. Добавим --columns ns4, чтобы показывать только столбцы для имени, состояния и IPv4-адреса. Команда lxc list  по умолчанию показывает ещё три столбца: IPv6-адрес, является ли контейнер постоянным, доступны ли снэпшоты для каждого контейнера:

lxc list --columns ns4

В выходных данных отобразится таблица с именем каждого контейнера, его текущим состоянием, IP-адресом и типом:

DHCP-сервер LXD предоставляет этот IP-адрес, и в большинстве случаев он останется таким же, даже если сервер будет перезагружен. Однако на следующих шагах мы создадим правила iptables для пересылки подключений из интернета в контейнер. Поэтому следует указать DHCP-серверу LXD всегда предоставлять контейнеру один и тот же IP-адрес.

Следующий набор команд сконфигурирует контейнер для получения статического IP-адреса. Сначала переопределим сетевую конфигурацию для устройства eth0, унаследованную от профиля LXD по умолчанию. Это позволит нам установить статический IP-адрес, который обеспечит корректную передачу веб-трафика в контейнер и из него.

lxc config device — команда, которая выполняет действие config для настройки устройства. Первая строка содержит подкоманду override для переопределения устройства eth0 с веб-сервера контейнера. Вторая строка содержит подкоманду для установки поля ipv4.address устройства eth0 контейнера webserver на IP-адрес, который был предоставлен DHCP-сервером в самом начале.

Запустим команду config:

lxc config device override webserver eth0

Получим такие выходные данные:

Теперь установим статический IP:

lxc config device set webserver eth0 ipv4.address your_webserver_container_ip

Если команда выполнена успешно, мы не получим никакого вывода.

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

lxc restart webserver

Затем проверим состояние контейнера:

lxc list

Мы должны увидеть, что контейнер запущен, а IPV4-адрес — наш статический адрес.

Шаг 4: настройка Nginx внутри контейнера LXD

На этом шаге подключимся к контейнеру webserver  и настроим веб-сервер. 

Чтобы подключиться к контейнеру, введём команду lxc shell:

lxc shell webserver

Внутри контейнера командная строка будет выглядеть так:

[environment second]

Оболочка, даже если это корневая оболочка, ограничена контейнером. Все, что мы запускаем в ней, остаётся в контейнере и не может выйти на хост-сервер.

Обновим список пакетов и установим Nginx:

apt update
apt install nginx

После установки отредактируем веб-страницу Nginx по умолчанию. В частности, добавим две строки текста, чтобы было ясно, что этот сайт размещён внутри контейнера webserver.

С помощью редактора откроем файл var/www/html/index.nginx-debian.html:

nano /var/www/html/index.nginx-debian.html

Добавим две выделенные фразы в файл:

Сохраним файл и выйдем из текстового редактора.

Теперь выйдем из контейнера:

logout

Как только приглашение сервера по умолчанию вернётся, используем curl, чтобы проверить, работает ли веб-сервер в контейнере. Для этого нам понадобится IP-адрес веб-контейнера, который мы нашли ранее с помощью команды lxc list.

Используем curl для проверки:

curl http://your_webserver_container_ip

В качестве выходных данных мы получим приветственную HTML-страницу Nginx. Она включает в себя наши правки:

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

Шаг 5: переадресация входящих подключений к контейнеру Nginx с помощью LXD

Для начала нужно настроить сервер на пересылку любых подключений, которые он может получать по порту 80. Чтобы сделать это, создадим правило iptables для пересылки сетевых подключений. 

Для команды iptables требуются два IP-адреса: общедоступный (your_server_ip) и частный (your_webserver_container_ip), который мы можем получить с помощью команды lxc list.

Выполним эту команду, чтобы создать новое правило IPtables:

PORT=80 PUBLIC_IP=your_server_ip CONTAINER_IP=your_container_ip IFACE=eth0  sudo -E bash -c 'iptables -t nat -I PREROUTING -i $IFACE -p TCP -d $PUBLIC_IP --dport $PORT -j DNAT --to-destination $CONTAINER_IP:$PORT -m comment --comment "forward to the Nginx container"'

Разберём команду:

  • -t nat указывает, что мы используем таблицу nat  для преобразования адресов;

  • -I PREROUTING указывает, что мы добавляем правило в цепочку PREROUTING;

  • -i указывает интерфейс eth0, который является общедоступным сетевым интерфейсом на хосте для дроплетов;

  • -p TCP говорит, что мы используем протокол TCP;

  • -d $PUBLIC_IP указывает IP-адрес для правила;

  • --dport $PORT: указывает порт (например, 80);

  • -j DNAT говорит, что мы хотим выполнить переход к Destination NAT (DNAT);

  • --to-destination $CONTAINER_IP:" class="formula inline">PORT говорит, что мы хотим, чтобы запрос направлялся на IP-адрес конкретного контейнера и порт назначения.

Теперь перечислим правила IPTables:

sudo iptables -t nat -L PREROUTING

Вы увидите подобные выходные данные:

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

curl --verbose  'http://your_server_ip'

Увидим заголовки, за которыми следует содержимое веб-страницы, созданной нами в контейнере:

5a4ea4acdc7ae2edd88ab25886c9c2fc.png

Это подтверждает, что запросы отправляются в контейнер. Сохраним правило брандмауэра, чтобы оно применялось повторно после перезагрузки. Для этого сначала установим пакет iptables-persistent:

sudo apt install iptables-persistent

При установке пакета приложение предложит сохранить текущие правила брандмауэра. Примем и сохраним все текущие правила.

Когда мы перезагрузим компьютер, загрузится правило брандмауэра. А сервис Nginx в контейнере LXD автоматически перезапустится.

Шаг 6: остановка и извлечение контейнеров с помощью LXD

В какой-то момент нам может потребоваться остановить или удалить контейнер. На этом шаге разберём, как сделать это. 

Сначала остановим контейнер:

lxc stop webserver

Используем команду lxc list для проверки статуса:

lxc list

Состояние контейнера читается как STOPPED:

Чтобы удалить контейнер, используем lxc delete:

lxc delete webserver

Повторный ввод lxc list показывает, что контейнер не запущен:

lxc list

Команда выведет следующее:

Используем команду lxc help, чтобы просмотреть дополнительные параметры.

Чтобы удалить правило брандмауэра, которое направляет трафик в контейнер, сначала найдём правило в списке правил с помощью команды, которая связывает номер строки с каждым правилом:

sudo iptables -t nat -L PREROUTING --line-numbers

Найдём правило с префиксом в виде номера строки, вот такое:

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

sudo iptables -t nat -D PREROUTING 1

Перечислим правила ещё раз, чтобы гарантировать удаление:

sudo iptables -t nat -L PREROUTING --line-numbers

Правило удалено:

Сохраним изменения, чтобы правило не возвращалось при перезапуске сервера:

sudo netfilter-persistent save

Теперь мы можем открыть другой контейнер со своими собственными настройками и добавить новое правило брандмауэра для переадресации трафика на него.

Заключение 

В этой статье мы установили и настроили LXD. Затем создали веб-сайт, используя Nginx, работающий внутри контейнера LXD, и сделали его общедоступным в IPtables.

«Администрирование Linux. Мега»

© Habrahabr.ru