Данная инструкция содержит пошаговый алгоритм установки и настройки LXD. Инструкция рассматривает следующие темы:


— Установка и запуск контейнера.
— Настройка сети.
— Настройка статических IP адресов для контейнеров.
— Настройка NAT и Iptables.
— Создание бэкапов и восстановление из них.
— Отличительные особенности от Docker.


Введение


LXD — это гипервизор контейнеров, который базируется на LXС[1]. Основное отличие от LXC состоит в том, что LXD вводит понятия образа контейнера, и строит инфраструктуру вокруг этих двух понятий.


Проще говоря, LXD – это Docker для виртуальных ОС. Принцип такой же: образ ОС можно скачивать из репозиториев и разворачивать экземпляры на хосте как контейнеры. Один образ можно «клонировать» на несколько виртуальных машин.


Отличия от Docker:


  1. Docker – виртуализация приложений, а LXD – виртуализация операционных систем.
  2. При старте контейнера запускается полноценное linux окружение: запускаются скрипты в init.d и различные установленные сервисы (mysql, apache, nginx, cron и т.п.).
  3. Есть возможность задать статический ip адрес контейнеру.
  4. После запуска контейнера можно менять конфигурацию контейнера ("пробросить" папку и т.п.).
  5. При выходе из контейнера командой exit он продолжает свою работу.
  6. Можно получить напрямую доступ к файловой системе контейнера из машины хоста. Корневая система контейнера находится в папке /var/lib/lxd/containers/<название контейнера>/rootfs.
  7. По умолчанию сервис LXD работает через unix сокет, но его можно открыть во внешнюю сеть и раздавать свои образы. Другими словами можно поднять персональный сервер с образами.

Другие возможности LXD:


  1. Можно интегрировать с OpenStack через плагин nova-lxd.
  2. Есть возможность спящего режима (гибернация) контейнера.
  3. Есть API управлением контейнерами[4].
  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 можно почитать здесь:


  1. Официальный сайт LXD.
  2. Список доступных образов.
  3. Серия статей об LXD 2.0 на русском языке.
  4. Взаимодействие напрямую с LXD API.
  5. Запуск Docker в LXD контейнере.
  6. Настройка статичного адреса для LXC-контейнера в Ubuntu 16.04.
  7. Настройка ZFS для LXD в Ubuntu.
  8. Справочная информация по ZFS.
  9. Как сохранить правила iptables после перезагрузки Ubuntu?
  10. Утилита создания и восстановления бэкапов для LXD.
Поделиться с друзьями
-->

Комментарии (10)


  1. Gular
    24.08.2016 14:15
    +2

    Нужно переосмысливать всё это с использованием Ansible. Видимо много людей не ощутили всю мощь этого инструмента.


  1. sav6622
    24.08.2016 15:06
    -2

    А где последний пункт «Отличительные особенности от Docker.»?


    1. vistoyn
      24.08.2016 15:07
      +1

      он в самом начале во введении "Отличия от Docker"


    1. veter
      24.08.2016 19:23

      И пункт «отличия от lxc»

      Хотя судя по тому что в конце пошли команды непосредственно lxc отличий будет очень мало.


      1. vistoyn
        24.08.2016 20:15

        LXC и LXD немного разные вещи. LXC — низкоуровневый API по работе с контейнерами, LXD — высокоуровневый.
        В документации сказано "LXD использует LXC через liblxc и прослойку, написанную на Go для создания и управления контейнерами."
        Я использую и то и то в своей работе, и скажу, имхо, LXD куда удобнее администрировать и переносить в образах между хостами чем LXC.
        В Canonical хорошо поработали над LXD. Хотя есть над чем работать еще, например, сделать веб интерфейс для LXD.


  1. 1it
    24.08.2016 17:08

    Спасибо, статья годная.
    Жду когда появится на Debian.
    В общем-то я уже сам делал пакетик, но не охота заморачиваться с его поддержкой.


  1. 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
    


  1. Godless
    24.08.2016 23:09

    мне кажется это должно быть тут, можно даже в статью прилепить.
    https://youtu.be/90oxad2r8_E


  1. mickvav
    25.08.2016 20:27

    Годно. Как второй бридж подцепить, чтобы разные машины в разные сетки кидать? Умеет оно виртуалки с дисками на ISCSI заводить?


  1. 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