Lab 40 – Template, cloud-init e cloni: linked e full, snippets e deploy da CLI
Dipendenze
Sezione intitolata “Dipendenze”- Lab precedenti:
- Nodi e storage: cluster
desopve01-03; template surbd-vm; snippets sucephfs. - Rete: il proxy
proxy.proxmox.community:3128per i pacchetti dei guest. - Indirizzi: VM 102 su 172.27.199.102; VM 103 in DHCP sulla VNet
vnsimp1; VM 104-106 su 172.27.199.104-106. - Credenziali: utente
labusercon chiave SSH, senza password → Appendice B.
Obiettivi
Sezione intitolata “Obiettivi”- Trasformare un’immagine cloud in un template con cloud-init.
- Capire la differenza tra linked clone e full clone, con tempi e spazio misurati.
- Configurare utente, chiavi, IP statico e DHCP dalla scheda Cloud-Init.
- Leggere quello che Proxmox VE passa al guest con
qm cloudinit dump. - Aggiungere configurazione personalizzata con gli snippets (
cicustom). - Creare tre VM pronte all’uso, su tre nodi, con un ciclo di comandi.
Come funziona
Sezione intitolata “Come funziona”Template. Un template è una VM in sola lettura: non si avvia e i suoi dischi diventano dischi base (base-9000-disk-0). Si usa solo come sorgente di cloni.
Linked clone e full clone.
| Linked clone | Full clone | |
|---|---|---|
| Disco | copy-on-write sul disco base del template | copia completa e indipendente |
| Tempo | pochi secondi | proporzionale ai dati da copiare |
| Spazio iniziale | quasi zero | quanto i dati del disco |
| Vincoli | stesso storage del template; il template non si può eliminare finché esistono cloni | nessuno: può andare su un altro storage |
Lo storage deve supportare i cloni a livello di disco: Ceph RBD (clone di uno snapshot), ZFS, LVM-thin, qcow2 (backing file).
Cloud-init. Le immagini cloud non hanno un installer: al primo avvio cloud-init legge la configurazione da un datasource. Proxmox VE usa il datasource NoCloud: genera un piccolo CD (il drive CloudInit) con tre file:
user-data: utente, chiavi SSH, hostname, pacchetti;network-config: indirizzi, gateway, DNS;meta-data: l’instance-id.
Quando cambi un parametro Cloud-Init, Proxmox VE rigenera il CD con un nuovo instance-id, e al riavvio successivo cloud-init applica di nuovo la configurazione.
Snippets. Con cicustom si possono sostituire o integrare i file generati con file propri, salvati in uno storage con contenuto Snippets. Il tipo vendor si aggiunge allo user-data di Proxmox VE invece di sostituirlo: utente, chiavi e rete restano quelli della scheda Cloud-Init.
Procedura
Sezione intitolata “Procedura”1. L’immagine cloud
Sezione intitolata “1. L’immagine cloud”L’immagine debian-13-genericcloud-amd64.qcow2 è stata scaricata nel Lab 19 nello storage local, contenuto Import:
image: /var/lib/vz/import/debian-13-genericcloud-amd64.qcow2file format: qcow2virtual size: 3 GiB (3221225472 bytes)disk size: 324 MiBÈ un sistema già installato: 3 GiB di disco virtuale, 324 MiB di dati reali.
2. La VM base con il drive Cloud-Init
Sezione intitolata “2. La VM base con il drive Cloud-Init”Il disco si importa direttamente durante la creazione, con import-from:
qm create 9000 --name debian13-cloud --ostype l26 --memory 2048 --cores 2 --cpu x86-64-v2-AES \ --scsihw virtio-scsi-single \ --scsi0 rbd-vm:0,import-from=local:import/debian-13-genericcloud-amd64.qcow2,discard=on,ssd=1,iothread=1 \ --ide2 rbd-vm:cloudinit --boot order=scsi0 --serial0 socket --vga serial0 \ --net0 virtio,bridge=vmbr0 --agent enabled=1qm resize 9000 scsi0 8Gtransferred 3.0 GiB of 3.0 GiB (100.00%)scsi0: successfully created disk 'rbd-vm:vm-9000-disk-0,discard=on,iothread=1,size=3G,ssd=1'Resizing image: 100% complete...done.--ide2 rbd-vm:cloudinitcrea il drive Cloud-Init. Sta surbd-vmcome il disco, così i cloni funzionano su ogni nodo.--serial0 socket --vga serial0: le immagini cloud Debian usano la console seriale; la console della VM diventa xterm.js (Lab 38).qm resize: il disco passa da 3 a 8 GiB. Al primo avvio cloud-init allarga partizione e filesystem da solo.
I parametri Cloud-Init. La chiave pubblica del DC è già tra quelle autorizzate sul nodo (Lab 05); per il template si isola solo quella:
qm set 9000 --ciuser labuser --sshkeys /root/lab40-dc.pub --ipconfig0 ip=dhcp \ --nameserver 172.27.199.20 --searchdomain proxmox.community --ciupgrade 0--sshkeys: un file con la chiave pubblica diadministratordel DC (Lab 05). Nessuna password: si entra solo con la chiave.--ipconfig0 ip=dhcp: nel template; ogni clone avrà il suo indirizzo.--ciupgrade 0: l’opzione Upgrade packages è attiva di default e al primo avvio lancia l’aggiornamento dei pacchetti. Nel laboratorio il guest non ha ancora il proxy configurato, quindi la si disattiva nel template: il proxy lo imposta lo snippet della sezione 8.
Nella vista Hardware compare il CloudInit Drive (ide2):

