↓ До тексту
  1. Статті/

Proxmox + Cloud-Init: нова VM за секунди, а не за пів години

cat /etc/passwd
Автор
cat /etc/passwd
Технічний блог про Linux, DevOps та Open Source технології.
Зміст

Щоразу, коли мені потрібна нова віртуалка на Proxmox, я маю вибір із кількох варіантів - і більшість із них погані.

A. Завантажити ISO -> створити VM -> встановити ОС -> залогуватися -> додати користувача, налаштувати мережу і SSH. Довго, і так щоразу.

B. Щоб було швидше, машину з пункту A можна перетворити на template і далі клонувати. Залишиться залогуватися та поміняти IP, hostname і ключі. Частину роботи можна віддати Ansible - але це все одно два кроки: склонувати і прогнати плейбук. Трохи швидше.

C. Один раз приготувати шаблон з Cloud-Init, а при клонуванні вказувати SSH-ключ, hostname та IP прямо з Proxmox. Те, що треба.

Склонував шаблон -> задав IP і hostname -> запустив. Усе.

А не ось це щоразу (так не робимо):

встановити з ISO -> налаштувати мережу -> створити користувача -> додати SSH-ключі. І так кожного разу.

Cloud-Init - це той самий механізм, яким AWS, GCP та Azure налаштовують інстанси ще до першого запуску. У Proxmox він теж є: задаємо параметри (користувач, SSH-ключі, IP), а Cloud-Init застосовує їх при першому завантаженні машини.

Що потрібно зробити?
#

  • завантажити офіційний cloud image (готовий образ ОС із вбудованим Cloud-Init);
  • зібрати з нього шаблон з диском Cloud-Init і перетворити на template;
  • склонувати шаблон і передати клону hostname, IP та SSH-ключ;
  • пересвідчитися, що машина піднялась саме так, як ми задали;
  • те саме зробити мишкою у вебінтерфейсі - для тих, кому так звичніше.

З чим працюю?
#

1
2
root@pve-lab:~# pveversion
pve-manager/9.2.21/4f6e0ac86f9e8c7f (running kernel: 7.0.14-23-pve)
  • Proxmox VE 9.2 (підійде будь-який 8.x чи 9.x);
  • Ubuntu 26.04 LTS cloud image від Canonical;
  • сховище для дисків VM - у прикладі local-lvm (підставляй назву свого);
  • міст vmbr0, у який дивляться машини.

Доступ до GUI або SSH на Proxmox - і все. Адреси та VMID у прикладі - мої; усюди підставляй свої.

Спершу подивимось на весь шлях одним відео, а далі розберемо кожен крок.

Завантажуємо cloud image
#

Cloud image - це готовий образ диска з уже встановленою ОС і Cloud-Init усередині. Важить він небагато, бо це не ISO-інсталятор, а майже порожня система, яка «добудує» себе при першому запуску.

1
2
mkdir -p /root/img && cd /root/img
wget https://cloud-images.ubuntu.com/releases/26.04/release/ubuntu-26.04-server-cloudimg-amd64.img

Перевіримо, що саме завантажили:

1
qemu-img info ubuntu-26.04-server-cloudimg-amd64.img
1
2
3
4
image: ubuntu-26.04-server-cloudimg-amd64.img
file format: qcow2
virtual size: 3.5 GiB (3758096384 bytes)
disk size: 825 MiB

Формат qcow2, віртуальний розмір 3.5 ГБ, реально на диску - 825 МБ. Диск ми потім розширимо під потрібний розмір, Cloud-Init сам доросте файлову систему.

Збираємо шаблон
#

1. Порожня VM без диска
#

Диск підключимо наступним кроком - з образу. Поки що створюємо саму машину з контролером virtio-scsi-single (сучасний і найшвидший варіант SCSI у Proxmox):

1
2
qm create 9000 --name ubuntu-2604-template --memory 2048 --cores 2 \
    --net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-single

VMID 9000 - за традицією під шаблони віддають «високі» номери, щоб не плутати з робочими машинами.

2. Імпортуємо cloud image як диск
#

