Настраиваем хост контейнеров LXD с хранилищем zfs и web-интерфейсом.
https://habr.com/post/308400/
Если мы настраиваем физический хост или виртуальную машину на собственном сервере, то нам нужно удалить пакет cloud-init. Он предназначен для автоматического конфигурирования системы в различных облачных окружениях.
sudo apt-get -y purge cloud-init && sudo rm -rf /etc/cloud
Теперь ставим lxd:
sudo apt-get install lxd zfsutils-linux bridge-utils
Использование ZFS позволяет использовать снепшоты для бекапа, а также дедупликацию и компрессию для экономии места. Если на хосте LXС/LXD есть ZFS volume, то контейнеры можно создавать как в нем, так и по старому в директории. Просто при создании контейнера нужно указывать имя zfs pool, в котором будет создан dataset
sudo zpool create -f lxd /dev/xvdb sudo zpool status sudo zfs list sudo zfs set dedup=on lxd sudo zfs set compression=on lxd sudo zdb -S lxd
Мне нужно, чтобы контейнеры имели адреса в двух физических LAN. Таким образом, в netplan мне нужно настроить два bridge, в котором указать в качестве slave-интерфейсов мои физические интерфейсы.
Устанавливаем bridge-utils:
sudo apt-get install bridge-utils
Удаляем все ненужные yaml-файлики из /etc/netplan/ и оставляем единственный с таким вот содержимым:
network: version: 2 renderer: networkd ethernets: eth0: dhcp4: no dhcp6: no eth1: dhcp4: no dhcp6: no bridges: br0: dhcp4: no dhcp6: no interfaces: - eth0 addresses: [ 192.168.77.13/24 ] gateway4: 192.168.77.1 nameservers: addresses: - 192.168.77.100 - 192.168.77.1 search: [autosys.tk] parameters: stp: false forward-delay: 0 br1: dhcp4: no dhcp6: no interfaces: - eth1 addresses: [ 192.168.100.113/24 ] parameters: stp: false forward-delay: 0
Перед созданием или импортом контейнеров необходимо произвести первоначальное конфигурирование LXD. Выполняем команду:
sudo lxd init
Вот один из вариантов конфигурирования:
Would you like to use LXD clustering? (yes/no) [default=no]: n Do you want to configure a new storage pool? (yes/no) [default=yes]: yes Name of the new storage pool [default=default]: lxd Name of the storage backend to use (btrfs, dir, lvm, zfs) [default=zfs]: zfs Create a new ZFS pool? (yes/no) [default=yes]: n Name of the existing ZFS pool or dataset: lxd Would you like to connect to a MAAS server? (yes/no) [default=no]: n Would you like to create a new local network bridge? (yes/no) [default=yes]: n Would you like to configure LXD to use an existing bridge or host interface? (yes/no) [default=no]: yes Name of the existing bridge or host interface: br0 Would you like LXD to be available over the network? (yes/no) [default=no]: n Would you like stale cached images to be updated automatically? (yes/no) [default=yes] Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: y config: {} cluster: null networks: [] storage_pools: - config: source: lxd description: "" name: lxd driver: zfs profiles: - config: {} description: "" devices: eth0: name: eth0 nictype: bridged parent: br0 type: nic root: path: / pool: lxd type: disk name: default
Повторное конфигурирование можно запустить так:
dpkg-reconfigure -p medium lxd
Для того, чтобы отредактировать дефолтный профиль, который будет применяться к новым контейнерам. Сохраним его в файл:
sudo lxc profile show default > default_lxd_profile.yaml
Отредактируем его, например - заменив lxdbr0 на имя нашего bridge - br0. И сохраним его в конфигурации LXD:
sudo lxc profile edit default < default_lxd_profile.yaml
Удалить дефолтный lxdbr0 можно командой:
sudo lxc network delete lxdbr0
sudo lxc config device add ContainerName DeviceName disk source=/tmp/share_on_host path=/tmp/share_on_guest
Тут ContainerName - имя контейнера, DeviceName - имя устройства (оно может быть произвольным и служит для идентификации этого ресурса в конфигурации).
Для добавления хранилища выполняем:
sud mkdir -p /path/to/storage/pool sudo lxc storage create PoolName dir source=/path/to/storage/pool
Данная команда создаст пул в директории. Для того, чтобы его впоследствии использовать нужно создать соответствующий профиль.
Создаем пустой профиль:
sudo lxc profile create dir_storage
Открываем редактор:
sudo lxc profile edit dir_storage
И приводим его к такому виду:
config: {} description: "Profile with Directory storage" devices: eth0: name: eth0 nictype: bridged parent: br0 type: nic root: path: / pool: lxd_dir type: disk name: dir_storage used_by: []
Добавление профиля и устройства в него:
sudo lxc profile create device_ppp sudo lxc profile device add device_ppp dev_ppp unix-char path=/dev/ppp
И назначаем профиль контейнеру:
sudo lxc profile assign pptp device_ppp,default
Тут важно, что нужно перечислить все профили, назначаемые контейнеру.
В этом случае профиль можно не создавать.
sudo lxc config device add <ctname> dev_ppp unix-char path=/dev/ppp
Допустим, у нас есть контейнер test1 и нам надо сменить в нем пароль root. Для этого выполняем:
sudo lxc exec test1 -- sh -c passwd
Web-интерфейсов для LXD существует несколько. Покопавшись на github я выбрал LXDUI от AdaptiveScale. Его преимущества - довольно легкий (написан на python), обновляется, по крайней мере пока.
Устанавливаем запчасти:
sudo apt-get install -y python3 zfsutils-linux bridge-utils unzip python3-pip sudo rm /usr/bin/python && sudo ln -s /usr/bin/python3.6 /usr/bin/python sudo pip3 install --upgrade pip
Скачиваем:
wget https://github.com/AdaptiveScale/lxdui/archive/master.zip
Распаковываем:
unzip ./master.zip
Устанавливаем:
cd lxdui-master sudo pip3 install .
Запускаем:
sudo lxdui start
sudo nano /lib/systemd/system/lxdui.service
Пишем туда вот что:
[Unit] Description=LXC/LXD Web User Interface After=network.target [Service] Type=simple ExecStart=/usr/local/bin/lxdui start ExecStop=/usr/local/bin/lxdui stop ExecReload=/usr/local/bin/lxdui reload [Install] WantedBy=multi-user.target
Включаем сервис:
sudo systemctl enable lxdui
И запускаем его:
sudo service lxdui start
LXDUI от AdaptiveScale сам по себе прост и неплох, однако в нем нет аутентификации локальных или доменных пользователей.
Я решил это исправить и добавить аутентификацию пользователей, авторизовавшихся через pam-модули хоста.
Для этого нужно немного отредактировать файлик ./app/lib/auth.py
В моем случае он установился в /usr/local/lib/python3.6/dist-packages/app/lib/auth.py
sudo pip3 install python-pam
В самом конце это файлика есть функция authenticate, которую я привел вот к такому виду:
def authenticate(self, username, password): #try to authenticate using pam pamobj = pam.pam() if pamobj.authenticate(username, password) is True: groups_gids = subprocess.check_output("id -G " + username, shell=True, universal_newlines=True).split() #for group in [subprocess.check_output("getent group " + gid, shell=True, universal_newlines=True).split(':',maxsplit = 1)[0] for gid in groups_gids]: for group in [grp.getgrgid(gid).gr_name for gid in groups_gids]: if group.lower() == 'lxdui': return True, 'Authenticated' #Authebticate using LXDUI database account, err = self.get(username) if account is None: return 'Error', err if account['password'] == self.sha_password(password): return True, 'Authenticated' else: return False, 'Incorrect password.'
Кроме того, в начало файла нужно добавить:
import pam, grp, subprocess
Мой хост присоединен к домену Active Directory и теперь пользователи, входящие в доменную или локальную группу lxdui будут нормально логиниться.
На новом хосте создаем контейнер с таким же именем как и старый. Останавливаем его. Монтируем.
sudo lxc stop CONTAINERNAME sudo zfs mount lxd/containers/CONTAINERNAME
Удаляем файлы:
sudo rm -Rf /var/lib/lxd/storage-pools/lxd/containers/CONTAINERNAME/rootfs/*
И теперь выполняем rsync. тут сложность в том, что rsync должен быть выполнен с правами sudo на обоих хостах:
sudo rsync -hXAavzP --stats --numeric-ids --rsync-path="echo PASSWORD | sudo -Sv && sudo rsync" Username@Old_LXC_Host:/var/lib/lxc/CONTAINERNAME/rootfs/ /var/lib/lxd/storage-pools/lxd/containers/CONTAINERNAME/rootfs/
Контейнеры импортированные из LXC работали в privileged mode, поэтому нужно задать такой же режим импортированному контейнеру:
sudo lxc config set CONTAINERNAME security.privileged true
Также нужно отключить apparmor:
sudo lxc profile set default raw.lxc lxc.apparmor.profile=unconfined
В данном случае - отключаем apparmor (устанавливаем профиль unconfined) для профиля default.
Или можно отключить apparmor для заданного контейнера:
sudo lxc config set CONTAINERNAME raw.lxc lxc.apparmor.profile=unconfined
При попытке мигрировать с хоста Ubuntu 16.04.5 у меня толком ничего не вышло. При миграции переезжала файловая система, однако файл с настройками контейнера не создавался. |
---|
На хосте LXC ставим lxd-tools.
Добавляем диск и делаем zfs-пул.
Затем настраиваем lxd с помощью
lxd init
Мигрируем контейнер с помощью
lxc-to-lxd
Затем делаем
export
переносим полученный image на новый хост и разворачиваем там.
При попытке установить lxd-tools из репозитория Ubuntu 16.04 оказалось, что ставится только версия lxd-tools (2.0.11-0ubuntu1~16.04.4), в которой отсутствует lxc-to-lxd.
Поэтому, ставим из backports:
sudo apt install -t xenial-backports lxd-tools
В результате установится версия 3.0.1-0ubuntu1~16.04.4, в которой lxc-to-lxd есть!.
sudo lxc-to-lxd container_to_move
Если контейнер удачно конвертировался в LXD. Экспортируем его в файл:
lxc snapshot container_name backup lxc publish container_name/backup --alias container_name-backup lxc image export container_name-backup . lxc image delete container_name-backup
Импортируем на новом хосте:
lxc image import TARBALL-NAME --alias container_name-backup lxc launch container_name-backup container_name lxc image delete container_name-backup