e nella scheda Cloud-Init la configurazione, modificabile anche da qui:

3. Conversione in template
Sezione intitolata “3. Conversione in template”More → Convert to template (o qm template 9000). Il disco viene rinominato in base-9000-disk-0 e Ceph ne crea lo snapshot protetto __base__, sorgente di tutti i linked clone.
4. Linked clone
Sezione intitolata “4. Linked clone”More → Clone sul template. Mode è Linked Clone e Target Storage è bloccato su “Same as source”:

Il task dura 2 secondi. Il disco del clone è un clone RBD dello snapshot del template:
rbd info rbd-vm/vm-102-disk-0 | grep -E "parent|size"rbd du -p rbd-vm size 8 GiB in 2048 objects parent: rbd-vm/base-9000-disk-0@__base__NAME PROVISIONED USEDbase-9000-disk-0@__base__ 8 GiB 1.1 GiBbase-9000-disk-0 8 GiB 0 Bvm-102-cloudinit 4 MiB 4 MiBvm-102-disk-0 8 GiB 12 MiBIl clone occupa 12 MiB: legge i dati comuni dal disco base e scrive solo le differenze.
Un IP statico e l’avvio:
qm set 102 --ipconfig0 ip=172.27.199.102/24,gw=172.27.199.1qm start 102Dopo meno di un minuto si entra con la chiave del DC:
hostname -flinked01.proxmox.communitycloud-init status --longstatus: doneextended_status: degraded done...recoverable_errors:DEPRECATED: - 'user' of type string is deprecated in 22.2 and scheduled to be removed in 27.2. Use 'users' list instead.ip -br -4 a | grep -v "^lo"eth0 UP 172.27.199.102/24df -h / | tail -1/dev/sda1 7.7G 596M 6.8G 8% /sudo -n true && echo "sudo senza password: ok"sudo senza password: ok- L’hostname è il nome del clone: Proxmox VE lo passa a cloud-init.
- Il filesystem è già cresciuto a 7,7 GiB.
degraded donenon indica un errore: cloud-init segnala solo un avviso di deprecazione sul formato dello user-data generato da Proxmox VE (la chiaveuser). La configurazione è applicata.- L’utente creato da cloud-init ha
sudosenza password, la prassi delle immagini cloud.
5. Full clone e i suoi vincoli
Sezione intitolata “5. Full clone e i suoi vincoli”Un full clone verso un altro nodo, su uno storage locale:
qm clone 9000 103 --name full01 --full --storage local-zfs --target desopve02can't clone to non-shared storage 'local-zfs'Per clonare su un altro nodo lo storage di destinazione deve essere condiviso. Sullo stesso nodo il full clone su local-zfs funziona:
time qm clone 9000 103 --name full01 --full --storage local-zfstransferred 8.0 GiB of 8.0 GiB (100.00%)
real 0m11.967sNAME USED REFERrpool/data/vm-103-disk-0 542M 542M12 secondi contro 2, e 542 MiB occupati subito. Il disco è indipendente: il template si potrebbe eliminare senza conseguenze per questa VM.
6. DHCP con la VNet SDN
Sezione intitolata “6. DHCP con la VNet SDN”La VM 103 va sulla VNet vnsimp1 del Lab 27, che ha DHCP e IPAM, con l’IP in DHCP:
qm set 103 --net0 virtio,bridge=vnsimp1 --ipconfig0 ip=dhcpqm cloudinit dump 103 networkversion: 1config: - type: physical name: eth0 mac_address: 'bc:24:11:06:db:69' subnets: - type: dhcp4 - type: nameserver address: - '172.27.199.20' search: - 'proxmox.community'All’avvio l’IPAM di Proxmox VE assegna l’indirizzo e il DHCP della zona lo consegna:
{'hostname': 'full01', 'ip': '10.60.60.102', 'mac': 'BC:24:11:06:DB:69', 'subnet': '10.60.60.0/24', 'vmid': 103, 'vnet': 'vnsimp1', 'zone': 'simple1'}0 bc:24:11:06:db:69 10.60.60.102 * ff:ca:53:09:5a:00:02:00:00:ab:11:cf:d3:17:39:9a:c9:d3:ff2 packets transmitted, 2 received, 0% packet loss, time 1056msLa prima riga viene dall’IPAM (pvesh get /cluster/sdn/ipams/pve/status), la seconda dal file dei lease del DHCP sul nodo, la terza è un ping dal nodo.
7. Cosa riceve il guest: qm cloudinit dump
Sezione intitolata “7. Cosa riceve il guest: qm cloudinit dump”Lo user-data che Proxmox VE genera per il template:
qm cloudinit dump 9000 user#cloud-confighostname: debian13-cloudmanage_etc_hosts: truefqdn: debian13-cloud.proxmox.communityuser: labuserssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC7iIUcNX6/zxPH06HIwBM0Txccu3wAqjjIBFBmR1rCo [email protected]chpasswd: expire: Falseusers: - defaultÈ qui la chiave user che cloud-init segnala come deprecata. Quando un clone non si comporta come previsto, qm cloudinit dump <vmid> user|network|meta è il primo controllo.
8. Snippets: configurazione aggiuntiva
Sezione intitolata “8. Snippets: configurazione aggiuntiva”Lo storage cephfs è condiviso tra i nodi: si abilita il contenuto Snippets e ci si salva un file di vendor-data:
pvesm set cephfs --content iso,backup,vztmpl,snippets/mnt/pve/cephfs/snippets/web-vendor.yaml:
#cloud-config# vendor-data: si aggiunge allo user-data generato da Proxmox VE (utente, chiavi, rete)apt: http_proxy: http://proxy.proxmox.community:3128 https_proxy: http://proxy.proxmox.community:3128package_update: truepackages: - qemu-guest-agent - nginxruncmd: - systemctl enable --now qemu-guest-agent - echo "<h1>$(hostname) - creata dal template 9000</h1>" > /var/www/html/index.htmlVolid Format Type Size VMIDcephfs:snippets/web-vendor.yaml snippet snippets 408Lo snippet configura il proxy per apt, installa guest agent e nginx e scrive una pagina con il nome della VM.
9. Tre VM da template, su tre nodi, da CLI
Sezione intitolata “9. Tre VM da template, su tre nodi, da CLI”qm agisce solo sulle VM del nodo su cui si lancia; per lavorare su tutto il cluster da un solo nodo si usa l’API con pvesh:
for i in 1 2 3; do id=$((103+i)); n=desopve0$i pvesh create /nodes/desopve01/qemu/9000/clone --newid $id --name web0$i --target $n pvesh set /nodes/$n/qemu/$id/config --ipconfig0 ip=172.27.199.$id/24,gw=172.27.199.1 \ --cicustom vendor=cephfs:snippets/web-vendor.yaml pvesh create /nodes/$n/qemu/$id/status/startdoneTempo di ogni clone, misurato con date prima e dopo il comando:
clone 9000 -> 104 su desopve01: 2.5 sclone 9000 -> 105 su desopve02: 5.7 sclone 9000 -> 106 su desopve03: 2.9 sIl linked clone su un altro nodo funziona perché rbd-vm è condiviso. Dopo circa un minuto, il tempo di installare i pacchetti, le tre VM rispondono:
for id in 104 105 106; do curl -s http://172.27.199.$id/; done<h1>web01 - creata dal template 9000</h1><h1>web02 - creata dal template 9000</h1><h1>web03 - creata dal template 9000</h1>Il guest agent risponde su tutti e tre i nodi:
for p in "desopve01 104" "desopve02 105" "desopve03 106"; do set -- $p pvesh create /nodes/$1/qemu/$2/agent/ping && echo "agent VM $2 su $1: ok"; doneagent VM 104 su desopve01: okagent VM 105 su desopve02: okagent VM 106 su desopve03: oke cloud-init ha finito:
# su desopve02, che ospita la VM 105qm guest exec 105 -- cloud-init statusstatus: doneVerifica e test
Sezione intitolata “Verifica e test”- Il template 9000 ha il disco base
base-9000-disk-0con lo snapshot__base__su Ceph. - Un linked clone si crea in 2 secondi e occupa 12 MiB; un full clone dello stesso disco su ZFS richiede 12 secondi e 542 MiB.
- Un clone verso un altro nodo su uno storage locale viene rifiutato: serve uno storage condiviso.
- Con
ip=dhcpsu una VNet con IPAM il clone riceve l’indirizzo assegnato dall’IPAM. - Un vendor snippet su storage condiviso installa pacchetti e servizi al primo avvio, su qualsiasi nodo.
- Tre VM complete partono da template con un ciclo di
pvesh, e in un minuto servono una pagina web e rispondono al guest agent.
Stato finale del lab
Sezione intitolata “Stato finale del lab”- Template 9000
debian13-cloudsudesopve01, disco surbd-vm: utentelabuser, chiave del DC,ipconfig0 ip=dhcp,ciupgrade 0. - VM 104-106
web01-web03, linked clone del template, accese sudesopve01,02e03, indirizzi 172.27.199.104-106: nginx e guest agent, snippetvendor=cephfs:snippets/web-vendor.yaml. Servono come carico per i lab di backup, migrazione e HA. - Storage
cephfs: contenutosnippetsattivo, conweb-vendor.yaml. - VM 102 e 103: eliminate con
qm stop <id> && qm destroy <id> --purge, insieme ai loro dischi e all’indirizzo nell’IPAM.
Cosa hai imparato
Sezione intitolata “Cosa hai imparato”- Un’immagine cloud con un drive Cloud-Init diventa un template riusabile in pochi comandi;
import-fromimporta il disco in un passo. - I linked clone sono istantanei e leggeri ma legati al template e al suo storage; i full clone sono indipendenti e più lenti.
- Il clone su un altro nodo richiede uno storage condiviso.
- Cloud-init applica nome, utente, chiavi e rete al primo avvio, e allarga da solo il disco.
qm cloudinit dumpmostra esattamente ciò che riceve il guest.- Con un vendor snippet si aggiungono pacchetti e comandi senza perdere la configurazione della scheda Cloud-Init.
- Per automatizzare su tutto il cluster si usa
pvesh, perchéqmvede solo le VM del nodo locale.