1
qm set 9000 --scsi0 local-lvm:0,import-from=/root/img/ubuntu-26.04-server-cloudimg-amd64.img
  • local-lvm - назва вашого сховища;
  • 0 - розмір береться автоматично з образу;
  • --scsi0 - диск на SCSI-контролері.

Proxmox імпортує й сконвертує образ:

1
2
3
4
5
  Logical volume "vm-9000-disk-0" created.
transferred 0.0 B of 3.5 GiB (0.00%)
transferred 1.8 GiB of 3.5 GiB (50.15%)
transferred 3.5 GiB of 3.5 GiB (100.00%)
scsi0: successfully created disk 'local-lvm:vm-9000-disk-0,size=3584M'

3. Диск Cloud-Init
#

1
qm set 9000 --ide2 local-lvm:cloudinit

Це віртуальний CD-ROM, через який Proxmox передаватиме налаштування (користувача, SSH-ключі, IP) всередину машини. Побачите рядок generating cloud-init ISO - Proxmox щоразу перегенеровує цей диск, коли параметри змінюються.

4. Завантаження, консоль, агент
#

1
2
3
qm set 9000 --boot order=scsi0
qm set 9000 --serial0 socket --vga serial0
qm set 9000 --agent enabled=1
  • --boot order=scsi0 - вантажимось лише з диска, не чекаючи CD-ROM;
  • --serial0 socket --vga serial0 - багато cloud images очікують serial console; без неї можна не побачити вивід при завантаженні;
  • --agent enabled=1 - вмикаємо QEMU Guest Agent, щоб Proxmox бачив IP машини й коректно робив shutdown та freeze для бекапів. Щоб агент справді відповідав, він має бути встановлений усередині образу - Ubuntu cloud image це вміє, інакше в GUI побачите «Guest Agent not running».

5. Перетворюємо на шаблон
#

1
qm template 9000
1
  Renamed "vm-9000-disk-0" to "base-9000-disk-0" in volume group "vmdata"

Готово. У дереві Proxmox машина з’явиться з іконкою шаблону, запустити її вже не можна - тільки клонувати.

Клонуємо й задаємо параметри
#

Ось тут і починається магія. Клонуємо шаблон у нову VM:

1
qm clone 9000 201 --name web01 --full

--full робить повну, незалежну копію диска. (Є ще linked clone - швидший і легший, але прив’язаний до шаблону; про різницю - нижче.)

А тепер найцікавіше: одним рядком задаємо користувача, SSH-ключ та IP, які Cloud-Init застосує при першому старті:

1
2
3
qm set 201 --ciuser ops --cipassword 'ВашПароль' \
    --sshkeys ~/.ssh/id_ed25519.pub \
    --ipconfig0 ip=10.10.20.51/24,gw=10.10.20.1 --nameserver 1.1.1.1
  • --ciuser - ім’я користувача, якого створить Cloud-Init;
  • --cipassword - його пароль (за бажання; надійніше заходити ключем);
  • --sshkeys - шлях до файлу з публічним ключем, він ляже в authorized_keys;
  • --ipconfig0 - мережа для net0: або статично ip=.../gw=..., або ip=dhcp;
  • --nameserver - DNS-сервер (ще є --searchdomain).

Збільшимо диск під робочий розмір - Cloud-Init сам розширить кореневу файлову систему при старті:

1
qm resize 201 scsi0 10G

Запускаємо:

1
qm start 201

Перевіряємо: воно справді піднялось саме так
#

Момент істини - заходимо на свіжу машину тим самим ключем, який вкинули при клонуванні, і дивимось, що Cloud-Init застосував:

1
ssh ops@10.10.20.51 'hostname; hostname -I; cloud-init status; df -h / | tail -1'
1
2
3
4
web01
10.10.20.51
status: done
/dev/sda1       8.6G  2.7G  5.9G  32% /

Усе на місці: hostname web01, IP саме той, що задали, вхід ключем працює, cloud-init status: done, а коренева файлова система вже розрослася до нового розміру диска. Від qm clone до робочої машини - кілька секунд, без жодного логіну в консоль.

Те саме, але мишкою
#

