LXD является следующей итерацией LXC, которая предоставляет новый CLI.
При этом, LXD -- это не переписанный LXC. Де-факто, он использует liblxc
для управления linux контейнерами. Наряду с контейнерами, LXD позволяет создавать и
QEMU KVM виртуальные машины, что может быть полезно, например, при необходимости
изменять параметры ядра в контейнере.
Основные преимущества LXD:
- Интуитивно понятный интерфейс
- Частообновляемые образы ОС
- Гибкий контроль потребления ресурсов
- Возможность пробросить устройство в ВМ (USB, GPU, NIC, и другие)
- Гибкое управление сетью и хранилищами
Установка LXD
Установить LXD очень просто:
snap install lxd
И после этого, нам необходимо провести базовую конфигурацию.
Выполним команду:
lxd init
нам будут заданы следующие вопросы:
Would you like to use LXD clustering? (yes/no) [default=no]: no
Отвечаем нет, поскольку мы конфигурируем LXD в standalone режиме.
LXD clustering позволяет конфигурировать высокодоступные кластеры, требуется минимум 3 LXD сервера.
Далее, создаем новый zfs pool где будут храниться данные наших контейнеров и ВМ.
Do you want to configure a new storage pool? (yes/no) [default=yes]: yes
Name of the new storage pool [default=default]: default
Name of the storage backend to use (btrfs, dir, lvm, zfs) [default=zfs]: zfs
Create a new ZFS pool? (yes/no) [default=yes]: yes
Would you like to use an existing block device? (yes/no) [default=no]: no
Size in GB of the new loop device (1GB minimum): 128
На вопрос о MAAS (Metal As A Server) отвечаем no, поскольку конфигурируем LXD в standalone режиме:
Would you like to connect to a MAAS server? (yes/no) [default=no]: no
Далее последуют вопросы о конфигурации сетевого моста для контейнеров.
Используя его все контейнеры получают свой приватный IP адрес, они могут обмениваться данными
друг с другом внутри этой сети и обращаться в интернет.
Would you like to create a new local network bridge? (yes/no) [default=yes]: yes
What should the new bridge be called? [default=lxdbr0]: lxdbr0
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 10.30.0.1/24
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: none
Здесь мы задали подсеть IP из которой будут назначаться нашим контейнерам и отключили IPv6.
Мы не будем пользоваться LXD демоном по сети:
Would you like LXD to be available over the network? (yes/no) [default=no]: no
Разрешаем автоматически обновлять устаревшие образы ОС:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] yes
И, наконец, имеется возможность сохранить получившуюся кофигурацию LXD в YAML формате, которой мы пользоваться не будем:
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: no
Теперь LXD полностью сконфигурирован и можно создавать свой первый контейнер!
Первый LXD контейнер
Для начала нужно определиться с образом контейнера который мы хотим развернуть.
Список доступных образом можно получить так:
lxc image list images:
Предположим, мы выбрали debian/bullseue
, в таком случае контейнер можно запустить так:
lxc launch images:debian/bullseye NAME
После завершения этой команды, можем посмотреть список всех контейнеров/ВМ:
# lxc list
+------+---------+--------------------+------+-----------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+---------+--------------------+------+-----------------+-----------+
| NAME | RUNNING | 10.30.0.11 (eth0) | | VIRTUAL-MACHINE | 0 |
+------+---------+--------------------+------+-----------------+-----------+
Наконец, запустим shell в контейнере:
lxc exec NAME -- /bin/bash
Первая LXD VM
Немногим сложнее создать первую ВМ с LXD. Для этого нам понадобится создать свой
LXD профиль:
lxc profile create vm
Далее создаем текстовый файл lxd-vm.yaml
со следующим содержимым:
config:
user.user-data: |
#cloud-config
ssh_pwauth: no
ssh_authorized_keys:
- "ssh-rsa AAAAB..."
growpart:
mode: auto
devices: ['/']
ignore_growroot_disabled: false
description: LXD profile for virtual machines
devices:
eth0:
nictype: bridged
parent: lxdbr0
type: nic
config:
source: cloud-init:config
type: disk
root:
path: /
pool: default
type: disk
name: vm
used_by: []
Здесь Вам понадобится поменять 6ю строку на свой публичный ключ. Их может быть
несколько, просто добавьте для каждого новый элемент в массив ssh_authorized_keys
.
Это необходимо, чтобы у нас была возможность залогиниться в нашу новую ВМ, поскольку команда
lxc exec
работает только для контейнеров.
Загружаем получившуюся конфигурацию в созданный профиль:
lxc profile edit vm < lxd-vm.yaml
И создаем виртуальную машину(разумеется, вместо ubuntu:20.04
можете выбрать любой другой образ):
lxc init --vm ubuntu:20.04 NAME -p vm
Static IP for VM/container
Если Вам не нравится назначенный автоматически IP, его можно задать вручную:
lxc stop NAME
lxc network attach lxdbr0 NAME eth0 eth0
lxc config device set NAME eth0 ipv4.address IP_ADDRESS
lxc start NAME
Контейнер/VM можно и не перезапускать, но для этого понадобится внутри
контейнера/VM вручную вызвать dhclient
.
Ограничение ресурсов для контейнера/ВМ
Размер корневого раздела можно ограничить так:
lxc config device override NAME root size=64GB
Количество ядер CPU:
lxc config set NAME limits.cpu 4
Объем оперативной памяти:
lxc config set NAME limits.memory 16GB
CPU allowance. Позволяет ограничить выделяемое процессорное время на контейнер:
lxc config set NAME limits.cpu.allowance 80%
Снапшоты
Снапшоты позволяют быстро и практически "бесплатно" заморозить состояние VM/контейнера,
чтобы потом можно было к нему откатиться.
Сделать снапшот очень просто:
lxc snapshot CONTAINER_NAME SNAPSHOT_NAME
Если мы что-то сломали в нашем контейнере, можно откатиться к нужному состоянию:
lxc restore CONTAINER_NAME SNAPSHOT_NAME
Удалить снапшот:
lxc delete CONTAINER_NAME/SNAPSHOT_NAME
Посмотреть список снапшотов, как и всю более детальную информацию о контейнере/ВМ:
lxc info CONTAINER_NAME
Удаление контейнера/ВМ
Будьте осторожны! Эта операция необратима!
lxc delete CONTAINER_NAME
Поздравляю! Мы установили LXD, научились управлять контейнерами и даже виртуальными машинами.
Бонус
Еще в качестве бонуса несколько полезных команд, которыми я часто пользуюсь.
Иногда возникает необходимость создать общий каталог для нескольких контейнеров.
В таком случае, вместо NFS можно просто примонтировать директорию с хостовой ОС
в контейнеры. Это можно сделать следующим образом:
lxc config device add CONTAINER_NAME sharedtmp disk \
path=/tmp/share_on_guest source=/tmp/share_on_host
где sharedtmp
-- имя устройства типа disk
которое будет создано и примонтировано.
Здесь следует знать, что в целях безопасности в LXD контейнерах используется UID И GID
смещение в 1000000
. Таким образом, у пользователя root
в контейнере будет UID 0
, а
у того же пользователя на хостовой ОС -- 1000000
.
Поэтому после создания устройства, нам может понадобиться изменить владельца каталога на
хостовой ОС:
chown -R 1000000:1000000 /tmp/share_on_host
Еще пара полезных команд позволяющих загрузить/выгрузить из контейнера файл.
Из контейнера на хостовую ОС:
lxc file pull CONTAINER_NAME/path-in-container path-on-host
С хостовой ОС в контейнер:
lxc file push path-on-host CONTAINER_NAME/path-in-container
Добавьте ключ -r
если нужно рекурсивной загрузки (для каталогов).