Оригинал: Сборка шаблона cloud-init на ZFS — Кирилл Решетников, 1 июля 2026. Лицензия CC BY-NC-SA 4.0 . Публикуется с сохранением авторства и лицензии.
Введение
Статья рассматривает создание Cloud-Init шаблонов в Proxmox VE при использовании ZFS. Материал основан на практическом опыте миграции с mdadm + LVM на ZFS. Проблема возникла при развёртывании ВМ через Terraform: перестал корректно работать dynamic inventory в Ansible. Причина — несовместимость модели хранения ZFS (zvol) и формата qcow2.
Использованное ПО:
- Proxmox VE 9.1
- Debian 13
Проблематика: ZFS и QCOW2
В Proxmox VE с ZFS диски ВМ размещаются в zvol (блочное устройство), а Cloud-Init образы распространяются в формате qcow2 (файл). Это создаёт архитектурный конфликт.
Основная проблема — двойной Copy-on-Write:
- qcow2 выполняет CoW внутри файла;
- ZFS выполняет CoW на уровне блоков.
Последствия:
- двойная запись (write amplification);
- рост задержек (latency);
- ухудшение IOPS;
- дополнительная фрагментация.
В документации Proxmox VE не рекомендуется использовать qcow2 на ZFS.
Различия между форматами
QCOW2
Файловый формат с поддержкой Copy-on-Write, снапшотов, сжатия и thin provisioning. Требует наличия файловой системы. На ZFS создаёт двойной CoW.
RAW
Линейный образ без дополнительной логики:
- нет метаданных;
- запись напрямую в блоки;
- CoW делегирован ZFS.
Преимущества: минимальные накладные расходы и предсказуемая производительность для ZFS.
ZVOL
Блочное устройство внутри ZFS:
- используется Proxmox VE по умолчанию;
- не требует файловой системы;
- управляется ZFS;
- поддерживает снапшоты и клонирование.
Ключевой параметр — volblocksize (размер блока). В Proxmox VE по умолчанию zvol создаётся с блоком 16K, что оптимально для дисков ВМ.
Типичные значения:
- 8K–16K — диски ВМ или БД;
- 64K–128K — универсальный сценарий;
- 256K — изображения;
- 512K–1M — видео и медиафайлы.
ZFS Dataset
Файловая система внутри ZFS:
- параметр
recordsizeвлияет на поведение записи; - при использовании qcow2 возникает двойной CoW;
- дополнительный слой абстракции (ФС → файл → ZFS).
Почему возникает конфликт
При попытке использовать файловый образ (qcow2) как источник для блочного устройства (zvol) Proxmox импортирует qcow2, конвертирует в raw и записывает результат в zvol.
Типичная ошибка:
qm importdisk 7777 ./debian-13-generic-amd64.qcow2 storage --format qcow2Результат: диск импортируется с ошибками, Cloud-Init не инициализируется, ВМ в неконсистентном состоянии.
Варианты решения
Подход 1: ZFS Dataset (directory storage)
Создайте dataset с файловой системой:
rpool/data/imagesПлюсы: простая настройка, совместимость с инструкциями. Минусы: двойной CoW, деградация производительности на HDD.
Вывод: допустимо, но не оптимально.
Подход 2 (рекомендуемый): использование RAW
На этапе импорта укажите формат raw:
qm importdisk <VMID> <image> <storage> --format rawНапример:
qm importdisk 7777 ./debian-13-generic-amd64.qcow2 storage --format rawПлюсы: нет двойного CoW, максимальная производительность, корректная работа Cloud-Init.
Сборка Cloud-Init шаблона на ZFS
1. Импорт образа
Шаг 1. Увеличиваем размер диска:
qemu-img resize ./debian-13-generic-amd64.qcow2 32GШаг 2. Создаём ВМ без диска:
qm create 9998 --name "debian-13-ci" --memory 2048 --cores 2 --net0 virtio,bridge=vnet01Расшифровка:
9998— id новой ВМ;debian-13-ci— имя ВМ;--memory 2048— 2 ГБ ОЗУ;--cores 2— число vCPU;--net0— основной сетевой интерфейс.
Шаг 3. Импортируем образ в формате RAW (ключевое отличие):
qm importdisk 9998 debian-13-generic-amd64.qcow2 vm-hdd --format rawШаг 4. Ставим SCSI-контроллер и добавляем диск:
qm set 9998 --scsihw virtio-scsi-single --scsi0 vm-hdd:vm-9998-disk-0,discard=onШаг 5. Обновляем порядок загрузки:
qm set 9998 --boot order=scsi0Шаг 6. Добавляем Cloud-Init диск:
qm set 9998 --ide1 vm-hdd:cloudinitШаг 7. Настраиваем пользователя и SSH:
# Создание пользователя
qm set 9998 --ciuser ansible
qm set 9998 --cipassword <ПАРОЛЬ>
# Добавление SSH ключа
qm set 9998 --sshkeys ~/.ssh/id_ed25519.pub
# Сетевые настройки (DHCP)
qm set 9998 --ipconfig0 ip=dhcp
# Или статический IP
qm set 9998 --ipconfig0 ip=10.10.10.254/24,gw=10.10.10.1
qm set 9998 --nameserver 10.10.10.15
qm set 9998 --searchdomain infra.lan
# Обновления при запуске
qm set 9998 --ciupgrade 1Шаг 8. Добавляем последовательный порт:
qm set 9998 --serial0 socket --vga serial0Шаг 9. Включаем QEMU Guest Agent:
qm set 9998 --agent enabled=1Шаг 10. Сохраняем как шаблон:
qm template 9998Шаги 11–12. Создаём клон для проверки и запускаем тестовую машину.
2. Добавление Cloud-Init в готовый шаблон
Если шаблон уже существует:
- Сделайте полную копию (Full Clone).
- Подключитесь через VNC или SSH.
- Переключитесь на root:BASH
sudo -i - Обновите систему:BASH
apt update && apt full-upgrade -y - Установите qemu-guest-agent и cloud-init:BASH
apt install -y qemu-guest-agent cloud-init - Создайте конфигурацию
/etc/cloud/cloud.cfg.d/99-pve.cfg:PLAINTEXTdatasource_list: [ NoCloud, ConfigDrive ] - Очистите журналы и machine-id:BASH
cloud-init clean --logs rm -f /etc/machine-id truncate -s 0 /etc/machine-id - Опционально очистите журналы:BASH
journalctl --rotate journalctl --vacuum-time=1s apt clean - Выключите машину:BASH
poweroff - На гипервизоре добавьте Cloud-Init диск:BASH
qm set <VMID> --ide2 <storage>:cloudinit - Добавьте последовательный порт:BASH
qm set <VMID> --serial0 socket --vga serial0 - Включите агента:BASH
qm set <VMID> --agent enabled=1 - Сохраните как шаблон:BASH
qm template <VMID>
Типичные ошибки
- использование qcow2 на ZFS в production;
- импорт qcow2 в zvol без конвертации в raw;
- игнорирование параметра
volblocksize; - неочищенное состояние cloud-init при клонировании;
- отсутствие serial console (недоступны логи);
- неправильно заданный datasource.
Вывод
Оптимальная схема для Proxmox VE с ZFS:
- диски ВМ — zvol;
- формат диска — raw;
- Cloud-Init — отдельный диск.
ZFS уже реализует CoW, снапшоты и thin provisioning. Использование qcow2 поверх ZFS дублирует эти механизмы и приводит к деградации производительности и усложнению архитектуры.