Квоты в LXC через qemu-nbd на Debian 8
Важно: везде заменяйте имя контейнера mydebianvm и IP-адреса на значения вашей среды. Соблюдайте порядок остановки, отмонтирования и отключения nbd — иначе возможны повреждения данных.
О чём эта инструкция
Квоты (filesystem quota) полезны, когда нескольким пользователям или виртуальным хостам нужно ограничить использование дискового пространства. Это критично для хостинга (например, ISPConfig) и многопользовательских окружений. В руководстве показан рабочий способ: использовать lxc с образом qcow2, подключаемым через qemu-nbd, и включить файловые квоты внутри контейнера.
Краткие определения: LXC — лёгкая виртуализация на уровне контейнеров; qemu-nbd — утилита, подключающая qcow2-образ как сетевой блочный девайс /dev/nbd*; qcow2 — формат образа диска qemu; quota, aquota — механизмы учёта и ограничения использования диска.
Сопутствующие варианты решения
- Использовать LVM с квотами на уровне файловой системы (если доступно) — проще для прямых блочных устройств, но сложнее для переносимости.
- Прямое использование raw-образов с loop-модулями и включением quota — возможный путь, но меньше гибкости снимков (snapshots).
- Использовать overlayfs или bind-монты и ограничивать пространство с помощью cgroups v2 (контрольно-ограничивающие механизмы) — альтернативная модель контроля ресурсов.
Основные шаги (микрометодология)
- Установить зависимости (lxc, qemu-utils, bridge-utils).
- Создать контейнер lxc с образом (loop-backed).
- Конвертировать raw в qcow2 и создать слой live-образа для коммитов/бэкапов.
- Настроить сетевой бридж br0 на хосте.
- Подготовить конфигурацию контейнера + скрипты prestart/poststop для подключения qemu-nbd и монтирования.
- Запустить контейнер, установить пакеты quota внутри и активировать квоты через одноразовый скрипт на старте.
- Проверить работоспособность и настроить процедуру бэкапа/удаления.
Предварительные требования
Для работы потребуются утилиты qemu и пакет lxc. Установите их командой:
apt-get install lxc qemu-utilsИнсталлятор запросит директорию для образов LXC (по умолчанию /var/lib/lxc). Выберите раздел с достаточным свободным местом. Если выбрали нестандартный путь — корректируйте его во всех командах и конфигурациях ниже.
Подготовка модуля loop
Проверьте, загружен ли модуль loop:
lsmod | grep '^loop'Если результат пуст, загрузите модуль:
modprobe loopСоздание виртуальной машины
Я использую Debian Jessie/jessie для хоста и контейнера, но можно выбирать другие шаблоны lxc.
lxc-create -B loop -t debian -n mydebianvm --fssize=20G -- -r jessie- -t выбирает шаблон, -r — релиз.
- Для установки размера виртуального диска измените –fssize (например –fssize=50G).
- -n задаёт имя VM; в примерах дальше используется mydebianvm — замените его на своё имя.
Чтобы работать с квотами и удобными бэкапами, конвертируем raw-образ в qcow2:
qemu-img convert -O qcow2 /var/lib/lxc/mydebianvm/rootdev /var/lib/lxc/mydebianvm/rootdev.qcow2Создаём «live» слой, записывающий изменения в отдельный файл (удобно для коммитов и бэкапа):
qemu-img create -f qcow2 -b /var/lib/lxc/mydebianvm/rootdev.qcow2 /var/lib/lxc/mydebianvm/rootdev-live.qcow2Оригинальный raw-файл можно удалить:
rm /var/lib/lxc/mydebianvm/rootdevНастройка сетевого бриджа на хосте
Установите bridge-utils:
apt-get install bridge-utilsОткройте /etc/network/interfaces и добавьте (или скорректируйте) настройки бриджа:
vim /etc/network/interfacesДобавьте следующий фрагмент (замените address и netmask на значения вашей сети):
auto br0
iface br0 inet static
address 192.168.1.254
netmask 255.255.255.0
bridge_ports eth0
bridge_stp off
bridge_fd 2
bridge_maxwait 20Активируйте бридж:
ifup br0Конфигурация контейнера
Сделайте резервную копию старого файла конфигурации:
mv /var/lib/lxc/mydebianvm/config /var/lib/lxc/mydebianvm/config_bakСоздайте новый конфиг:
vim /var/lib/lxc/mydebianvm/configВставьте следующее содержимое (замените IP-адрес контейнера на свободный в вашей сети):
lxc.rootfs = /var/lib/lxc/mydebianvm/rootfs
lxc.rootfs.options = usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0
lxc.hook.pre-start = /var/lib/lxc/prestart-nbd.sh
lxc.hook.post-stop = /var/lib/lxc/poststop-nbd.sh
# Common configuration
lxc.include = /usr/share/lxc/config/debian.common.conf
# only if bridge is set up (or use other method)
lxc.network.type = veth
lxc.network.name = veth0
lxc.network.flags = up
lxc.network.link = br0
lxc.network.ipv4 = 192.168.1.101/24
lxc.network.ipv4.gateway = 0.0.0.0
# Container specific configuration
lxc.mount = /var/lib/lxc/mydebianvm/fstab
lxc.utsname = debian8
lxc.arch = amd64
lxc.autodev = 1
lxc.kmsg = 0Скрипт prestart-nbd.sh
Создайте файл /var/lib/lxc/prestart-nbd.sh:
vim /var/lib/lxc/prestart-nbd.shСодержимое (без изменений):
#!/bin/bash
CHK=$(lsmod | grep '^nbd');
if [[ "$CHK" == "" ]] ; then
modprobe nbd nbds_max=64 max_part=8
fi
DEV=""
for D in /dev/nbd* ; do
F=$(basename $D)
if [[ $(lsblk | grep "^${F} ") == "" ]] ; then
DEV="$D"
break;
fi
done
echo "Next free NBD is $DEV";
CHK=$(lsof /var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2 | grep 'qemu-nbd' | awk '{ print $2 }');
if [[ "$CHK" == "" ]] ; then
if [[ "$DEV" == "" ]] ; then
print "No free nbd device found";
exit 1;
fi
echo "Connecting $DEV to /var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2"
qemu-nbd -c ${DEV} -n --aio=native /var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2
else
NBD=$(lsof -p ${CHK} | grep '/dev/nbd' | awk '{ print $9 }');
if [[ "$NBD" != "" ]] ; then
echo "/var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2 is already connected to $NBD"
DEV="$NBD";
else
echo "/var/lib/lxc/${LXC_NAME}/rootdev-live.qcow2 is used by suspicious PID";
exit 1;
fi
fi
CHK=$(mount | grep " /var/lib/lxc/${LXC_NAME}/rootfs ")
if [[ "$CHK" == "" ]] ; then
echo "/var/lib/lxc/${LXC_NAME}/rootfs not mounted";
echo "Mounting ${DEV} to /var/lib/lxc/${LXC_NAME}/rootfs"
mount ${DEV} /var/lib/lxc/${LXC_NAME}/rootfs
fi
echo "${DEV} ${DEV:1} none bind,create=file,optional 0 0" > /var/lib/lxc/${LXC_NAME}/fstabСделайте скрипт исполняемым:
chmod +x /var/lib/lxc/prestart-nbd.shСкрипт poststop-nbd.sh
Создайте /var/lib/lxc/poststop-nbd.sh:
vim /var/lib/lxc/poststop-nbd.shСодержимое:
#!/bin/bash
CHK=$(mount | grep " /var/lib/lxc/${LXC_NAME}/rootfs " | awk '{ print $1 }')
if [[ "$CHK" != "" ]] ; then
echo "Unmounting ${CHK} from /var/lib/lxc/${LXC_NAME}/rootfs"
echo "Disconnecting ${CHK}"
umount /var/lib/lxc/${LXC_NAME}/rootfs && qemu-nbd -d ${CHK}
fiСделайте исполняемым:
chmod +x /var/lib/lxc/poststop-nbd.shЗапуск контейнера и настройка квот
Запустите контейнер в фоне:
lxc-start -n mydebianvm -dУстановите пакеты quota внутри контейнера без интерактивного входа, с помощью lxc-attach:
lxc-attach -n mydebianvm -- apt-get -y update
lxc-attach -n mydebianvm -- apt-get -y install quotaАктивировать квоты сразу через lxc-attach нельзя, поэтому создаём одноразовый скрипт, который выполнится при следующей загрузке контейнера.
Создайте файл /var/lib/lxc/mydebianvm/rootfs/opt/actquota.sh:
vim /var/lib/lxc/mydebianvm/rootfs/opt/actquota.shСодержимое:
#!/bin/bash
mount -o remount,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0 /
touch /aquota.user /aquota.group
chmod 0600 /aquota.*
quotacheck -cmug /
quotaon -avug
echo '#!/bin/sh -e
exit 0' > /etc/rc.local
rm -f /opt/actquota.shСкрипт удаляет сам себя и очищает /etc/rc.local контейнера после выполнения.
Сделайте его исполняемым:
chmod 700 /var/lib/lxc/mydebianvm/rootfs/opt/actquota.shДобавьте вызов в rc.local контейнера, чтобы скрипт запустился при старте:
echo '#!/bin/bash
if [[ -e "/opt/actquota.sh" ]] ; then
/opt/actquota.sh
fi' > /var/lib/lxc/mydebianvm/rootfs/etc/rc.localПерезапустите контейнер, чтобы активировать квоты:
lxc-stop -r -n mydebianvmПроверка результата
Подключитесь в контейнер:
lxc-attach -n mydebianvmВнутри выполните:
repquota -avugВы должны увидеть используемые квоты для пользователей и групп.
Удаление контейнера и безопасное отключение nbd
Очень важно соблюдать порядок действий. Остановите контейнер:
lxc-stop -n mydebianvmОтмонтируйте rootfs контейнера на хосте:
umount /var/lib/lxc/mydebianvm/rootfsТолько после отмонтирования отключайте nbd (выберите корректный /dev/nbdX):
qemu-nbd -d /dev/nbd0NEVER отключать nbd до отмонтирования — это может привести к повреждению данных и потребует перезагрузки хоста.
Резервное копирование образа
Поскольку мы использовали два файла (базовый rootdev.qcow2 и live-образ rootdev-live.qcow2), перед бэкапом надо зафиксировать изменения из live-слоя в базовый:
qemu-img commit /var/lib/lxc/mydebianvm/rootdev-live.qcow2Теперь файл /var/lib/lxc/mydebianvm/rootdev.qcow2 содержит текущее состояние диска и его можно копировать для бэкапа.
Когда это может не сработать
- Модуль nbd не загружен или не поддерживается в ядре.
- Нет свободных /dev/nbd* устройств.
- Неправильный порядок остановки/отмонтирования перед отключением nbd приведёт к повреждению.
- Повреждён qcow2-образ или диск переполнен.
- В контейнере не установлены пакеты quota или команда quotacheck не выполняется из-за ошибок в файловой системе.
Альтернативные подходы и когда их выбрать
- LVM-контейнеры: если инфраструктура использует LVM, проще выделять тома и включать квоты на файловой системе хоста.
- cgroups v2: для контроля общего потребления ресурсов (IO, память), но не замещает файловые квоты.
- ZFS или btrfs с квотами и снимками: если нужна расширенная функциональность снимков и дедупликации.
Безопасность и рекомендации
- Ограничьте доступ к файлам образов на хосте (правильные права доступа).
- Не оставляйте исполняемые скрипты с глобальным доступом.
- Контролируйте, кто может запускать lxc-* команды и подключать образ через qemu-nbd.
- Регулярно тестируйте процедуру восстановления и бэкапов.
Контроль качества и критерии приёмки
- Контейнер стартует и получает назначенный IP.
- Файл /aquota.user и /aquota.group созданы и имеют права 0600.
- repquota -avug показывает квоты для пользователей/групп.
- Возможность выполнить qemu-img commit и получить корректный бэкап типа qcow2.
- При остановке контейнера rootfs отмонтирован, затем nbd отключён без ошибок.
Роль‑ориентированные контрольные списки
- Администратор хоста: установка qemu-utils/lxc/bridge-utils, конфигурация br0, создание qcow2 и live-образа, скрипты prestart/poststop, права на файлы образов.
- Администратор контейнера: установка quota, проверка quotacheck/quoton, проверка repquota.
- Оператор бэкапов: выполнение qemu-img commit, копирование rootdev.qcow2, проверка целостности бэкапа.
Быстрый справочник команд (cheat sheet)
- Установить пакеты: apt-get install lxc qemu-utils bridge-utils
- Создать контейнер: lxc-create -B loop -t debian -n mydebianvm –fssize=20G – -r jessie
- Конвертировать в qcow2: qemu-img convert -O qcow2 /var/lib/lxc/mydebianvm/rootdev /var/lib/lxc/mydebianvm/rootdev.qcow2
- Создать live-образ: qemu-img create -f qcow2 -b /var/lib/lxc/mydebianvm/rootdev.qcow2 /var/lib/lxc/mydebianvm/rootdev-live.qcow2
- Запустить контейнер: lxc-start -n mydebianvm -d
- Установить quota внутри: lxc-attach -n mydebianvm – apt-get -y install quota
- Активировать квоты (один раз): создать /opt/actquota.sh и добавить вызов в /etc/rc.local
- Проверить: repquota -avug
- Commit изменений live-образа: qemu-img commit /var/lib/lxc/mydebianvm/rootdev-live.qcow2
- Отключить nbd: qemu-nbd -d /dev/nbd0
Короткий глоссарий
- LXC — контейнерная виртуализация на уровне ОС.
- qemu-nbd — утилита для подключения qcow2 как /dev/nbd*.
- qcow2 — формат образа диска qemu с поддержкой снапшотов.
- quota — механизм контроля использования диска пользователями/группами.
- repquota — утилита для отображения текущих квот.
Итог
Это испытанная схема для включения файловых квот в LXC с использованием qemu-nbd и qcow2: она даёт гибкость снимков и упрощает бэкап. Следуйте аккуратно порядку запуска/остановки и проверяйте квоты после первого старта контейнера.
Примечание: если в вашей среде используются другие инструменты управления контейнерами или хранилищем (LVM, ZFS, btrfs), рассмотрите альтернативные подходы, описанные выше.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента