Docker совершил революцию в мире контейнеризации, но он не единственный игрок. LXC (Linux Containers) и его надстройка LXD предлагают другой подход: они позволяют запускать полноценные системы (как виртуальные машины), но без накладных расходов гипервизора. Если вам нужен «VPS внутри сервера» с полноценным init, системными службами и возможностью ставить любые пакеты — LXC/LXD может быть идеальным решением.
В этой статье мы подробно разберём:
- Что такое LXC и LXD, чем они отличаются от Docker и виртуальных машин.
- Архитектуру LXC/LXD.
- Установку и первоначальную настройку.
- Основные команды LXD: создание, управление, доступ к контейнерам.
- Настройку сети, хранилищ и профилей.
- Примеры: запуск веб-сервера, базы данных, снапшоты, миграцию.
- LXD в production: кластеризация, отказоустойчивость.
- Сравнение LXC/LXD с Docker и виртуальными машинами.
- Частые ошибки и лучшие практики.
1. Что такое LXC и LXD
1.1 LXC (Linux Containers)
LXC — это технология контейнеризации на уровне операционной системы, которая использует возможности ядра Linux: cgroups (ограничение ресурсов) и namespaces (изоляция). LXC позволяет запускать несколько изолированных Linux-систем на одном хосте, используя общее ядро.
Ключевые особенности LXC:
- Контейнер выглядит как полноценная Linux-система: свой init (systemd, sysvinit), свои пользователи, свои сетевые интерфейсы.
- Можно установить любое ПО, которое работает в данной ОС.
- Не требует гипервизора, как виртуальные машины.
- Использует общее ядро хоста, но изолирует процессы, сеть, файловую систему.
LXC существует с 2008 года и изначально управлялся через набор утилит командной строки (lxc-create, lxc-start, lxc-attach и т.д.). Эти утилиты работают, но не очень удобны для массового управления.
1.2 LXD
LXD — это надстройка над LXC, которая предоставляет удобный API, клиент командной строки и инструменты для управления контейнерами. Важное дополнение: Начиная с 2024–2025 годов Canonical ужесточила лицензионную политику LXD, из-за чего большинство независимых Linux-дистрибутивов полностью исключили LXD из своих официальных репозиториев, заменив его на полностью открытый форк Incus. Хотя базовый синтаксис команд управления (lxc ...) у них совпадает, для долгосрочных open-source проектов сегодня рекомендуется выбирать именно Incus.
Что даёт LXD:
- Простой и мощный CLI (
lxc). - REST API для автоматизации.
- Поддержка образов (Ubuntu, Debian, CentOS, Alpine и др.).
- Снапшоты, бэкапы, миграция.
- Кластеризация (несколько серверов LXD объединяются в кластер).
- Профили для быстрой настройки контейнеров.
- Хранилища (ZFS, Btrfs, LVM, директории).
- Сетевые возможности (мосты, VLAN, маршрутизация).
Важно: LXD — это не замена Docker. Это другой инструмент для других задач. Docker упаковывает одно приложение, LXD запускает целую систему.
1.3 Отличия от Docker и виртуальных машин
| Критерий | LXC/LXD | Docker | Виртуальные машины |
|---|---|---|---|
| Что запускает | Полноценную ОС | Одно приложение | Полноценную ОС |
| Ядро | Общее с хостом | Общее с хостом | Собственное |
| Init | systemd, sysvinit | Нет (один процесс) | systemd, sysvinit |
| Изоляция | Высокая (namespaces, cgroups) | Высокая (namespaces, cgroups) | Полная (гипервизор) |
| Запуск | Секунды | Миллисекунды | Минуты |
| Потребление ресурсов | Низкое | Очень низкое | Высокое |
| Использование | VPS, тестовые среды, CI | Микросервисы, приложения | Разные ОС, полная изоляция |
| Управление | LXD CLI/API | Docker CLI/API | libvirt, VMware, Hyper-V |
Когда выбирать LXC/LXD:
- Нужен «VPS внутри сервера» с полноценной ОС.
- Требуется запустить несколько изолированных сред для тестирования.
- Нужна миграция контейнеров между серверами.
- Хочется использовать привычные инструменты (apt, systemd) внутри контейнера.
- Не нужна полная виртуализация (экономия ресурсов).
Когда выбирать Docker:
- Нужно упаковать одно приложение.
- Требуется микросервисная архитектура.
- Важна скорость запуска и минимальный размер образа.
- Нужна экосистема (Docker Hub, Compose, Swarm, Kubernetes).
ВАЖНО! По умолчанию LXD создаёт непривилегированные контейнеры — это безопасно, так как контейнер не имеет прав root на хосте. Если вам нужно запустить Docker внутри LXD или выполнить привилегированную операцию, включите: lxc config set mycontainer security.privileged true. Но делайте это только если понимаете риски.
2. Архитектура LXC/LXD
LXD состоит из нескольких компонентов:
- LXD daemon — фоновый процесс, который управляет контейнерами. Слушает Unix-сокет и (опционально) сетевой порт.
- LXC — низкоуровневая библиотека и утилиты для работы с контейнерами.
- Клиент
lxc— командная строка для взаимодействия с LXD daemon. - Образы — шаблоны систем (Ubuntu, Debian, CentOS, Alpine и др.), которые можно скачать и использовать.
- Профили — наборы настроек (CPU, память, сеть, диски), применяемые к контейнерам.
- Хранилища — места, где хранятся контейнеры (ZFS, Btrfs, LVM, directory).
- Сети — мосты, VLAN, маршрутизация.
Как это работает:
- Вы запускаете
lxc launch ubuntu:22.04 mycontainer. - LXD скачивает образ, создаёт контейнер, применяет профиль по умолчанию.
- Контейнер запускается как изолированный процесс с собственным init.
- Вы можете подключаться к нему (
lxc exec mycontainer bash), управлять пакетами, настраивать сеть.
3. Установка LXD
3.1 Установка на Ubuntu/Debian
В Ubuntu LXD доступен как snap-пакет (рекомендуется) или через apt.
Через snap (рекомендуется):
sudo snap install lxdЧерез apt (для Debian):
sudo apt update
sudo apt install lxd3.2 Установка на CentOS/RHEL/Rocky Linux
sudo dnf install epel-release
sudo dnf install lxd3.3 Первоначальная настройка
После установки выполните:
sudo lxd initВас проведут через несколько вопросов:
- Хранилище: выберите
zfs(если доступно),btrfs,lvmилиdir. Для тестов подойдётdir. - Размер хранилища: по умолчанию.
- Сеть: создайте новый мост
lxdbr0(рекомендуется). - IPv4/IPv6: можно оставить автоматически.
- LXD в кластере: нет (для одного сервера).
- Порт API: можно не включать, если не нужен удалённый доступ.
ВАЖНО! Обратите внимание, что lxd init можно запустить с флагом --auto и параметрами, чтобы не отвечать на вопросы интерактивно — это полезно для автоматизации (например, в cloud-init).
После завершения LXD готов к работе.
3.4 Добавление пользователя в группу lxd
Чтобы управлять LXD без sudo:
sudo usermod -aG lxd $USER
newgrp lxd4. Основные команды LXD
4.1 Управление образами
# Список доступных образов
lxc image list images:
# Список локальных образов
lxc image list
# Копирование образа
lxc image copy images:ubuntu/22.04 local: --alias ubuntu224.2 Создание и запуск контейнеров
# Создать контейнер из образа
lxc launch ubuntu:22.04 mycontainer
# Создать, но не запускать
lxc init ubuntu:22.04 mycontainer
# Запустить остановленный контейнер
lxc start mycontainer
# Остановить
lxc stop mycontainer
# Перезапустить
lxc restart mycontainer
# Удалить
lxc delete mycontainer4.3 Просмотр информации
# Список всех контейнеров
lxc list
# Подробная информация о контейнере
lxc info mycontainer
# Логи
lxc info mycontainer --show-log4.4 Доступ к контейнеру
# Выполнить команду внутри контейнера
lxc exec mycontainer -- bash
# Или просто
lxc exec mycontainer bash
# Выполнить одну команду
lxc exec mycontainer -- apt update
# Скопировать файл из хоста в контейнер
lxc file push /path/on/host/file.txt mycontainer/path/in/container/
# Скопировать файл из контейнера на хост
lxc file pull mycontainer/path/in/container/file.txt /path/on/host/4.5 Управление ресурсами
# Ограничить CPU (2 ядра)
lxc config set mycontainer limits.cpu 2
# Ограничить память (512 МБ)
lxc config set mycontainer limits.memory 512MB
# Посмотреть конфигурацию
lxc config show mycontainer
# Изменить конфигурацию
lxc config edit mycontainer4.6 Снапшоты
# Создать снапшот
lxc snapshot mycontainer snap1
# Список снапшотов
lxc info mycontainer
# Восстановить из снапшота
lxc restore mycontainer snap1
# Удалить снапшот
lxc delete mycontainer/snap14.7 Клонирование
# Клонировать контейнер
lxc copy mycontainer mycontainer-clone
# Клонировать из снапшота
lxc copy mycontainer/snap1 mycontainer-clone5. Настройка сети
5.1 Мост (bridge) — по умолчанию
При lxd init создаётся мост lxdbr0. Контейнеры получают IP из этого моста и имеют доступ в интернет через NAT.
Просмотр сети:
lxc network list
lxc network show lxdbr0Настройка DHCP:
lxc network set lxdbr0 ipv4.dhcp.ranges 10.0.0.100-10.0.0.2005.2 Проброс портов
Чтобы открыть порт контейнера наружу:
# Строгий синтаксис проброса портов в LXD (протокол tcp указывается явно)
lxc config device add mycontainer http proxy \
listen=tcp:0.0.0.0:80 \
connect=tcp:127.0.0.1:80
# Альтернативный, более современный и производительный способ через NAT (LXD 4.0+, требует OVN или статического IP)
lxc network forward create lxdbr0 192.0.2.1 target_address=10.0.0.50ВАЖНО! Connect указывает адрес внутри контейнера. Если сервис слушает только на 127.0.0.1 внутри контейнера — это сработает. Если на конкретном IP — укажите его.
Теперь порт 80 на хосте будет перенаправляться на порт 80 в контейнере.
5.3 Использование macvlan
Если нужно, чтобы контейнер получил IP из вашей локальной сети (как отдельное устройство):
lxc config device add mycontainer eth0 nic nictype=macvlan parent=eth05.4 Статический IP
lxc config device override mycontainer eth0 ipv4.address=10.0.0.506. Хранилища
LXD поддерживает несколько типов хранилищ:
- dir — обычная директория (просто, но медленно).
- ZFS — продвинутая файловая система с снапшотами и дедупликацией.
- Btrfs — похожа на ZFS, но проще.
- LVM — логические тома.
Просмотр пулов:
lxc storage list
lxc storage show defaultСоздание нового пула:
lxc storage create mypool zfsИспользование пула для контейнера:
lxc launch ubuntu:22.04 mycontainer -s mypool7. Профили
Профили позволяют задать общие настройки для группы контейнеров.
Создание профиля:
lxc profile create web
lxc profile edit webПример профиля для веб-сервера:
# Исправленный синтаксис профиля LXD (все значения конфигурации пишем строго в кавычках)
config:
limits.cpu: "2"
limits.memory: "1GB"
boot.autostart: "true"
devices:
eth0:
name: eth0
nictype: bridged
parent: lxdbr0
type: nic
root:
path: /
pool: default
type: diskПрименение профиля:
lxc launch ubuntu:22.04 webserver -p default -p web8. Практические примеры
8.1 Запуск веб-сервера в контейнере
# Создание контейнера
lxc launch ubuntu:22.04 web1
# Вход в контейнер
lxc exec web1 bash
# Внутри контейнера:
apt update
apt install nginx
systemctl start nginx
systemctl enable nginx
# Выход
exit
# Проброс порта 80
lxc config device add web1 http proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80Теперь http://ваш_сервер откроет Nginx из контейнера.
8.2 Запуск базы данных
lxc launch ubuntu:22.04 db1
lxc exec db1 bash
apt update
apt install mysql-server
mysql_secure_installation
exit
# Проброс порта 3306 (только для локального доступа)
lxc config device add db1 mysql proxy listen=tcp:127.0.0.1:3306 connect=tcp:127.0.0.1:3306ВАЖНО! Обратите внимание, что listen — это адрес на хосте, а connect — внутри контейнера.
8.3 Снапшот и восстановление
# Создание снапшота
lxc snapshot web1 before-update
# Обновление (что-то сломалось)
lxc exec web1 bash
apt upgrade -y
# ... всё сломалось ...
exit
# Восстановление
lxc restore web1 before-update8.4 Миграция контейнера на другой сервер
# На сервере-источнике
lxc remote add backup-server 192.168.1.100
# Копирование контейнера
lxc copy web1 backup-server:web1
# На сервере-приёмнике
lxc start web1ВАЖНО! На сервере-приёмнике выполните lxc config set core.https_address :8443 и задайте пароль доверия: lxc config set core.trust_password secret. При lxc remote add вам будет предложено ввести этот пароль.
9. LXD в production
9.1 Кластеризация
Рассмотрим кластер из двух узлов: node1 (192.168.1.10) и node2 (192.168.1.11). Для простоты используем локальные хранилища (без Ceph), что подойдёт для знакомства и тестирования.
Шаг 1. Настройка первого узла (node1)
На первом узле запускаем инициализацию с параметрами кластера:
# ПРАВИЛЬНО: Строгая структура YAML preseed для автоматической инициализации кластера LXD
lxd init --preseed <<EOF
config:
core.https_address: 192.168.1.10:8443
core.trust_password: "secret-cluster-pass"
cluster:
server_name: node1
enabled: true
member_config: []
networks: []
storage_pools: []
profiles: []
EOFЗдесь:
core.https_address— адрес, на котором LXD принимает подключения от других узлов.core.trust_password— пароль для присоединения новых узлов к кластеру.server_name— имя узла в кластере.
Шаг 2. Получение токена для второго узла
На первом узле генерируем токен присоединения:
lxc cluster add node2Вывод будет примерно таким:
Token: eyJzZXJ2ZXJfbmFtZSI6Im5vZGUyIiwiZmluZ2VycHJpbnQiOiI2ZjVj...
Этот токен нужен на втором узле.
Шаг 3. Настройка второго узла (node2)
На втором узле запускаем инициализацию и выбираем присоединение к кластеру:
lxd initНа вопросы отвечаем так:
Would you like to use LXD clustering? yes
What IP address or DNS name should be used to reach this node? 192.168.1.11
Are you joining an existing cluster? yes
Do you have a join token? yes
Please provide join token: <вставьте токен из шага 2>
LXD свяжется с первым узлом, проверит токен и добавит node2 в кластер.
Шаг 4. Проверка кластера
На любом узле:
lxc cluster list+-------+----------------------+----------+--------+----------------+
| NAME | URL | ROLES | STATE | MESSAGE |
+-------+----------------------+----------+--------+----------------+
| node1 | https://192.168.1.10 | database | ONLINE | fully operational |
| node2 | https://192.168.1.11 | database | ONLINE | fully operational |
+-------+----------------------+----------+--------+----------------+
Шаг 5. Создание контейнера на конкретном узле
# Создать контейнер на node1
lxc launch ubuntu:22.04 web1 --target node1
# Создать контейнер на node2
lxc launch ubuntu:22.04 web2 --target node2
# Посмотреть, где работают контейнеры
lxc listШаг 6. Перемещение контейнера между узлами
Для живой миграции нужно, чтобы оба узла использовали общее хранилище (Ceph, или NFS). С локальными хранилищами миграция работает только в остановленном состоянии:
# Остановить контейнер
lxc stop web1
# Переместить на node2
lxc move web1 --target node2
# Запустить на новом узле
lxc start web1
Для живой миграции (без остановки контейнера) требуется распределённое хранилище — Ceph или общий блочный накопитель. С локальными хранилищами (ZFS, Btrfs, dir) миграция возможна только в остановленном состоянии: контейнер переносится копированием.
Кворум: кластер LXD использует базу данных Raft. Для отказоустойчивости нужно минимум 3 узла с ролью database, иначе при потере одного узла кластер перестанет принимать изменения (split-brain). Два узла достаточно для знакомства, но не для production.
ВАЖНО! Полная настройка кластера выходит за рамки этой статьи. См. официальную документацию LXD Clustering.
9.2 Отказоустойчивость
LXD может автоматически перезапускать контейнеры на других узлах при отказе сервера (с использованием Ceph или распределённого хранилища).
9.3 Мониторинг
LXD предоставляет метрики через API. Можно использовать Prometheus и Grafana для мониторинга контейнеров.
9.4 Резервное копирование
# Экспорт контейнера в файл
lxc export web1 web1-backup.tar.gz
# Импорт
lxc import web1-backup.tar.gz10. Сравнение LXC/LXD с Docker и VM
| Критерий | LXC/LXD | Docker | Виртуальные машины |
|---|---|---|---|
| Запуск ОС | Полноценная ОС | Одно приложение | Полноценная ОС |
| Ядро | Общее | Общее | Собственное |
| Init | systemd | Нет | systemd |
| Скорость запуска | Секунды | Миллисекунды | Минуты |
| Потребление RAM | Низкое | Очень низкое | Высокое |
| Изоляция | Высокая | Высокая | Полная |
| Миграция | Да | Ограниченно | Да |
| Кластеризация | Да | Swarm/K8s | Да |
| Использование | VPS, тесты, CI | Микросервисы | Разные ОС |
| Сложность | Средняя | Низкая | Высокая |
11. Частые ошибки и лучшие практики
| Ошибка | Последствия | Решение |
|---|---|---|
| Недостаточно прав | Ошибка доступа к LXD | Добавьте пользователя в группу lxd. |
| Сеть не настроена | Контейнер без интернета | Проверьте lxc network list, настройте lxdbr0. |
| Нет проброса портов | Сервис недоступен извне | Используйте lxc config device add ... proxy. |
Хранилище dir для production | Медленно, нет снапшотов | Используйте ZFS или Btrfs. |
| Нет лимитов | Контейнер съедает все ресурсы | Установите limits.cpu, limits.memory. |
| Нет бэкапов | Потеря данных | Настройте lxc export по cron. |
| Игнорирование обновлений | Уязвимости | Регулярно обновляйте LXD и контейнеры. |
| Запуск Docker внутри LXD* | Конфликты, сложности | Не рекомендуется, если не уверены. |
* Если вам действительно необходимо запустить Docker внутри непривилегированного контейнера LXD (оркестрация в контейнере), не делайте контейнер привилегированным. Вместо этого включите поддержку вложенности и виртуализации одной безопасной командой: lxc config set mycontainer security.nesting true.
Лучшие практики:
- Используйте ZFS или Btrfs для production.
- Настраивайте профили для типовых контейнеров.
- Делайте снапшоты перед обновлениями.
- Ограничивайте ресурсы.
- Мониторьте состояние контейнеров.
- Регулярно обновляйте LXD и образы.
- Документируйте конфигурацию.
Docker и LXD не конкурируют, а дополняют друг друга. Docker — для приложений, LXD — для систем. Освоив оба инструмента, вы сможете выбирать подходящий для каждой задачи.
👤 Зарегистрируйтесь, чтобы добавить материал в закладки.