Не всі люблять CLI, тож покажемо той самий шлях у вебінтерфейсі. Відкриваємо VM web01 -> вкладка Cloud-Init - і бачимо рівно те, що задавали командою: користувач, DNS, SSH-ключ та IP Config. Далі беремо шаблон -> More -> Clone -> і Proxmox пропонує той самий діалог клонування.

Вкладка Cloud-Init - це просто інший вигляд на ті самі параметри. Усе, що ми передали через qm set, тут можна відредагувати в полях:

Вкладка Cloud-Init у вебінтерфейсі Proxmox

Змінили щось у GUI - натисніть Regenerate Image, щоб Proxmox перезібрав диск Cloud-Init. Нові мережеві параметри підхопляться при наступному завантаженні машини.

Ще швидше: другий клон
#

Потрібна ще одна машина? Той самий шаблон, інший VMID, інший IP - і за секунди маємо другу:

1
2
3
4
qm clone 9000 202 --name web02 --full
qm set 202 --ciuser ops --sshkeys ~/.ssh/id_ed25519.pub \
    --ipconfig0 ip=10.10.20.52/24,gw=10.10.20.1
qm start 202
1
qm list
1
2
3
4
      VMID NAME                 STATUS     MEM(MB)    BOOTDISK(GB)
       201 web01                running    2048              10.00
       202 web02                running    2048              10.00
      9000 ubuntu-2604-template stopped    2048               3.50

Дві однакові машини з різними адресами - і жодного ISO, жодного ручного налаштування.

Дрібниці, що стануть у пригоді
#

  • DHCP замість статики. Якщо в мережі є DHCP, досить --ipconfig0 ip=dhcp - і адреса прилетить сама.
  • Linked clone проти full. --full робить незалежну копію (шаблон можна хоч видаляти). Linked clone створюється миттєво й майже не займає місця, але тримається за диск шаблону - зручно для швидких тестових машин, не варто для того, що має жити довго.
  • Коли Cloud-Init відпрацьовує. Повна конфігурація застосовується лише на першому завантаженні. Якщо хочете «скинути» машину до чистого стану з новими параметрами - простіше склонувати нову з шаблону, ніж перенавчати стару.
  • Більше, ніж user і IP. Через Cloud-Init можна передавати цілий user-data: ставити пакети, писати файли, запускати команди при першому старті. У Proxmox для цього є сніпети (snippets) - окрема тема, але саме так шаблон перетворюється на справжній «золотий образ».

Підсумок
#

Один раз витрачений вечір на шаблон - і нові віртуалки перестають бути рутиною. Замість «встановити з ISO -> налаштувати мережу -> створити користувача» залишається qm clone, один qm set із потрібними параметрами і qm start. Hostname, IP та ключ - з коробки, бо про них подбав Cloud-Init.

Наступний логічний крок - не клонувати руками, а описати все кодом: той самий шаблон плюс Terraform, і цілий стенд піднімається однією командою. Але це вже окрема історія.

Related

Vikunja - задачі команди на власному сервері

Задачі команди губляться в чатах, табличках і голові одного менеджера. Ставимо власну Vikunja на одну маленьку VM: один контейнер, SQLite, окремий диск під дані, HTTPS без домену через внутрішній CA Caddy. А далі - проєкти, дедлайни й канбан-дошка, де видно, хто що робить. Усе кроками, які осилить офіс без штатного адміна.

Stirling PDF - офісний PDF-комбайн на власному сервері

Офісні файли ганяють через випадкові онлайн-конвертери PDF, хоча там комерційна таємниця й персональні дані. Ставимо власний Stirling PDF на одну Ubuntu-VM: окремий диск під дані, Docker, fat-образ заради конвертації кириличних документів і OCR, вхід із паролем і HTTPS без домену через внутрішній CA Caddy. Другий пост серії «Офіс без адміна».

Vaultwarden - менеджер паролів для офісу без адміна

Паролі команди живуть у чатах і на стікерах, поки хтось не звільниться разом із доступами. Ставимо власний Vaultwarden на одну маленьку VM: окремий диск під дані, Docker, HTTPS без домену через внутрішній CA Caddy, а далі - спільний сейф організації з колекціями по відділах і запрошеннями на ~20 людей. Усе кроками, які осилить офіс без штатного адміна.