Cloud-Init - Templates Proxmox
Cloud-Init permet de provisionner automatiquement les VMs créées depuis un template : hostname, utilisateur, clés SSH, packages, scripts de démarrage. Sur Proxmox, les paramètres cloud-init sont injectés via un lecteur ide2 dédié et peuvent être enrichis avec un fichier vendor-data stocké dans les snippets.
Prérequis
Sur le nœud Proxmox où le template sera créé :
apt install libguestfs-tools
Le stockage local doit avoir le type snippets activé dans Datacenter → Storage → local → Content.
Création du template
Étape 1 - Télécharger l’image cloud
cd /var/lib/vz/template/iso/
wget https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2
Étape 2 - Pré-installer les packages dans l’image
virt-customize modifie l’image avant le premier démarrage - permet d’éviter de dépendre du réseau pour les packages critiques.
virt-customize -a debian-13-genericcloud-amd64.qcow2 --install sudo,qemu-guest-agent
Étape 3 - Créer la VM
qm create 9999901 \
--name debian13-cloud \
--memory 2048 \
--balloon 0 \
--cores 1 \
--sockets 1 \
--cpu host \
--machine q35 \
--numa 1 \
--net0 virtio,bridge=vmbr0 \
--hotplug disk,network,memory \
--onboot 1 \
--agent 1,fstrim_cloned_disks=1
--balloon 0: désactive le ballooning mémoire (non adapté aux VMs avec charge prévisible)--cpu host: expose les instructions CPU du nœud à la VM (meilleures performances)--machine q35: chipset moderne, requis pour PCIe, NVMe et certaines fonctions UEFI--numa 1: active la topologie NUMA (pertinent sur nœuds multi-socket)--agent 1,fstrim_cloned_disks=1: active le qemu-guest-agent et le fstrim automatique des disques clonés
Étape 4 - Importer le disque
qm importdisk 9999901 debian-13-genericcloud-amd64.qcow2 educeph --format qcow2
Après l’import, le disque apparaît comme unused0 dans la conf. L’attacher avec les options de performance :
qm set 9999901 \
--scsihw virtio-scsi-single \
--scsi0 educeph:vm-9999901-disk-0,discard=on,iothread=1,ssd=1
virtio-scsi-single: un contrôleur par disque, permet l’iothread dédiédiscard=on: propage le TRIM/UNMAP au stockage Cephiothread=1: thread I/O dédié à ce disque (meilleures performances)ssd=1: expose le disque comme SSD à l’OS (optimise les comportements d’écriture)
Étape 5 - Configurer le lecteur cloud-init et le boot
# Lecteur cloud-init sur Ceph
qm set 9999901 --ide2 educeph:cloudinit
# Ordre de démarrage
qm set 9999901 --boot order=scsi0
# Console série (requis pour cloud-init sur cloud images)
qm set 9999901 --serial0 socket --vga serial0
# Utilisateur et IP par défaut
qm set 9999901 --ciuser root --ipconfig0 ip=dhcp
Étape 6 - Associer le fichier vendor-data
qm set 9999901 --cicustom "vendor=local:snippets/vendor-data"
Étape 7 - Protéger et convertir en template
# Protection contre la suppression accidentelle
qm set 9999901 --protection 1
# Conversion en template (irréversible)
qm template 9999901
Fichier vendor-data
Le vendor-data est appliqué après le user-data généré par Proxmox (hostname, utilisateur, clé SSH de l’interface). Il permet d’ajouter des customisations sans écraser ce que Proxmox injecte.
Les packages, clé SSH et utilisateur root sont configurés via l’onglet Cloud-Init dans l’interface Proxmox (ils sont injectés dans le user-data généré automatiquement). Le vendor-data se limite à l’exécution du script de post-configuration.
Créer le fichier sur le nœud Proxmox :
nano /var/lib/vz/snippets/vendor-data
Contenu :
#cloud-config
runcmd:
- /root/script-user-data.sh
vendor-data vs user-data : utiliser
vendor=dans--cicustompréserve leuser-datagénéré par Proxmox (hostname, utilisateur, clé SSH de l’interface). Utiliseruser=le remplace entièrement.
Script de post-configuration
Le script est embarqué dans l’image lors du virt-customize (voir étape 2). Il configure chrony pour utiliser la passerelle locale (VIP VRRP du segment) comme serveur NTP primaire.
nano /tmp/script-user-data.sh
Contenu :
#!/bin/bash
gateway=$(ip route | awk '/default/ {print $3}')
cat <<EOF > /etc/chrony/sources.d/10-custom.sources
# Local NTP Server
server $gateway iburst prefer
# Fallback NTP Pool
pool fr.pool.ntp.org iburst maxsources 2
EOF
systemctl enable chrony && systemctl restart chrony
Embarquer le script dans l’image avec virt-customize :
virt-customize -a debian-13-genericcloud-amd64.qcow2 \
--install sudo,qemu-guest-agent \
--upload /tmp/script-user-data.sh:/root/script-user-data.sh \
--run-command "chmod +x /root/script-user-data.sh"
Au premier démarrage, cloud-init exécute /root/script-user-data.sh qui détecte automatiquement la passerelle du segment et configure chrony. Chaque VM clonée pointe ainsi vers le FW de son propre segment sans configuration manuelle.
Vérifier ce que Proxmox génère pour une VM donnée :
qm cloudinit dump <vmid> user
Clonage et utilisation
Depuis le template, cloner une nouvelle VM :
qm clone 9999901 <nouveau-vmid> --name <hostname> --full --storage educeph
Au premier démarrage, cloud-init :
- Applique le
user-dataProxmox (hostname, utilisateur, clé SSH de l’interface GUI) - Applique le
vendor-data(packages, runcmd, clé SSH supplémentaire)
Problèmes connus
disk unused après importdisk
Après qm importdisk, le disque n’est pas automatiquement attaché - il reste en unused0 dans la conf. Toujours suivre avec qm set --scsi0 pour l’attacher.
vendor-data non appliqué
Si le fichier vendor-data n’est pas dans /var/lib/vz/snippets/ ou que le stockage local n’a pas Snippets activé dans son Content, cloud-init ignore silencieusement le fichier.