Данная инструкция содержит пошаговый алгоритм установки и настройки LXD. Инструкция рассматривает следующие темы:
— Установка и запуск контейнера.
— Настройка сети.
— Настройка статических IP адресов для контейнеров.
— Настройка NAT и Iptables.
— Создание бэкапов и восстановление из них.
— Отличительные особенности от Docker.
Введение
LXD — это гипервизор контейнеров, который базируется на LXС[1]. Основное отличие от LXC состоит в том, что LXD вводит понятия образа контейнера, и строит инфраструктуру вокруг этих двух понятий.
Проще говоря, LXD – это Docker для виртуальных ОС. Принцип такой же: образ ОС можно скачивать из репозиториев и разворачивать экземпляры на хосте как контейнеры. Один образ можно «клонировать» на несколько виртуальных машин.
Отличия от Docker:
- Docker – виртуализация приложений, а LXD – виртуализация операционных систем.
- При старте контейнера запускается полноценное linux окружение: запускаются скрипты в init.d и различные установленные сервисы (mysql, apache, nginx, cron и т.п.).
- Есть возможность задать статический ip адрес контейнеру.
- После запуска контейнера можно менять конфигурацию контейнера ("пробросить" папку и т.п.).
- При выходе из контейнера командой
exit
он продолжает свою работу. - Можно получить напрямую доступ к файловой системе контейнера из машины хоста. Корневая система контейнера находится в папке
/var/lib/lxd/containers/<название контейнера>/rootfs
. - По умолчанию сервис LXD работает через unix сокет, но его можно открыть во внешнюю сеть и раздавать свои образы. Другими словами можно поднять персональный сервер с образами.
Другие возможности LXD:
- Можно интегрировать с OpenStack через плагин nova-lxd.
- Есть возможность спящего режима (гибернация) контейнера.
- Есть API управлением контейнерами[4].
- Можно запускать Docker внутри LXD[5].
Установка LXD
LXD на текущий момент нормально работает на Ubuntu 16.04 LTS. Можно запустить и на других системах, но могут возникнуть сложности или что-то будет работать не так как надо. К примеру, на Centos 7 контейнеры запускаются только в привилегированном режиме, отсутствуют готовые сборки lxd и нужно их компилировать вручную.
В свежей Ubuntu версии, по умолчанию, уже встроен lxd. Если он не установлен, то поставить можно так:
aptitude install lxd
Настройка LXD
Обновите систему и установите необходимые для работы пакеты:
aptitude update
aptitude upgrade
aptitude install lxd zfs zfsutils-linux
Инициализация LXD
Инициализацию LXD нужно делать до того как вы начнете пользоваться контейнерами.
Перед тем как делать инициализацию нужно решить, какое backend хранилище будет использоваться. Backend хранилищ – это место, где находятся все контейнеры и образы. Выделяют два основных типов хранилища: ZFS и Dir.
- ZFS позволяет моментально создавать и восстанавливать снимки контейнеров, создавать контейнеры из образов. Благодаря ZFS, снимки LXD занимают значительно меньше места, чем сам контейнер.
- Dir хранит образы обычным способом на диске. Каждый снимок будет занимать столько же, как и сам контейнер.
ZFS монтируется в файл как loop device, поэтому нужно следить за размером хранилища и увеличивать место, если его мало осталось. ZFS имеет смысл использовать, если у вас есть приватное удаленное хранилище образов, куда вы отправляете, время от времени, снимки контейнеров в качестве бэкапов, а затем скачиваете их от туда для установки новых версий или для восстановления контейнеров из бэкапов.
Я на продакшн сервер решил поставить Dir. ZFS протестирую у себя на локалке. Бэкапы буду делать обычными скриптами – упаковывать их в tar и отправлять их на Amazon S3.
После того как вы решили какое backend хранилище использовать, начинайте процесс инициализации. Делается это командой:
lxd init
Утилита будет задавать вопросы, на которые вам нужно будет ответить. Первым вопросом утилита спросит: какой тип хранилища использовать?
Name of the storage backend to use (dir or zfs): dir
Если ваш ответ Dir, то утилита сразу перейдет к настройке сети. Если ваш ответ ZFS, то система будет задавать следующие вопросы:
Create a new ZFS pool (yes/no)? yes
Name of the new ZFS pool: lxd
Would you like to use an existing block device (yes/no)? no
Size in GB of the new loop device (1GB minimum): 10
«Size in GB of the new loop device» — это размер хранилища ZFS. Все образы и контейнеры будут храниться в этом хранилище, поэтому если вы собираетесь хранить много образов или контейнеров, то нужно увеличить это число.
Затем утилита спросит: нужно ли открывать доступ к LXD из вне? Отвечаем «нет». Если вы хотите создать публичный или приватный репозиторий, то нужно ответить «да».
Would you like LXD to be available over the network (yes/no)? no
Настройка LXD bridge
После настройки типа хранилища, утилита спросит: «Желаете ли вы сконфигурировать LXD bridge?». Отвечаем «да».
Do you want to configure the LXD bridge (yes/no)? yes
Запуститься интерфейс настройки сети. Отвечайте на вопросы следующим образом:
Would you like to setup a network bridge for LXD containers now? Yes
Bridge interface name: lxdbr0
Do you want to setup an IPv4 subnet? Yes
IPv4 address: 10.200.0.1
IPv4 CIDR mask: 16
First DHCP address: 10.200.100.1
Last DHCP address: 10.200.255.254
Max number of DHCP clients: 25399
Do you want to NAT the IPv4 traffic? Yes
Do you want to setup an IPv6 subnet? No
Для сети будет использоваться мост с интерфейсом lxdbr0.
Маска сети 10.200.0.0/16.
IP адрес хоста 10.200.0.1.
Автоматически DHCP будет раздавать IP для контейнеров с 10.200.100.1 по 10.200.255.254, но вручную можно установить, начиная с 10.200.0.2.
Протокол ip6 для контейнеров можно не включать.
Запустить повторно утилиту настройки LXD bridge можно командой:
dpkg-reconfigure -p medium lxd
Установка статического IP для контейнера
Откройте файл:
nano /etc/default/lxd-bridge
Раскоментируйте строчку LXC_DHCP_CONFILE и пропишите:
LXD_CONFILE="/etc/lxd-dnsmasq.conf"
Создайте файл настроек статических IP адресов:
nano /etc/lxd-dnsmasq.conf
Пропишите статический IP адрес для тестового контейнера:
dhcp-host=test,10.200.1.1
В дальнейшем, в этот файл можно будет добавлять другие статические IP адреса для других контейнеров.
После каждого изменения файла /etc/lxd-dnsmasq.conf нужно будет перезагружать lxd-bridge командой:
service lxd-bridge restart
Если это не помагает, то нужно остановить контейнеры с неверными IP, удалить файл dnsmasq.lxdbr0.leases, а затем перезагрузить lxd-bridge:
lxc stop test
rm /var/lib/lxd-bridge/dnsmasq.lxdbr0.leases
service lxd-bridge restart
Настройка NAT
Для того, чтобы заработал NAT, выполнив команды:
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
Настройка Grub
Отредактируйте файл
nano /etc/default/grub
Поменяйте строчку
GRUB_CMDLINE_LINUX="swapaccount=1 quiet"
Без этой строки у меня при запуске lxd выходил warning о том что cgroup swap account не будет работать. Я решил включить опцией swapaccount=1. quiet – это тихая загрузка системы (опционально)
Добавление LXD в автозапуск
systemctl enable lxd
Перезапуск системы
Перезагрузите Ubuntu:
init 6
Установка и запуск образа виртуальной машины
Добавьте репозиторий (опционально, по умолчанию images уже добавлен):
lxc remote add images images.linuxcontainers.org:8443
Скачайте образ:
lxc image copy images:centos/6/amd64 local: --alias=centos-image
centos-image – синоним образа, чтобы легче было к нему обращаться
Запустите образ:
lxc launch local:centos-image test
test — название будущего контейнера
Можно запускать образы в две команды:
lxc init local:centos-image test
lxc start test
Первая команда создаст контейнер, а вторая его запустит. Первая команда полезна, если вы хотите просто создать контейнер, но не запускать его.
Посмотрите статус запущенных контейнеров
lxc list
Команда должна показать следующую информацию:
(Ubuntu)[root@ubuntu /]# lxc list
+------+---------+-------------------+------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+---------+-------------------+------+------------+-----------+
| test | RUNNING | 10.200.1.1 (eth0) | | PERSISTENT | 0 |
+------+---------+-------------------+------+------------+-----------+
Обратите внимание, что LXD выдал статический IP для контейнера, который вы настроили в /etc/lxc-dnsmasq.conf
Проброс папки
Данная команда монтирует папку /data/test/folder в контейнер test в папку /folder
mkdir -p /data/test/folder
chown 100000:100000 /data/test/folder
lxc config device add disk_name test disk path=/folder source=/data/test/folder
Монтирование папок не изменяет содержимое папок /var/lib/lxd/containers/test, а монтируется в отдельную папку /var/lib/lxd/devices/test. Поэтому бэкапы и снимки контейнера не будут содержать примонтированные папки и файлы. Обновление контейнера из бэкапа или образа не будет затрагивать содержимое примонтированных папок.
Просмотреть информацию о настройке можно через команду:
lxc config show test
Подключение к виртуальной машине
Зайдите в запущенный контейнер test:
lxc exec test -- /bin/bash
Проверьте соединение:
ifconfig
Вывод:
[root@test ~]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:16:3E:23:21:3F
inet addr:10.200.1.1 Bcast:10.200.255.255 Mask:255.255.0.0
inet6 addr: fe80::216:3eff:fe23:213f/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:15078 errors:0 dropped:0 overruns:0 frame:0
TX packets:15320 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:28090645 (26.7 MiB) TX bytes:841975 (822.2 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Проверьте NAT:
ping ya.ru
Вывод:
[root@test ~]# ping ya.ru
PING ya.ru (93.158.134.3) 56(84) bytes of data.
64 bytes from www.yandex.ru (93.158.134.3): icmp_seq=1 ttl=50 time=105 ms
64 bytes from www.yandex.ru (93.158.134.3): icmp_seq=2 ttl=50 time=106 ms
64 bytes from www.yandex.ru (93.158.134.3): icmp_seq=3 ttl=50 time=105 ms
64 bytes from www.yandex.ru (93.158.134.3): icmp_seq=4 ttl=50 time=105 ms
64 bytes from www.yandex.ru (93.158.134.3): icmp_seq=5 ttl=50 time=104 ms
64 bytes from www.yandex.ru (93.158.134.3): icmp_seq=6 ttl=50 time=106 ms
^C
--- ya.ru ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 6671ms
rtt min/avg/max/mdev = 104.942/105.845/106.664/0.568 ms
Установите базовые пакеты:
yum install mc nano openssh-server epel-release wget -y
yum update -y
chkconfig sshd on
service sshd start
Установите пароль от рута
passwd
Отключитесь от контейнера:
exit
Подключение через ssh
Скопируйте ключ ssh хоста в контейнер
ssh-copy-id root@10.200.1.1
Если Ubuntu ругается, что не может найти ключ, то сначала сгенерируйте ключ ssh, а затем скопируйте его командой ssh-copy-id. Если ключ скопировался успешно, то пропустите этот шаг (генерация ключа).
ssh-keygen
Теперь вы можете заходить в контейнер через ssh без пароля (через сертификаты):
ssh root@10.200.1.1
Проброс ssh через NAT
Часто нужно получить возможность подключения через ssh к контейнеру напрямую, минуя хост (чтобы каждый раз не заходить на хост, чтобы перейти в контейнер).
Для этого нужно выполнить команду:
iptables -t nat -A PREROUTING -p tcp --dport 22001 -j DNAT --to-destination 10.200.1.1:22
Автосохранение iptables после загрузки Ubuntu
В Ubuntu по умолчанию iptables теряются после перезагрузки хост машины. Чтобы решить эту проблему нужно создать файл:
nano /etc/network/if-up.d/00-iptables
Записать содержимое файла:
#!/bin/sh
iptables-restore < /etc/default/iptables
#ip6tables-restore < /etc/default/iptables6
Установить права на запуск:
chmod +x /etc/network/if-up.d/00-iptables
Сохранить текущие настройки:
iptables-save > /etc/default/iptables
Перезагрузиться и попробовать подключиться в к контейнеру через ssh:
ssh root@<внешний ip хост машины> -p22001
Тонкая настройка iptables
Если использовать восстановление iptables при загрузке, то LXD будет добавлять свои команды в iptables, и в iptables будут содержаться дубликаты записей. К тому же на различных серверах требуется запретить входящие соединения и открыть только необходимые порты.
Готовый листинг /etc/default/iptables
, решающий две задачи сразу, представлен ниже:
# Generated by iptables-save v1.6.0 on Fri Aug 19 16:21:18 2016
*mangle
:PREROUTING ACCEPT [129:9861]
:INPUT ACCEPT [129:9861]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [102:11316]
:POSTROUTING ACCEPT [102:11316]
COMMIT
# Completed on Fri Aug 19 16:21:18 2016
# Generated by iptables-save v1.6.0 on Fri Aug 19 16:21:18 2016
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Проброс ssh порта в контейнер test
-A PREROUTING -p tcp -m tcp --dport 22001 -j DNAT --to-destination 10.200.1.1:22
COMMIT
# Completed on Fri Aug 19 16:21:18 2016
# Generated by iptables-save v1.6.0 on Fri Aug 19 16:21:18 2016
*filter
:INPUT ACCEPT [128:9533]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [102:11316]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
# Разрешаем входящие соединения http и ssh
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
# Запрещаем остальные входящие соединения
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
# Completed on Fri Aug 19 16:21:18 2016
Создание бэкапов
Данный метод создает бэкапы контейнеров как LXD образы, готовые к импорту. В идеале нужно создавать снимки и отправлять их в приватный репозиторий LXD. Но иногда, этого сделать нельзя. Например, у небольшой компании нет возможности покупать еще один сервер. В этом случае можно обойтись простым решением tar + Amazon S3.
Скачайте готовые скрипты для создания и восстановления бэкапов:
wget https://github.com/vistoyn/lxd_backup/raw/1.1/scripts/lxc-backup -O "/usr/local/bin/lxc-backup"
wget https://github.com/vistoyn/lxd_backup/raw/1.1/scripts/lxc-restore -O "/usr/local/bin/lxc-restore"
Установите флаг выполнения для скриптов:
chmod +x /usr/local/bin/lxc-restore
chmod +x /usr/local/bin/lxc-backup
Перед созданием и восстановлением бэкапов нужно остановить работающий контейнер. Можно, в принципе, делать бэкап на работающем контейнере, но при создании бэкапа возможна потеря некоторых данных (зависит от установленных программ в контейнере).
Для dir
Данная команда создаст бэкап контейнера test, сожмет файл в архив и сохранит его на диске в папке /backup/lxc/test:
lxc stop test
lxc-backup test
Восстановление бэкапа из снимка:
lxc-restore test /backup/lxc/test/snap-test-2016-08-19.tar.bz2
Для zfs
Для ZFS после имени контейнера нужно добавлять «.zfs»
Создание бэкапа:
lxc stop test
lxc-backup test.zfs
Восстановление бэкапа из снимка:
lxc-stop test
lxc-restore test.zfs /backup/lxc/test/snap-test.zfs-2016-08-19.tar.bz2
Импорт бэкапа
На новом хосте иногда потребуется создать контейнер из бэкапа. Для этого нужно сначала импортировать образ, а затем его запустить как контейнер.
Команда импорта бэкапа как образа LXD:
lxc image import /backup/lxc/test/snap-test-2016-08-19.tar.bz2 --alias my-new-image
Команда запуска образа как контейнера:
lxc launch me-new-image test2
Материалы
Данная статья не рассматривает множество других вопросов, связанных с LXD. Дополнительную литературу о LXD можно почитать здесь:
- Официальный сайт LXD.
- Список доступных образов.
- Серия статей об LXD 2.0 на русском языке.
- Взаимодействие напрямую с LXD API.
- Запуск Docker в LXD контейнере.
- Настройка статичного адреса для LXC-контейнера в Ubuntu 16.04.
- Настройка ZFS для LXD в Ubuntu.
- Справочная информация по ZFS.
- Как сохранить правила iptables после перезагрузки Ubuntu?
- Утилита создания и восстановления бэкапов для LXD.
Комментарии (10)
sav6622
24.08.2016 15:06-2А где последний пункт «Отличительные особенности от Docker.»?
veter
24.08.2016 19:23И пункт «отличия от lxc»
Хотя судя по тому что в конце пошли команды непосредственно lxc отличий будет очень мало.vistoyn
24.08.2016 20:15LXC и LXD немного разные вещи. LXC — низкоуровневый API по работе с контейнерами, LXD — высокоуровневый.
В документации сказано "LXD использует LXC через liblxc и прослойку, написанную на Go для создания и управления контейнерами."
Я использую и то и то в своей работе, и скажу, имхо, LXD куда удобнее администрировать и переносить в образах между хостами чем LXC.
В Canonical хорошо поработали над LXD. Хотя есть над чем работать еще, например, сделать веб интерфейс для LXD.
1it
24.08.2016 17:08Спасибо, статья годная.
Жду когда появится на Debian.
В общем-то я уже сам делал пакетик, но не охота заморачиваться с его поддержкой.
virpool
24.08.2016 17:15+1Если вы хотите создать публичный или приватный репозиторий, то нужно ответить «да»
Не только. «Да» позволит еще удаленно управлять контейнерами и осуществлять живые миграции https://www.stgraber.org/2016/04/25/lxd-2-0-live-migration-912/
lxc exec test — /bin/bash
С «односложными» командами, а тем более с запуском шелла, можно гораздо проще:
lxc exec test bash
Godless
24.08.2016 23:09мне кажется это должно быть тут, можно даже в статью прилепить.
https://youtu.be/90oxad2r8_E
mickvav
25.08.2016 20:27Годно. Как второй бридж подцепить, чтобы разные машины в разные сетки кидать? Умеет оно виртуалки с дисками на ISCSI заводить?
vistoyn
26.08.2016 00:45Пока тестировал LXD, столкнулся со следующими моментами:
1) Если у вас несколько серверов, то важно чтобы subuid совпадали.
Если они будут разными то при восстановлении файлов из образов и бэкапов могут возникнуть трудности с uid/gid.
Проверить их можно в следующих файлах:
$ less /etc/subuid
lxd:100000:65536 root:100000:65536
$ less /etc/subgid
lxd:100000:65536 root:100000:65536
2) Иногда сразу не запускается lxdbr0. Причин я нашел две:
а) named слушает порт 53 на интерфейсе 0.0.0.0 и не дает dnsmasq его слушать. Исправляется следующим образом:
В файле/etc/bind/named.conf.options
прописать:
listen-on { 127.0.0.1; }; listen-on-v6 { none; };
б) Бывает случай когда дефолтный dnsmasq слушает этот порт. lxd зачем-то запускает свой dnsmasq, вместо того, чтобы
использовать дефолтный. Нужно dnsmasq по умолчанию перевешать на другой порт.
В файле/etc/dnsmasq.conf
нужно прописать:
port=5353
В файле
/etc/default/dnsmasq
поменять флаг запуска:
ENABLED=0
3) Образ centos6 amd64 из официального репозитория немного косячные. Иногда статический ip не прописывается контейнеру.
Вот фикс: https://gist.github.com/vistoyn/75fd36c577b393dcc073a295f869232d
Gular
Нужно переосмысливать всё это с использованием Ansible. Видимо много людей не ощутили всю мощь этого инструмента.