Dawan Proxmox VE — TSSR

Chapitre 2 — Machines Virtuelles KVM

Ateliers — chapitre 2

Infrastructure : nœud pxe2<N>1 (même nœud que le Chapitre 1 — les conteneurs LXC restent en place)


État du lab en fin de chapitre :

  • VM 105 vm-debian installée depuis l'ISO, adresse fixe .54, second disque de 6 Gio, un instantané et une sauvegarde (ateliers 2 à 6). VM 110 vm-debian-restauree, carte débranchée, arrêtée ou supprimée
  • Template debian13-template (VMID 100) créé via image cloud + cloud-init, nettoyé, converti en template en lecture seule (ateliers 7 à 9)
  • Deux clones de production (VM 101 vm-web-01, VM 102 vm-web-02) avec IP statiques (ateliers 8 et 9)
  • Template 106 debian-modele, tiré de la VM 105 et nettoyé à la main, et son clone lié VM 107 vm-classique-01 en .58, personnalisé dans sa console (atelier 9, partie B)

Atelier 1 — Vérifier les prérequis KVM

Contexte

Avant de créer la moindre VM KVM, deux vérifications s'imposent — et les sauter est la cause des deux pannes les plus fréquentes du chapitre. D'abord, le processeur du nœud doit exposer ses extensions de virtualisation matérielle (Intel VT-x ou AMD-V) : sans elles, les VMs démarrent en émulation logicielle, lentes au point d'être inutilisables.

Ensuite, le pool de stockage doit avoir de la place : une VM en provisionnement fin qui remplit un pool saturé fige toutes les autres.

Résultat à obtenir : la confirmation que la virtualisation matérielle est active sur le nœud. La preuve que ce nœud est lui-même une machine virtuelle capable d'en héberger d'autres. Et une lecture claire du taux de remplissage du pool local-lvm, avant d'y créer des VMs.

Trois étages de virtualisation : serveur de la salle, nœud pxe211, VM capable d'être un hyperviseur

Les trois étages que l'atelier fait prouver, du serveur de la salle à une VM qui peut elle-même héberger des VM. Cliquez sur un étage pour la commande qui le prouve et le résultat obtenu.

Arborescence attendue

Aucun fichier produit : deux vérifications en ligne de commande,
depuis le Shell du nœud.

Ce que vous devez faire

  1. Vérifier les extensions CPU : chercher vmx (Intel) ou svm (AMD) dans /proc/cpuinfo, et confirmer que le module KVM est bien chargé.
  2. Un cran plus loin : votre nœud est lui-même une VM. Prouvez-le, puis montrez qu'il peut quand même faire tourner des VM KVM, et même laisser ses VM en faire autant (virtualisation imbriquée).
  3. Évaluer le pool LVM-thin : lire le taux d'occupation des données et des métadonnées du pool. Demandez-vous ce qui se passerait si les métadonnées atteignaient 100 % — c'est un piège moins connu que le remplissage des données.
Cliquez pour vous aider

Étape 1 — Extensions de virtualisation CPU

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Vérifier VT-x (Intel) ou AMD-V : une ligne « flags » par cœur logique
nproc
grep -c "^flags.*vmx" /proc/cpuinfo   # Intel
grep -c "^flags.*svm" /proc/cpuinfo   # AMD (l'un ou l'autre)

# Vérifier les modules KVM chargés
lsmod | grep ^kvm

Résultat attendu (nœud pxe211, 4 vCPU Intel) :

4
4
0
kvm_intel             507904  0
kvm                  1445888  1 kvm_intel

Un nombre supérieur à 0 pour vmx ou svm suffit : c'est le nombre de cœurs logiques qui annoncent l'extension, ici autant que nproc. Ne comptez pas avec un simple grep -c vmx : les noyaux récents ajoutent une ligne vmx flags par cœur, et le compte double (8 sur le lab).

kvm_intel (ou kvm_amd) doit figurer à côté de kvm : c'est lui qui parle au processeur. Si seul kvm apparaît, l'extension est désactivée dans le BIOS.

Étape 1 bis — Un hyperviseur dans un hyperviseur

Votre nœud n'est pas un serveur physique : c'est une VM, installée sur un serveur de la salle. Pour qu'il héberge à son tour des VM KVM, le serveur de la salle doit lui transmettre les extensions du processeur. C'est la virtualisation imbriquée (nested).

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Sur quoi tourne ce système ? « none » sur du matériel, le nom de l'hyperviseur sinon
systemd-detect-virt
# Le périphérique par lequel QEMU parle au module KVM
ls -l /dev/kvm
# Ce nœud laisse-t-il ses propres VM utiliser KVM à leur tour ? (Intel, puis AMD)
cat /sys/module/kvm_intel/parameters/nested
cat /sys/module/kvm_amd/parameters/nested   # même question, processeur AMD

Résultat attendu (nœud pxe211, processeur Intel) :

kvm
crw-rw---- 1 root kvm 10, 232 Sep 28 07:46 /dev/kvm
Y
cat: /sys/module/kvm_amd/parameters/nested: No such file or directory

Un seul des deux fichiers existe : celui du module du processeur. Sur un nœud Intel, la question AMD répond No such file or directory, et inversement : c'est normal.

Trois étages se lisent ici :

Étage Ce qui le prouve
le serveur de la salle fait tourner votre nœud systemd-detect-virt répond kvm
votre nœud peut faire tourner des VM le drapeau vmx/svm de l'étape 1 et /dev/kvm
une VM de votre nœud pourrait en faire tourner d'autres nested vaut Y (ou 1)

C'est ce troisième étage, la virtualisation imbriquée, qui permettrait d'installer un Proxmox dans une VM de votre nœud. Le formateur l'a fait sur son poste à l'atelier 1 du chapitre 1.

Sur un serveur physique, systemd-detect-virt répondrait none. Et si /dev/kvm manquait, Proxmox ne pourrait démarrer une VM qu'en désactivant l'accélération (option KVM hardware virtualization à No), avec des performances très dégradées.

Étape 2 — État du pool LVM-thin

Le pool LVM-thin local-lvm est le stockage par défaut pour les disques VM.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Remplissage des données ET des métadonnées du pool thin
lvs -o name,size,data_percent,metadata_percent pve/data

Résultat attendu (pool presque vide, avec le seul CT 200) :

  LV   LSize   Data%  Meta%
  data 129.87g 0.74   1.66

Data% est le remplissage des blocs de données, Meta% celui de la table qui dit à quel volume appartient chaque bloc. Les deux saturent indépendamment.

Un pool rempli à 40 % de données mais à 100 % de métadonnées gèle ses VM tout autant. C'est le piège de la question posée plus haut : on l'évite en surveillant les deux colonnes.

Règle des 70% : ne jamais dépasser 70% de remplissage d'un pool LVM-thin. Le thin provisioning alloue l'espace à la demande.

Au-delà de ce seuil, les performances I/O chutent. Le risque de saturation complète augmente fortement ; elle bloque toutes les écritures sur le pool, VMs comprises.


Atelier 2 — Créer et installer une VM Debian depuis l'ISO

Contexte

Votre première machine virtuelle, de bout en bout. Vous la créez avec l'assistant Create VM, puis vous installez Debian depuis l'ISO avec une adresse IP fixe. Vous vérifiez enfin qu'elle démarre seule sur son disque et qu'on peut s'y connecter.

C'est la VM 105 vm-debian : elle sert à tous les ateliers suivants jusqu'à l'atelier 6 (cycle de vie, stockage, agent, instantanés).

Cours : §3 (médias) et §4 (créer une VM).

Résultat à obtenir : la VM 105 vm-debian, 2 cœurs, 2 Gio de mémoire, disque de 20 Gio sur local-lvm, carte VirtIO sur vmbr0. Elle est installée depuis l'ISO Debian 13 et démarre sur son disque avec l'adresse fixe 10.<site>.<N>.54/24 et un compte devops qui a les droits sudo.

Atelier 2 : la VM 105 installée depuis l'ISO

Le schéma suit la VM 105 de l'ISO à la première connexion SSH. Cliquez sur chaque bloc pour les valeurs à saisir.

Arborescence attendue

local → ISO Images
└── debian-13.6.0-amd64-netinst.iso     ← téléchargée au chapitre 1

VM 105 « vm-debian »
├── scsi0 : local-lvm, 20 Gio           ← disque système
├── ide2  : l'ISO, retirée après l'installation (atelier 3)
└── net0  : VirtIO sur vmbr0            ← adresse fixe 10.<site>.<N>.54 dans Debian

Ce que vous devez faire

  1. Vérifier que l'ISO Debian 13 est dans le stockage local (chapitre 1).
  2. Créer la VM 105 avec l'assistant Create VM, onglet par onglet, avec les valeurs du tableau de la solution. Repérer ensuite l'option qm create qui correspond à chaque champ.

    Cochez la case Advanced en bas de l'assistant. Relevez, sans les modifier, trois valeurs par défaut : le Shutdown timeout (onglet General), la case Backup du disque (Disks) et les CPU units (CPU).

  3. La démarrer et l'installer depuis sa console : français, adresse fixe 10.<site>.<N>.54/24 (jamais de DHCP), utilisateur devops, sans environnement de bureau, avec le serveur SSH.

  4. Vérifier, après le redémarrage, qu'elle démarre sur son disque et qu'elle a bien son adresse IPv4 ; corriger si besoin.
  5. Se connecter depuis le Shell du nœud : ssh devops@10.<site>.<N>.54.
Cliquez pour vous aider

Machine d'exemple : les captures ont été prises sur pxe212 (Proxmox VE 9.2.21), où la VM 105 était en 192.168.1.154. Les résultats en texte viennent du lab passé sur le plan des stagiaires (pxe211, VM 105 en 10.59.1.54). Chez vous : 10.<site>.<N>.54.

Étape 1 — Créer la VM avec l'assistant

En haut à droite, Create VM. Remplissez les onglets dans l'ordre :

Onglet Champ Valeur
General Node / VM ID / Name votre nœud / 105 / vm-debian
OS ISO image debian-13.6.0-amd64-netinst.iso (stockage local)
OS Type / Version Linux / 7.x - 2.6 Kernel (proposé d'office)
System Qemu Agent coché
System Machine q35 (le défaut est i440fx : à changer)
System BIOS / SCSI Controller laissés par défaut : SeaBIOS, VirtIO SCSI single
Disks Storage / Disk size local-lvm / 20
CPU Sockets / Cores / Type 1 / 2 / laissé par défaut (x86-64-v2-AES)
Memory Memory (MiB) 2048
Network Bridge / Model vmbr0 / VirtIO (paravirtualized)
Confirm Start after created décoché

Les options avancées. Cochez Advanced, en bas à droite de l'assistant : chaque onglet affiche des champs de plus, sous un trait. On les laisse tous par défaut.

Les trois valeurs demandées : Shutdown timeout default, soit 180 secondes laissées à la VM pour s'éteindre avant un arrêt forcé. Backup est coché : le disque est inclus dans les sauvegardes. CPU units vaut 100, le poids de la VM quand le processeur du nœud est saturé.

Le rôle de chaque champ avancé est détaillé au cours §4.1.

Assistant Create VM, onglet General : VM ID 105, nom vm-debian

L'onglet General : le nœud, le numéro et le nom. Le numéro doit être libre sur tout le cluster.

Onglet OS : l'ISO Debian choisie dans le stockage local

L'onglet OS : le lecteur CD de la VM reçoit l'ISO. Le type Linux, version 7.x - 2.6 Kernel, règle des optimisations propres à Linux.

Onglet System : Machine q35, Qemu Agent coché, BIOS et contrôleur SCSI par défaut

L'onglet System : Machine passe de Default (i440fx) à q35, les deux seuls choix de la liste. Cochez Qemu Agent, qui prépare le canal avec l'agent invité (atelier 5). BIOS et contrôleur SCSI restent par défaut.

Pourquoi q35. Le champ Machine choisit la carte mère que QEMU simule. i440fx reproduit un chipset Intel de 1996, avec un bus PCI.

q35 reproduit un chipset Intel plus récent, qui fournit un bus PCI Express virtuel. La documentation de Proxmox le recommande quand on veut faire passer une carte PCIe physique à la VM (passthrough), et c'est avec q35 qu'on peut activer un vIOMMU.

C'est aussi le choix des VM des ateliers suivants : le template de l'atelier 7 est en q35. Sur le lab, Debian nomme sa carte ens18 dans les deux cas : l'adresse fixe de l'installation ne change pas.

Onglet Disks : 20 Gio sur local-lvm

L'onglet Disks : un disque SCSI de 20 Gio sur local-lvm, avec IO thread coché d'office.

Onglet CPU : 1 socket, 2 cœurs, type par défaut x86-64-v2-AES

L'onglet CPU : 1 socket, 2 cœurs. Le type par défaut, x86-64-v2-AES, permet de migrer la VM vers n'importe quel nœud d'un cluster.

Onglet Memory : 2048 Mio

L'onglet Memory : 2048 Mio. Le ballooning est présenté au cours, §7.4.

Onglet Network : vmbr0, modèle VirtIO, pare-feu coché

L'onglet Network : la carte se branche sur vmbr0 ; le modèle VirtIO est le plus rapide (cours §7.1). La case Firewall cochée ne filtre rien tant que le pare-feu n'est pas activé.

Onglet Confirm : la configuration envoyée, machine q35, Start after created décoché

L'onglet Confirm liste exactement ce qui part vers Proxmox : agent 1, cores 2, cpu x86-64-v2-AES, ide2 (l'ISO), machine q35, memory 2048, net0 virtio,bridge=vmbr0,firewall=1, scsi0 local-lvm:20,iothread=on. Laissez Start after created décoché, puis Finish.

La même VM en ligne de commande. Chaque champ de l'assistant correspond à une option de qm create :

Onglet Champ de l'assistant Option qm create
General VM ID / Name 105 / --name vm-debian
OS ISO image --ide2 local:iso/debian-13.6.0-amd64-netinst.iso,media=cdrom
OS Type / Version : Linux, 7.x - 2.6 Kernel --ostype l26
System Machine --machine q35
System Qemu Agent --agent 1
System SCSI Controller --scsihw virtio-scsi-single
Disks Storage / Disk size / IO thread --scsi0 local-lvm:20,iothread=1
CPU Sockets / Cores / Type --sockets 1 --cores 2 --cpu x86-64-v2-AES
Memory Memory (MiB) --memory 2048
Network Bridge / Model / Firewall --net0 virtio,bridge=vmbr0,firewall=1
(ordre fixé par l'assistant) — --boot 'order=scsi0;ide2;net0'

Si vous créez la VM en ligne de commande à la place de l'assistant :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# La même VM que l'assistant, en une commande
qm create 105 \
  --name vm-debian \
  --ostype l26 \
  --machine q35 \
  --ide2 local:iso/debian-13.6.0-amd64-netinst.iso,media=cdrom \
  --agent 1 \
  --scsihw virtio-scsi-single \
  --scsi0 local-lvm:20,iothread=1 \
  --sockets 1 --cores 2 --cpu x86-64-v2-AES \
  --memory 2048 \
  --net0 virtio,bridge=vmbr0,firewall=1 \
  --boot 'order=scsi0;ide2;net0'

Résultat attendu (sur une VM de test 9106, supprimée ensuite) : scsi0: successfully created disk 'local-lvm:vm-9106-disk-0,iothread=1,size=20G', précédé d'avertissements de LVM sur le provisionnement fin (cours §6). qm config y montre machine: q35, boot: order=scsi0;ide2;net0 et scsi0: …,iothread=1,size=20G : la configuration est celle de l'assistant.

Dans les deux cas, vérifiez la configuration créée :

qm config 105   # la configuration créée, par l'assistant ou par qm create

Résultat attendu — l'essentiel, sur la VM 105 du lab, créée en i440fx. Avec q35, la configuration porte une ligne de plus, machine: q35 (sur la VM de test 9106) :

agent: 1
boot: order=scsi0;ide2;net0
cores: 2
cpu: x86-64-v2-AES
ide2: local:iso/debian-13.6.0-amd64-netinst.iso,media=cdrom,size=755M
memory: 2048
name: vm-debian
net0: virtio=BC:24:11:98:4E:62,bridge=vmbr0,firewall=1
scsi0: local-lvm:vm-105-disk-0,iothread=1,size=20G
scsihw: virtio-scsi-single

L'assistant a placé le disque avant le CD dans l'ordre de démarrage (order=scsi0;ide2;net0). Le disque vide est sauté au premier démarrage, et l'installateur se lance depuis le CD. La VM démarrera ensuite sur son disque une fois Debian installé.

Étape 2 — Installer Debian depuis la console

VM 105 → Start, puis Console. Dans le menu de l'installateur, Graphical install. Les écrans s'enchaînent ; voici les choix, dans l'ordre :

Écran Choix
Langue, pays, clavier Français, France, Français
Configurer le réseau adresse fixe (voir ci-dessous)
Nom de machine / Domaine vm-debian / champ vidé
Mot de passe du superutilisateur (« root ») laissé vide, deux fois : le compte root est bloqué et le premier utilisateur reçoit sudo
Nom complet / Identifiant / Mot de passe devops / devops / dawan
Partitionner les disques Assisté - utiliser un disque entier → le disque de 20 Gio → Tout dans une seule partition → Terminer → Oui
Analyser d'autres supports Non
Miroir de l'archive Debian France → deb.debian.org
Mandataire HTTP vide : la VM télécharge ses paquets directement sur Internet. Facultatif : http://10.<site>.<N>.50:3142, le cache apt du conteneur 200 (cours du chapitre 1, §13) ; la VM dépend alors de ce conteneur pour chaque apt
popularity-contest Non
Sélection des logiciels décocher « environnement de bureau Debian » et le bureau GNOME (environnement graphique, case « GNOME »), cocher « serveur SSH »
Programme de démarrage GRUB (GRand Unified Bootloader) Oui → /dev/sda

Le réseau, en adresse fixe. Si le réseau a un serveur DHCP, l'installateur prend une adresse seul et saute au nom de machine. Revenez alors en arrière (Revenir en arrière ou Échap), choisissez Configurer vous-même le réseau, puis saisissez l'adresse avec son masque :

Installateur : l'adresse IP fixe saisie avec son masque /24

Puis la passerelle et le serveur de noms, proposés d'office en .1. Gardez la passerelle 10.<site>.<N>.1, mais remplacez le serveur de noms : sur le lab Dawan, la passerelle du réseau NATé ne répond pas aux requêtes DNS.

Saisissez le DNS de l'hôte, 192.168.<site>.1 : 192.168.44.1 à Nantes, 192.168.75.1 à Paris, 192.168.67.1 à Strasbourg. Sans cela, l'installateur ne joint pas le miroir Debian, et la VM ne résout aucun nom.

Installateur : le mot de passe root laissé vide

Laisser le mot de passe root vide est le choix le plus sûr : on n'ouvre pas de session root. L'administration passe alors par sudo, comme sur les VM cloud du chapitre.

Installateur : le partitionnement assisté, disque entier

Installateur : le résultat, une partition ext4 et un swap

Sur le lab : une partition ext4 de 20,3 Go montée sur / et un swap de 1,2 Go. À la question Faut-il appliquer les changements sur les disques ?, la réponse proposée est Non : choisissez Oui.

Installateur : sélection des logiciels, bureau décoché, serveur SSH coché

Un serveur n'a pas besoin de bureau graphique. Cochez la case avec la barre d'espace ; la touche Entrée coche ou décoche aussi la ligne sélectionnée au lieu de valider : passez sur Continuer avec la touche Tab.

Installateur : GRUB, « Choix manuel du périphérique » sélectionné d'office

Piège : la ligne sélectionnée d'office est Choix manuel du périphérique. Choisissez /dev/sda.

L'installation se termine par Installation terminée : Continuer, la VM redémarre. Comptez une dizaine de minutes en tout.

Étape 3 — Vérifier le réseau au premier démarrage

Connectez-vous en devops.

Dans la console de la VM :

ip -br a   # les adresses de la VM

Sur le lab, sur un réseau qui annonce de l'IPv6 : aucune adresse IPv4, seulement de l'IPv6, malgré la saisie manuelle de l'adresse.

Console de la VM : ip -br a sans IPv4, et /etc/network/interfaces en inet6 auto

cat /etc/network/interfaces montre pourquoi : l'installateur a écrit iface ens18 inet6 auto, sans ligne inet static. Si ip -br a affiche bien votre 10.<site>.<N>.54/24, passez à l'étape 4. Sinon, corrigez.

Dans la console de la VM :

sudo nano /etc/network/interfaces.d/ens18   # la carte en adresse fixe, dans un fichier à part

Le contenu de ens18, à taper dans nano, puis Ctrl + O, Entrée et Ctrl + X :

auto ens18
iface ens18 inet static
    address 10.<site>.<N>.54/24
    gateway 10.<site>.<N>.1

Dans la console de la VM :

sudo nano /etc/network/interfaces           # désactiver les deux lignes écrites par l'installateur

Dans nano, ajoutez un # au début des deux lignes allow-hotplug ens18 et iface ens18 inet6 auto, puis enregistrez. Une ligne qui commence par # est ignorée.

Dans la console de la VM :

sudo reboot                                 # redémarrer pour appliquer

Résultat attendu : après redémarrage, la VM répond au ping depuis le nœud sur son adresse fixe. /etc/network/interfaces lit tous les fichiers de /etc/network/interfaces.d/ grâce à sa ligne source.

Étape 4 — Se connecter depuis le nœud

Dans le Shell du nœud (interface web → votre nœud → Shell), puis dans la VM :

ssh devops@10.<site>.<N>.54                 # mot de passe : dawan
hostname                                    # le nom de la VM
ip -br a show ens18                         # son adresse
df -h /                                     # son disque
exit                                        # retour au nœud

Résultat attendu :

vm-debian
ens18            UP             10.59.1.54/24 fe80::be24:11ff:fe98:4e62/64
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/sda1           19G    1,3G   17G   8% /

Le système installé occupe 1,3 Go. L'adresse IPv6 n'apparaît que si votre réseau en distribue.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm status 105                                 # la VM tourne
qm config 105   # démarrage, disque, carte ; à lire : boot, scsi0, net0
ping -c 2 10.<site>.<N>.54                     # elle répond à son adresse fixe

Résultat attendu (les lignes qui comptent) : status: running, boot: order=scsi0;ide2;net0, le disque de 20 Gio et la carte VirtIO, puis deux réponses au ping.

À garder : la VM 105 reste allumée pour l'atelier 3.


Atelier 3 — Console et cycle de vie de la VM

Contexte

Une VM se démarre, s'arrête proprement ou brutalement, redémarre, et chaque action laisse une trace. Vous pilotez la VM 105 par l'interface puis par qm, vous lisez l'historique des tâches, et vous terminez son installation : retirer l'ISO, la faire démarrer avec le nœud.

Cours : §5 (console et cycle de vie).

Résultat à obtenir : la différence entre Shutdown et Stop constatée sur la VM 105, et ses dernières tâches lues avec leur identifiant (UPID : Unique Process ID). L'ISO est retirée du lecteur CD, et la VM est réglée pour démarrer avec le nœud.

Atelier 3 : console et cycle de vie de la VM 105

Le schéma oppose l'arrêt propre et l'arrêt brutal, entre la lecture de l'état et les réglages finaux. Cliquez sur chaque bloc pour son détail.

Arborescence attendue

VM 105 « vm-debian »
├── ide2   : none, media=cdrom    ← l'ISO retirée
└── onboot : 1                    ← démarre avec le nœud

Ce que vous devez faire

  1. Ouvrir la console noVNC de la VM 105, puis lire son état avec qm status.
  2. Arrêter proprement la VM (Shutdown / qm shutdown), la redémarrer, puis l'arrêter brutalement (Stop / qm stop) : quelle différence pour le système invité ?
  3. Lire l'historique des tâches de la VM : dans l'interface (panneau Tasks) et en ligne de commande.
  4. Retirer l'ISO du lecteur CD et activer le démarrage automatique (onboot).
Cliquez pour vous aider

Machine d'exemple : nœud pxe212, VM 105.

Étape 1 — L'état de la VM

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm status 105              # en marche ou arrêtée
qm status 105 --verbose   # le détail ; à lire : status, qmpstatus, uptime, pid, name, maxmem, cpus

Résultat attendu (les lignes qui comptent) :

status: running
cpus: 2
maxmem: 2147483648
name: vm-debian
pid: 9151
qmpstatus: running
status: running
uptime: 61

pid est le processus QEMU de la VM sur le nœud (cours §2.3) ; uptime compte les secondes depuis son démarrage.

Étape 2 — Shutdown, puis Stop

Dans le Shell du nœud (interface web → votre nœud → Shell) :

time qm shutdown 105   # arrêt propre : le système invité ferme ses services
qm status 105          # l'état de la VM
qm start 105           # la redémarrer
time qm stop 105       # arrêt brutal : comme couper le courant
qm start 105           # la redémarrer

Résultat attendu : qm shutdown a rendu la main en 1,08 s puis status: stopped ; qm stop en 0,60 s.

Les deux durées se ressemblent, mais pas ce qui se passe dans la VM. Shutdown demande au système de s'arrêter (signal ACPI, ou l'agent s'il est installé) : Debian ferme ses services et écrit ses fichiers. Stop coupe le processus QEMU, comme on débranche une prise : à réserver à une VM qui ne répond plus.

Dans l'interface, ce sont les boutons Shutdown et Stop de la VM ; Reboot (qm reboot 105) enchaîne un arrêt propre et un démarrage.

Étape 3 — L'historique des tâches

Chaque action laisse une tâche : panneau Tasks en bas de l'interface, ou onglet Task History de la VM. En ligne de commande :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

pvesh get /nodes/$(hostname)/tasks --limit 4 --noborder 1   # les 4 dernières tâches du nœud

Résultat attendu (extrait) :

ID  Node    PID pstart           Starttime Type       UPID                                                            User                 Endtime Status
105 pxe212 9451 225154 2026-10-06 12:56:08 qmstart    UPID:pxe212:000024EB:00036F82:6AC4D3C8:qmstart:105:root@pam:    root@pam 2026-10-06 12:56:08 OK
105 pxe212 9428 225003 2026-10-06 12:56:06 qmshutdown UPID:pxe212:000024D4:00036EEB:6AC4D3C6:qmshutdown:105:root@pam: root@pam 2026-10-06 12:56:07 OK

L'UPID identifie la tâche : nœud, processus, heure, type (qmstart, qmshutdown), VM et utilisateur. C'est lui qu'on cite quand on cherche la cause d'un échec (cours §5.3).

Étape 4 — Retirer l'ISO, démarrer avec le nœud

L'installation est faite : l'ISO n'a plus rien à faire dans le lecteur. VM 105 → Hardware → CD/DVD Drive → Edit → Do not use any media ; puis Options → Start at boot → Yes. En ligne de commande :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm set 105 --ide2 none,media=cdrom   # vider le lecteur CD
qm set 105 --onboot 1                # démarrer avec le nœud
qm config 105   # vérifier ; à lire : boot, ide2, onboot

Résultat attendu (les lignes qui comptent) :

update VM 105: -ide2 none,media=cdrom
update VM 105: -onboot 1
boot: order=scsi0;ide2;net0
ide2: none,media=cdrom
onboot: 1

Une ISO laissée dans le lecteur bloque la migration de la VM vers un autre nœud : on la retire dès l'installation finie.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm status 105                              # la VM tourne
qm config 105   # lecteur vide, démarrage avec le nœud ; à lire : ide2, onboot

Résultat attendu (les lignes qui comptent) : status: running, ide2: none,media=cdrom, onboot: 1.


Atelier 4 — Le stockage de la VM : provisionnement fin et second disque

Contexte

Le disque de 20 Gio de la VM 105 n'occupe sur local-lvm que ce qu'elle a réellement écrit : c'est le provisionnement fin (thin provisioning). Vous le mesurez, vous ajoutez à la VM un second disque pour ses données, vous le remplissez, puis vous l'agrandissez sans arrêter la VM.

Cours : §6 (stockage LVM-thin).

Résultat à obtenir : le remplissage réel des disques de la VM 105 lu avec lvs, et un second disque de 4 Gio ajouté, formaté et monté sur /srv/donnees. Ce disque est ensuite agrandi à 6 Gio à chaud, système de fichiers compris.

Atelier 4 : provisionnement fin et second disque

Le schéma suit les disques de la VM 105, de la lecture de lvs à l'agrandissement. Cliquez sur chaque bloc pour son détail.

Arborescence attendue

VM 105 « vm-debian »
├── scsi0 : vm-105-disk-0, 20 Gio   ← système
└── scsi1 : vm-105-disk-1, 4 Gio, puis 6 Gio
            └── /srv/donnees (ext4)

Ce que vous devez faire

  1. Lire l'occupation réelle du disque de la VM avec lvs (colonne Data%).
  2. Ajouter un disque de 4 Gio à la VM, à chaud (Hardware → Add → Hard Disk).
  3. Dans la VM, le formater en ext4, le monter sur /srv/donnees, y écrire 1 Gio, puis relire lvs.
  4. L'agrandir de 2 Gio à chaud, puis étendre son système de fichiers.
Cliquez pour vous aider

Machine d'exemple : nœud pxe211, VM 105 en 10.59.1.54 (lab sur le plan des stagiaires) sur pxe212.

Étape 1 — Ce que le disque occupe vraiment

Dans le Shell du nœud (interface web → votre nœud → Shell) :

lvs pve/vm-105-disk-0   # le disque système de la VM

Résultat attendu :

  LV            VG  Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  vm-105-disk-0 pve Vwi-aotz-- 20.00g data        12.75

Le disque mesure 20 Gio pour la VM (LSize), mais n'occupe que 12,75 % de cette taille dans le pool data : les blocs que Debian a réellement écrits.

Étape 2 — Ajouter un second disque

VM 105 → Hardware → Add → Hard Disk : Bus SCSI, Storage local-lvm, Disk size 4, Discard coché. Ou :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm set 105 --scsi1 local-lvm:4,discard=on,iothread=1   # 4 Gio, à chaud

Résultat attendu :

update VM 105: -scsi1 local-lvm:4,discard=on,iothread=1
  Logical volume "vm-105-disk-1" created.
scsi1: successfully created disk 'local-lvm:vm-105-disk-1,discard=on,iothread=1,size=4G'

discard=on permet à la VM de signaler les blocs qu'elle libère, pour que le pool les récupère.

Étape 3 — Le formater, le monter, le remplir

Dans le Shell du nœud (interface web → votre nœud → Shell), puis dans la VM :

ssh devops@10.<site>.<N>.54                      # mot de passe : dawan
lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS             # le nouveau disque : sdb
sudo mkfs.ext4 -q -L donnees /dev/sdb           # un système de fichiers sur tout le disque
sudo mkdir -p /srv/donnees                      # le point de montage
sudo mount /dev/sdb /srv/donnees                # le monter
sudo dd if=/dev/urandom of=/srv/donnees/essai.bin bs=1M count=1000 status=none   # 1 Gio de données
sync                                            # tout écrire sur le disque
df -h /srv/donnees                              # l'espace occupé
exit                                            # retour au nœud

Résultat attendu — lsblk, puis df :

NAME    SIZE TYPE MOUNTPOINTS
sda      20G disk
├─sda1 18,9G part /
├─sda2    1K part
└─sda5  1,1G part [SWAP]
sdb       4G disk
sr0    1024M rom
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/sdb           3,9G   1002M  2,7G  27% /srv/donnees

Puis, sur le nœud, lvs pve/vm-105-disk-1 pve/data : le nouveau disque est passé à 26.07 % et le pool entier à 30.29 %. Le pool ne se remplit qu'au fil des écritures des VM : c'est pourquoi on le surveille (cours §6.2).

Étape 4 — Agrandir à chaud

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm resize 105 scsi1 +2G   # le disque passe de 4 à 6 Gio, VM en marche

Résultat attendu :

  Size of logical volume pve/vm-105-disk-1 changed from 4.00 GiB (1024 extents) to 6.00 GiB (1536 extents).
  Logical volume pve/vm-105-disk-1 successfully resized.

Dans la VM, lsblk /dev/sdb voit aussitôt 6 Gio, mais df affiche toujours 3,9 Gio : seul le disque a grandi, pas le système de fichiers (cours §6.4). On l'étend, toujours à chaud.

Dans le Shell du nœud, puis dans la VM :

ssh devops@10.<site>.<N>.54                 # mot de passe : dawan
sudo resize2fs /dev/sdb                     # étendre le système de fichiers
df -h /srv/donnees                          # la nouvelle taille
exit                                        # retour au nœud

Résultat attendu :

resize2fs 1.47.2 (1-Jan-2025)
Filesystem at /dev/sdb is mounted on /srv/donnees; on-line resizing required
The filesystem on /dev/sdb is now 1572864 (4k) blocks long.
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/sdb           5,9G   1002M  4,6G  18% /srv/donnees

Ce disque de données a son système de fichiers directement sur le disque, sans partition : une seule commande suffit. Sur un disque partitionné, il faut d'abord agrandir la partition (growpart, cours §6.4).

Le montage ne survit pas au redémarrage. mount vaut jusqu'au prochain arrêt. Pour le rendre permanent, on ajoute une ligne dans /etc/fstab : LABEL=donnees /srv/donnees ext4 defaults,nofail 0 2.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm config 105 | grep -E "^scsi"            # les deux disques de la VM
lvs pve/vm-105-disk-0 pve/vm-105-disk-1    # leurs volumes LVM-thin

Résultat attendu : scsi0 de 20 Gio et scsi1 de 6 Gio ; deux volumes dont Data% reste bien inférieur à 100 %.


Atelier 5 — L'agent QEMU

Contexte

L'agent invité est un petit programme installé dans la VM, qui répond à Proxmox par un canal dédié. Avec lui, Proxmox connaît l'adresse IP de la VM, l'arrête proprement et peut figer ses fichiers pendant une sauvegarde. Sur la VM 105, l'installateur Debian l'a déjà installé : vous vérifiez ce qu'il apporte.

Cours : §7.2 (agent QEMU).

Résultat à obtenir : l'agent de la VM 105 répond ; son adresse IP, son système et l'état de ses fichiers sont lus depuis le nœud. Une commande est exécutée dans la VM sans SSH.

Atelier 5 : l'agent QEMU de la VM 105

Le schéma part du canal et aboutit à ce que l'agent permet. Cliquez sur chaque bloc pour la commande correspondante.

Arborescence attendue

VM 105 « vm-debian »
├── option agent : 1                      ← le canal, côté Proxmox (atelier 2)
└── qemu-guest-agent (service actif)      ← le programme, dans Debian

Ce que vous devez faire

  1. Vérifier que l'option agent est active et que l'agent répond (qm agent 105 ping).
  2. Vérifier dans la VM que le paquet qemu-guest-agent est installé et son service actif.
  3. Lire depuis le nœud l'adresse IP de la VM, son système et l'état de ses systèmes de fichiers ; regarder la ligne IPs de l'onglet Summary.
  4. Exécuter une commande dans la VM depuis le nœud, avec qm guest exec.
Cliquez pour vous aider

Machine d'exemple : nœud pxe212, VM 105.

Étape 1 — L'agent répond-il ?

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm config 105 | grep ^agent   # le canal est-il ouvert côté Proxmox ?
qm agent 105 ping              # l'agent répond-il ?
echo "code : $?"               # son code

Résultat attendu : agent: 1, puis code : 0 : l'agent répond.

Étape 2 — Dans la VM

Dans le Shell du nœud, puis dans la VM :

ssh devops@10.<site>.<N>.54                 # mot de passe : dawan
systemctl is-active qemu-guest-agent        # le service
dpkg -l qemu-guest-agent                    # le paquet
exit                                        # retour au nœud

Résultat attendu : active, et le paquet qemu-guest-agent en version 1:10.0.13+ds-0+deb13u1, installé par l'installateur Debian : il l'ajoute de lui-même quand il détecte une machine virtuelle QEMU. Vous ne l'avez pas installé. Une image cloud, au contraire, n'a pas l'agent : vous le constaterez à l'atelier 8 ; il s'y installe avec apt install qemu-guest-agent, comme ici.

Étape 3 — Ce que Proxmox apprend grâce à l'agent

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm guest cmd 105 network-get-interfaces | grep -E '"ip-address"|"name"'   # les adresses de la VM
qm guest cmd 105 get-osinfo | grep pretty                                  # le système invité
qm guest cmd 105 fsfreeze-status                                           # fichiers figés ou non

Résultat attendu :

            "ip-address" : "127.0.0.1",
            "ip-address" : "::1",
      "name" : "lo",
            "ip-address" : "10.59.1.54",
            "ip-address" : "fe80::be24:11ff:fe98:4e62",
      "name" : "ens18",
   "pretty-name" : "Debian GNU/Linux 13 (trixie)",
thawed

Ce sont ces adresses que l'onglet Summary affiche sur la ligne IPs. thawed : les systèmes de fichiers ne sont pas figés. Une sauvegarde ou un instantané les fige un instant, pour copier un disque cohérent (atelier 6).

Étape 4 — Une commande dans la VM, sans SSH

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm guest exec 105 -- uptime   # exécuté par l'agent, dans la VM

Résultat attendu :

{
   "exitcode" : 0,
   "exited" : 1,
   "out-data" : " 12:58:19 up 0 min,  0 users,  load average: 0,00, 0,00, 0,00\n",
   "out-truncated" : 0
}

Avec l'agent, qm shutdown passe aussi par lui plutôt que par le signal ACPI, 1,34 s pour un arrêt propre.

Validation finale

Dans le Shell du nœud :

qm agent 105 ping              # l'agent répond-il ?
echo "code : $?"               # son code

Résultat attendu : code : 0, et l'adresse 10.<site>.<N>.54 sur la ligne IPs du Summary.


Atelier 6 — Instantanés et sauvegarde de la VM

Contexte

Avant une intervention risquée, on prend un instantané (snapshot) pour revenir en arrière en quelques secondes. Pour se protéger d'une panne du disque, on fait une sauvegarde : une archive complète, ailleurs. Vous faites les deux sur la VM 105, puis vous restaurez la sauvegarde sous un nouveau numéro, sans écraser l'originale.

Cours : §8 (instantanés) et §9 (sauvegardes).

Résultat à obtenir : un instantané de la VM 105, restauré après une casse volontaire. Une sauvegarde vzdump de la VM 105 est aussi restaurée en VM 110 avec sa carte réseau débranchée, pour ne pas entrer en conflit d'adresse avec l'originale.

Atelier 6 : instantané, sauvegarde et restauration

Les deux premiers blocs portent sur l'instantané, les deux suivants sur la sauvegarde. Cliquez sur chaque bloc pour la commande correspondante.

Arborescence attendue

VM 105 « vm-debian »
└── instantané « avant-essai »
local → Backups
└── vzdump-qemu-105-AAAA_MM_JJ-HH_MM_SS.vma.zst
VM 110 « vm-debian-restauree »   ← restaurée, carte réseau débranchée

Ce que vous devez faire

  1. Prendre un instantané de la VM 105, nommé avant-essai.
  2. Casser volontairement la VM (supprimer /etc/hostname), puis revenir à l'instantané et vérifier que le fichier est revenu.
  3. Sauvegarder la VM 105 avec vzdump sur le stockage local, en mode snapshot.
  4. Restaurer cette sauvegarde en VM 110, la renommer, débrancher sa carte réseau, la démarrer et constater pourquoi.
Cliquez pour vous aider

Machine d'exemple : nœud pxe211, VM 105 en 10.59.1.54 (lab sur le plan des stagiaires) sur pxe212.

Étape 1 — L'instantané

VM 105 → Snapshots → Take Snapshot, nom avant-essai. Ou :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qm snapshot 105 avant-essai --description "VM propre avant essai"   # l'instantané
qm listsnapshot 105                                                 # la liste des instantanés

Résultat attendu :

freeze guest filesystem
snapshotting 'drive-scsi0' (local-lvm:vm-105-disk-0)
  Logical volume "snap_vm-105-disk-0_avant-essai" created.
snapshotting 'drive-scsi1' (local-lvm:vm-105-disk-1)
  Logical volume "snap_vm-105-disk-1_avant-essai" created.
thaw guest filesystem
`-> avant-essai                 2026-10-06 12:59:16     VM propre avant essai
 `-> current                                            You are here!

freeze puis thaw : l'agent (atelier 5) a figé les fichiers le temps de l'instantané. Les deux disques sont pris ensemble.

Étape 2 — Casser, puis revenir

Dans le Shell du nœud :

ssh devops@10.<site>.<N>.54     # mot de passe : dawan
sudo rm /etc/hostname           # la casse
cat /etc/hostname               # le fichier a disparu
exit                            # retour au nœud
qm rollback 105 avant-essai     # retour à l'instantané : la VM s'arrête
qm status 105                   # stopped
qm start 105                    # la redémarrer

Dans le Shell du nœud, trente secondes plus tard, le temps que la VM démarre :

qm guest exec 105 -- cat /etc/hostname   # le fichier est revenu

Résultat attendu : cat: /etc/hostname: Aucun fichier ou dossier de ce nom, puis status: stopped après le retour arrière, et enfin "out-data" : "vm-debian\n" : le fichier est revenu.

Étape 3 — La sauvegarde

VM 105 → Backup → Backup now : Storage local, Mode Snapshot, Compression ZSTD. Ou :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

vzdump 105 --storage local --mode snapshot --compress zstd   # la sauvegarde
pvesm list local --content backup                            # le fichier produit

Résultat attendu (extrait) :

INFO: Starting Backup of VM 105 (qemu)
INFO: backup mode: snapshot
INFO: creating vzdump archive '/var/lib/vz/dump/vzdump-qemu-105-2026_10_06-12_59_52.vma.zst'
INFO: transferred 26.00 GiB in 11 seconds (2.4 GiB/s)
INFO: archive file size: 2.09GB
INFO: Finished Backup of VM 105 (00:00:12)
Volid                                                    Format  Type            Size VMID
local:backup/vzdump-qemu-105-2026_10_06-12_59_52.vma.zst vma.zst backup    2249067266 105

26 Gio de disques (20 + 6) donnent une archive de 2,09 Go : seuls les blocs écrits sont sauvegardés, puis compressés. La VM a tourné pendant toute la sauvegarde.

Étape 4 — Restaurer sous un nouveau numéro

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qmrestore /var/lib/vz/dump/vzdump-qemu-105-AAAA_MM_JJ-HH_MM_SS.vma.zst 110 \
  --storage local-lvm --unique 1     # nouvelle VM 110 ; --unique : nouvelle adresse MAC
qm config 110   # ce qu'elle a hérité ; à lire : name, net0, onboot

Résultat attendu (les lignes qui comptent) :

progress 100% (read 27917287424 bytes, duration 6 sec)
total bytes read 27917287424, sparse bytes 24502398976 (87.8%)
name: vm-debian
net0: virtio=BC:24:11:C7:0F:53,bridge=vmbr0,firewall=1
onboot: 1

La copie est parfaite, et c'est le problème : elle porte le même nom, démarre avec le nœud, et son système contient la même adresse fixe que la VM 105. Démarrée telle quelle, elle provoquerait un conflit d'adresse. On la renomme et on débranche sa carte avant de la démarrer.

Dans le Shell du nœud :

qm set 110 --name vm-debian-restauree --net0 virtio,bridge=vmbr0,link_down=1 --onboot 0   # renommer, débrancher
qm start 110                                         # la démarrer

Dans le Shell du nœud, trente-cinq secondes plus tard :

qm guest exec 110 -- ip -br a show ens18             # sa carte, DOWN

Résultat attendu :

update VM 110: -name vm-debian-restauree -net0 virtio,bridge=vmbr0,link_down=1 -onboot 0
   "out-data" : "ens18            DOWN           10.59.1.54/24 \n",

La VM 110 porte bien l'adresse de la VM 105, mais sa carte est DOWN : aucun conflit. Pour l'utiliser vraiment, il faudrait d'abord changer son adresse dans le fichier qui la déclare (/etc/network/interfaces ou interfaces.d/ens18, voir l'atelier 9, étape 9), puis rebrancher la carte (link_down=0).

Validation finale

Dans le Shell du nœud :

qm listsnapshot 105                 # l'instantané avant-essai
pvesm list local --content backup   # la sauvegarde
qm list   # la VM et sa restauration ; à lire : 105, 110

Résultat attendu (les lignes qui comptent) : l'instantané avant-essai, l'archive vzdump-qemu-105-…, puis les VM 105 vm-debian et 110 vm-debian-restauree.

Nettoyage : arrêtez la VM 110 (qm stop 110) ; supprimez-la si la mémoire du nœud manque (qm destroy 110). La VM 105, son instantané et la sauvegarde restent.


Atelier 7 — Créer une VM template depuis une image cloud

Contexte

Installer un système dans chaque VM à la main est long et source de divergences. La méthode professionnelle part d'une image cloud — un disque déjà installé, nettoyé et équipé de cloud-init, publié par la distribution elle-même. On la transforme une fois en template, puis on clone en quelques secondes.

Cet atelier pose la première brique : récupérer l'image cloud Debian 13 et bâtir la VM 100 qui deviendra ce template. Vous ne l'installez pas — vous importez un disque déjà prêt.

Résultat à obtenir : une VM 100 nommée debian13-template, dotée d'un disque de 20 Go importé depuis l'image cloud Debian 13, prête à être configurée par cloud-init à l'atelier suivant.

Atelier 7 : la VM 100 depuis une image cloud

Le schéma suit l'image cloud jusqu'au disque de 20 Go de la VM 100. Cliquez sur chaque bloc pour son détail.

Arborescence attendue

Sur le nœud :
/var/lib/vz/template/iso/      (stockage « local »)
└── debian-13-generic-amd64.qcow2        ← image cloud téléchargée

VM 100 « debian13-template »   ← squelette sans disque, puis disque importé

Ce que vous devez faire

  1. Télécharger l'image cloud Debian 13 (format .qcow2) sur le nœud.
  2. Créer la VM 100 « squelette » depuis l'interface — sans disque, avec les réglages adaptés à un template (agent invité activé, contrôleur adéquat).
  3. Importer le disque cloud dans la VM 100, puis l'attacher. Pensez à l'agrandir à 20 Go : les images cloud sont volontairement minuscules et démarreraient sinon presque pleines.
Cliquez pour vous aider

L'approche cloud-init évite une installation manuelle de 15 minutes : on part d'une image Debian déjà installée, pré-configurée avec cloud-init, personnalisée au premier démarrage.

Étape 1 — Télécharger l'image cloud Debian 13

L'image vient du site officiel de Debian :

L'image generic convient à Proxmox : elle contient cloud-init et les pilotes VirtIO. Copiez l'adresse du fichier .qcow2 depuis cette page, ou reprenez-la dans la commande ci-dessous.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Télécharger l'image cloud Debian 13 dans le dossier du stockage « local »
wget -O /var/lib/vz/template/iso/debian-13-generic-amd64.qcow2 \
  https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2

# Vérifier sa présence et sa taille
ls -lh /var/lib/vz/template/iso/debian-13-generic-amd64.qcow2

Résultat attendu : 414M. C'est la taille du fichier ; le disque qu'il contient est plus grand, comme le montre qemu-img :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

qemu-img info /var/lib/vz/template/iso/debian-13-generic-amd64.qcow2   # taille virtuelle et taille réelle de l'image ; à lire : virtual size, disk size
virtual size: 3 GiB (3221225472 bytes)
disk size: 414 MiB

Le format qcow2 ne stocke que les blocs écrits : 414 Mio de données pour un disque de 3 Gio.

Si le réseau est lent : l'image a peut-être été téléchargée à l'avance par le formateur. Vérifiez avec ls /var/lib/vz/template/iso/*.qcow2 avant de relancer le téléchargement.

Étape 2 — Créer la VM squelette depuis l'interface

Create VM en haut à droite :

Onglet Champ Valeur
General VM ID / Name 100 / debian13-template
OS Do not use any media ✓ (on importera le disque après)
System Machine / SCSI Controller / Qemu Agent q35 / VirtIO SCSI single / ✓
Disks — supprimer le disque proposé par défaut (🗑️)
CPU Sockets / Cores / Type 1 / 2 / x86-64-v2-AES
Memory Memory / Advanced ✓ → Minimum memory 2048 Mio / 512 Mio
Network Bridge / Model vmbr0 / VirtIO (paravirtualized)

Vérifiez le récapitulatif dans Confirm → Finish.

Machine d'exemple : nœud pxe211 (Proxmox VE 9.2.20). Les captures qui suivent viennent de l'assistant Create VM de ce test sur le lab.

Onglet OS : pas de média

Do not use any media : la VM ne démarrera sur aucune ISO, puisqu'on lui donnera un disque déjà installé. Le type de système reste Linux 7.x - 2.6 Kernel, celui des distributions Linux actuelles.

Onglet System

Machine q35, le chipset moderne (PCI Express) ; SCSI Controller déjà sur VirtIO SCSI single ; Qemu Agent coché : le canal est prêt pour l'agent. Le BIOS reste SeaBIOS : l'image cloud Debian démarre en BIOS comme en UEFI.

Onglet Disks, disque supprimé

Le disque scsi0 proposé par défaut a été supprimé (icône corbeille) : la liste est vide. Remarquez le bouton Import, nouveau en Proxmox VE 9 : il importe une image disque directement dans l'assistant, à condition qu'elle se trouve dans le contenu Import d'un stockage. Cet atelier utilise la méthode en ligne de commande, qui marque mieux chaque étape.

Onglet Memory, options avancées

Memory 2048 Mio, et, une fois Advanced coché, Minimum memory 512 Mio : c'est le plancher du ballooning (balloon en ligne de commande). Ballooning Device est coché par défaut.

Onglet Confirm

Le récapitulatif réellement envoyé : agent 1, balloon 512, cores 2, cpu x86-64-v2-AES, machine q35, memory 2048, scsihw virtio-scsi-single. Deux lignes viennent de l'assistant et pas de la commande qm create ci-dessous : un lecteur ide2 vide (none,media=cdrom) et firewall=1 sur la carte réseau. Start after created est décoché : c'est voulu.

Ne démarrez pas la VM — elle n'a pas encore de disque. Continuez à l'étape suivante.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI complet ; x86-64-v2-AES garde la VM migrable entre nœuds
qm create 100 --name debian13-template --memory 2048 --balloon 512 \
  --cores 2 --cpu x86-64-v2-AES --net0 virtio,bridge=vmbr0 \
  --machine q35 --ostype l26 --agent enabled=1

Résultat attendu : aucun affichage ; la VM 100 apparaît dans l'arbre, sans disque. --balloon 512 autorise Proxmox à reprendre de la mémoire à la VM jusqu'à ce plancher quand l'hôte en manque — l'agent et le pilote balloon de l'invité s'en chargent.

Étape 3 — Importer le disque cloud dans la VM

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Convertir l'image qcow2 en volume du pool local-lvm, rattaché à la VM 100
qm disk import 100 \
  /var/lib/vz/template/iso/debian-13-generic-amd64.qcow2 \
  local-lvm

Résultat attendu (fin de la sortie) :

transferred 3.0 GiB of 3.0 GiB (100.00%)
unused0: successfully imported disk 'local-lvm:vm-100-disk-0'

Le qcow2 est converti en raw au passage, seul format que connaît LVM-thin : les 3 Gio sont transférés en entier. qm importdisk, l'ancien nom de la commande, fonctionne encore.

Onglet Hardware après l'import

Le disque importé apparaît en Unused Disk 0 : il existe sur local-lvm, mais n'est branché sur aucun contrôleur. La VM ne pourrait pas démarrer dessus. Notez aussi la ligne Memory 512.00 MiB/2.00 GiB — le plancher et le maximum du ballooning.

Attachez-le : double-clic sur Unused Disk 0 → Bus/Device SCSI 0, Discard ✓, IO thread ✓ → Add.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI : attacher le volume importé comme premier disque SCSI
qm set 100 --scsihw virtio-scsi-single \
  --scsi0 local-lvm:vm-100-disk-0,discard=on,iothread=1

Résultat attendu : update VM 100: -scsi0 local-lvm:vm-100-disk-0,discard=on,iothread=1 -scsihw virtio-scsi-single. Le contrôleur virtio-scsi-single donne un contrôleur par disque : c'est ce qui permet à iothread=1 de dédier un fil d'exécution à ce disque.

Agrandir le disque (l'image cloud fait 3 Gio, on veut 20 Gio) : sélectionnez scsi0 → Disk Action → Resize → Size Increment 17 (Gio).

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Taille absolue : le disque passe à 20 Gio, quelle que soit sa taille de départ
qm resize 100 scsi0 20G

Résultat attendu :

  Size of logical volume pve/vm-100-disk-0 changed from 3.00 GiB (768 extents) to 20.00 GiB (5120 extents).
  Logical volume pve/vm-100-disk-0 successfully resized.

Sans signe +, la taille est absolue. Avec +18G, on ajouterait 18 Gio aux 3 Gio de l'image, soit 21 Gio. Dans l'interface, le champ est toujours un incrément.

Onglet Hardware, disque attaché et agrandi

Le disque est devenu Hard Disk (scsi0) local-lvm:vm-100-disk-0,discard=on,iothread=1,size=20G, et la ligne Unused Disk a disparu.

Pourquoi aucune commande à l'intérieur de la VM ici ? Parce que vous travaillez sur une image cloud.

Ces images embarquent cloud-init et son module de redimensionnement : au démarrage suivant, la VM constate que son disque a grandi et étend seule sa partition et son système de fichiers. Vérifiez-le après le prochain boot avec df -h /.

Ce ne sera pas le cas d'une VM installée depuis une ISO. Là, qm resize agrandit le disque virtuel et rien d'autre : la partition et le système de fichiers restent à leur taille d'origine. Il faut alors intervenir dans la VM, et l'outil nécessaire n'y est pas installé par défaut :

Dans la VM (sa Console, ou en SSH) :

# Dans la VM installee depuis une ISO
apt update                                       # la liste des paquets
apt install -y cloud-guest-utils                 # fournit growpart
growpart /dev/sda 1                              # etendre la partition
resize2fs /dev/sda1                              # etendre le systeme de fichiers
df -h /   # vérifier la nouvelle taille

Retenez les trois couches : le disque virtuel (agrandi par qm resize), la partition (growpart) et le système de fichiers (resize2fs). L'image cloud fait les deux dernières pour vous ; une installation classique, non.

Et si growpart répond NOCHANGE: partition 1 could only be grown by 2046, c'est que la partition visée n'est pas la dernière du disque : avec le partitionnement Debian par défaut, le swap s'intercale entre / et l'espace libre. Une partition ne grandit que sur l'espace immédiatement contigu. Deux issues.

Créer une partition dans l'espace libre et la monter là où la place manque. Ou supprimer le swap (swapoff -a, sfdisk --delete /dev/sda 5, puis 2), agrandir, et remettre du swap sous forme de fichier. C'est exactement le problème que LVM supprime : sur un volume logique, lvextend n'a aucune contrainte de contiguïté.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

ls -lh /var/lib/vz/template/iso/debian-13-generic-amd64.qcow2   # taille du fichier image téléchargé
qm config 100   # disque, contrôleur, chipset et agent de la VM 100 ; à lire : scsi0, scsihw, machine, agent

Résultat attendu (les lignes qui comptent) :

-rw-r--r-- 1 root root 414M Sep 14 16:30 /var/lib/vz/template/iso/debian-13-generic-amd64.qcow2
agent: 1
machine: q35
scsi0: local-lvm:vm-100-disk-0,discard=on,iothread=1,size=20G
scsihw: virtio-scsi-single

Atelier 8 — Configurer cloud-init

Contexte

Le disque cloud importé est anonyme : ni utilisateur, ni mot de passe, ni réseau configuré. C'est cloud-init qui injecte cette identité au premier démarrage, à partir des paramètres que vous fixez dans Proxmox. C'est le mécanisme qui rend un template réellement réutilisable — chaque clone reçoit sa propre configuration sans qu'on touche au disque.

Résultat à obtenir : la VM 100 configurée par cloud-init : utilisateur, mot de passe, clé SSH, adresse fixe, ordre de démarrage. Démarrée une fois pour valider la connexion SSH, nettoyée de ce premier démarrage, puis éteinte proprement avant d'en faire un template.

Atelier 8 : configurer cloud-init sur la VM 100

Le schéma suit la VM 100 du lecteur cloud-init jusqu'au nettoyage final. Cliquez sur chaque bloc pour son détail.

Arborescence attendue

VM 100 « debian13-template »
├── ide0 : lecteur cloud-init   ← porte l'identité injectée au boot
└── cloud-init : user / password / clé SSH / IP FIXE

Ce que vous devez faire

  1. Ajouter le lecteur cloud-init à la VM 100 (un disque cloudinit sur local-lvm).
  2. Renseigner les paramètres cloud-init : utilisateur, mot de passe, clé SSH publique, et une adresse IP fixe. Jamais de DHCP sur les ressources du lab, conformément à la règle d'adressage de la formation.
  3. Définir l'ordre de démarrage de la VM.
  4. Tester avant d'en faire un template : démarrer la VM et vérifier qu'elle répond à son adresse fixe. Se connecter en SSH pour confirmer que cloud-init a bien appliqué la configuration. Passer la console de la VM en clavier français : l'image cloud est en QWERTY (disposition de clavier anglo-saxonne), et chaque clone en hériterait.
  5. Nettoyer, puis éteindre : effacer ce que ce premier démarrage a laissé (état de cloud-init, identifiant machine-id), puis éteindre proprement. Ne la redémarrez plus ensuite.

⚠️ On teste avant de convertir en template : une fois la VM transformée en template, elle ne se démarre plus, et corriger cloud-init imposerait de tout refaire. Mais ce test laisse une trace : le premier démarrage a donné à la VM un identifiant système, le machine-id, que tous les clones recopieraient. D'où l'étape 5, le nettoyage, avant l'arrêt définitif.

Cliquez pour vous aider

Étape 1 — Ajouter le lecteur cloud-init

Cloud-init lit sa configuration depuis un CD-ROM (Compact Disc Read-Only Memory, disque en lecture seule) virtuel : VM 100 → Hardware → Add → CloudInit Drive, Storage local-lvm → Add.

Machine d'exemple : nœud pxe211 (Proxmox VE 9.2.21, lab 10.59.1.x). La VM y a l'adresse 10.59.1.55 (network) ; chez vous, c'est 10.<site>.<N>.55. Les captures datent d'avant le passage du lab sur ce plan.

Fenêtre Add CloudInit Drive

Proxmox propose IDE 0 : l'emplacement ide2 est déjà pris par le lecteur CD vide que l'assistant a créé (atelier 7). Gardez IDE 0, et choisissez le stockage local-lvm.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Équivalent CLI : lecteur cloud-init sur ide0, à côté du lecteur CD vide (ide2)
qm set 100 --ide0 local-lvm:cloudinit

Résultat attendu : ide0: local-lvm:vm-100-cloudinit,media=cdrom dans la configuration, et un volume vm-100-cloudinit de 4 Mio sur local-lvm — le lecteur est un vrai petit volume.

Onglet Hardware avec le lecteur cloud-init

Deux lecteurs CD : CloudInit Drive (ide0), qui portera l'identité de la VM, et le CD/DVD Drive (ide2) vide. Le disque système est scsi0, en 20 Gio.

Étape 2 — Configurer les paramètres cloud-init

VM 100 → onglet Cloud-Init :

Champ Valeur
User devops
Password dawan
SSH public key les clés autorisées sur le nœud (cat ~/.ssh/authorized_keys) : elles contiennent la clé du nœud lui-même, qui lui permettra de se connecter à la VM
IP Config (net0) Static : 10.<site>.<N>.55/24, Gateway 10.<site>.<N>.1

OK puis Regenerate Image.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Identité injectée au premier démarrage : compte, mot de passe, clé, adresse FIXE
qm set 100 \
  --ciuser devops \
  --cipassword 'dawan' \
  --sshkeys /root/.ssh/authorized_keys \
  --ipconfig0 ip=10.<site>.<N>.55/24,gw=10.<site>.<N>.1

# Relire ce que Proxmox a réellement mis sur le lecteur
qm cloudinit dump 100 user
qm cloudinit dump 100 network   # et la configuration réseau

Résultat attendu — la partie user, puis la partie network (clés raccourcies) :

#cloud-config
hostname: debian13-template
manage_etc_hosts: true
fqdn: debian13-template
user: devops
password: $5$mNlfP33C$xWwaMz2UVw6hm5bqvXitiKu7bURs5QobWhu2EB.l/d9
ssh_authorized_keys:
  - ssh-rsa AAAAB3NzaC1y... root@pxe211
  - ...
chpasswd:
  expire: False
users:
  - default
package_upgrade: true

Résultat attendu, partie network :

version: 1
config:
    - type: physical
      name: eth0
      mac_address: 'bc:24:11:bf:e1:d7'
      subnets:
      - type: static
        address: '10.59.1.55'
        netmask: '255.255.255.0'
        gateway: '10.59.1.1'
    - type: nameserver
      address:
      - '1.1.1.1'
      search:
      - 'dawan.local'

La dernière section n'a pas été saisie : faute de DNS indiqué dans l'onglet Cloud-Init, Proxmox reprend ceux du nœud (use host settings).

Onglet Cloud-Init

Chaque paramètre saisi : User devops, Password masqué, DNS use host settings, les clés SSH (masquées ici), Upgrade packages Yes et IP Config (net0) en adresse fixe. Après toute modification, Regenerate Image reconstruit le lecteur ; Proxmox le fait aussi seul au démarrage (generating cloud-init ISO).

Trois lignes méritent une explication. hostname vient du nom de la VM : c'est pour cela qu'un clone nommé vm-web-01 s'appellera vm-web-01 sans rien configurer. password est déjà une empreinte : Proxmox ne stocke jamais le mot de passe en clair, même dans sa configuration.

users: - default crée le compte par défaut de la distribution, renommé devops par la ligne user:. Sur Debian, ce compte par défaut reçoit d'office le droit sudo sans mot de passe. package_upgrade: true fait mettre à jour les paquets au premier démarrage : c'est pourquoi ce premier démarrage est plus long que les suivants.

Étape 3 — Configurer l'ordre de démarrage

VM 100 → Options → Boot Order → Edit : cochez uniquement scsi0, décochez ide0/ide2/net0, faites-le glisser en première position.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Démarrer uniquement sur le disque système
qm set 100 --boot order=scsi0

Résultat attendu : update VM 100: -boot order=scsi0. L'assistant avait réglé order=ide2;net0 : sans cette étape, la VM chercherait à démarrer sur le lecteur CD vide, puis sur le réseau.

Étape 4 — Tester la VM avant de créer le template

Démarrez : VM 100 → Start → Console. Cloud-init s'exécute au premier boot : il applique l'identité, agrandit le disque, puis met à jour les paquets (package_upgrade: true).

Depuis le Shell du nœud, attendez que la VM réponde, puis connectez-vous avec la clé injectée :

Dans le Shell du nœud (interface web → votre nœud → Shell) :

ping -c 2 10.<site>.<N>.55   # la VM répond-elle à son adresse fixe ?
ssh devops@10.<site>.<N>.55  # puis, dans la VM :
hostname                     # son nom
id                           # le compte
sudo -n true                 # sudo, sans mot de passe ?
echo "code : $?"             # 0 : oui
df -h /                      # le disque
cloud-init status            # l'état de cloud-init
exit                         # retour au nœud

Résultat attendu : le port SSH de la VM répondait une vingtaine de secondes après le démarrage.

debian13-template
uid=1000(devops) gid=1000(devops) groups=1000(devops),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev)
code : 0
/dev/sda1        20G  950M   18G   5% /
status: done

Tout est là. Le nom vient de la VM ; le compte devops est dans le groupe sudo et l'utilise sans mot de passe (sudo -n réussit).

Le système de fichiers fait bien 20G : cloud-init a agrandi la partition seul. Et cloud-init status confirme que le premier démarrage est terminé.

L'agent QEMU n'est pas dans l'image cloud Debian. Sur le lab, qm guest cmd 100 network-get-interfaces a répondu QEMU guest agent is not running pendant plus de six minutes, et pour cause : dpkg -l qemu-guest-agent répond no packages found.

La case Qemu Agent de l'atelier 7 prépare seulement le canal côté Proxmox ; le programme, lui, s'installe dans la VM (apt install qemu-guest-agent, comme à l'atelier 5). Tant qu'il n'y est pas, l'interface affiche Guest Agent not running à la place des adresses IP.

Summary de la VM 100 sans agent

La VM tourne (running, 2 CPU, disque de 20 Gio), mais la ligne IPs affiche Guest Agent not running : sans agent, Proxmox ne connaît pas l'adresse de la VM. C'est aussi pourquoi Shutdown met du temps : Proxmox essaie d'abord l'agent (QEMU Guest Agent is not running - VM 100 qga command 'guest-ping' failed - got timeout), puis passe par le signal ACPI.

Le clavier de la console. Tapez quelques lettres dans la Console de la VM : le a sort en q. L'image cloud Debian n'a aucun outil de clavier, et sa console reste en QWERTY.

Corrigez-le maintenant, avant le template : chaque clone en héritera.

Dans le Shell du nœud (interface web → votre nœud → Shell), connectez-vous à la VM :

ssh devops@10.<site>.<N>.55   # se connecter à la VM

Puis, dans la VM :

sudo apt-get update   # la liste des paquets
# Les outils du clavier de la console. DEBIAN_FRONTEND=noninteractive : aucune question,
# la disposition par défaut (us) est retenue ; la ligne suivante la remplace
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y console-setup
sudo nano /etc/default/keyboard   # disposition française : la ligne XKBLAYOUT devient XKBLAYOUT="fr"
sudo setupcon --force --save   # appliquer, et enregistrer pour les démarrages suivants
grep XKBLAYOUT /etc/default/keyboard   # vérifier
exit   # quitter la VM

Résultat attendu (VM de test sur pxe212, même image Debian 13) : XKBLAYOUT="fr". Après un redémarrage, les touches q w a z m frappées dans la console ont affiché azqw, : la console est en AZERTY (disposition de clavier française).

Étape 5 — Nettoyer le premier démarrage, puis éteindre

Le test a laissé deux traces dans la VM : l'état de cloud-init (/var/lib/cloud/), qui marque l'initialisation comme faite, et surtout l'identifiant système /etc/machine-id, tiré au hasard au premier démarrage.

Converti tel quel en template, ce disque donnerait le même machine-id à tous les clones : vérifié sur le lab, deux clones ont répondu le même identifiant, 87703c63bbf841358c1a7eb6912f791b, celui du template. Or des services s'en servent comme identité unique de la machine : le journal système, ou l'identifiant client d'un DHCP.

cloud-init clean efface les deux d'un coup :

Dans le Shell du nœud (interface web → votre nœud → Shell), puis dans la VM :

ssh devops@10.<site>.<N>.55                       # mot de passe : celui de la clé, ou aucun
# --logs : efface aussi les journaux de cloud-init ; --machine-id : remet l'identifiant système à zéro
sudo cloud-init clean --logs --machine-id
cat /etc/machine-id                               # l'identifiant, remis à zéro
exit                                              # retour au nœud

Résultat attendu (cloud-init 25.1.4, celui de l'image Debian 13) :

uninitialized

uninitialized dit à systemd de tirer un nouvel identifiant au prochain démarrage, et cloud-init, sans état, s'exécutera de nouveau : chaque clone aura donc son propre identifiant et sa propre initialisation.

Éteignez maintenant la VM, sans la redémarrer : VM 100 → Shutdown. Un nouveau démarrage referait un machine-id, et il faudrait nettoyer de nouveau.

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Le compte injecté, l'ordre de démarrage, puis le compte et sudo vus de l'intérieur
qm cloudinit dump 100 user   # à lire : user, hostname
qm config 100 | grep "^boot"   # l'ordre de démarrage
qm status 100   # éteinte après le nettoyage

Résultat attendu (les lignes qui comptent) : hostname: debian13-template et user: devops, puis boot: order=scsi0, puis status: stopped. La connexion SSH et sudo ont été vérifiés à l'étape 4, avant le nettoyage.


Atelier 9 — Créer un template et déployer des clones

Contexte

La VM 100 est configurée et validée : il est temps d'en faire un template, c'est-à-dire un modèle en lecture seule qu'on ne démarre plus mais qu'on clone. C'est là que tout le travail précédent porte ses fruits — deux VMs de production naissent en quelques secondes, identiques par construction, différenciées seulement par ce que cloud-init leur injecte.

Un template ne demande pas cloud-init : n'importe quelle VM installée peut en devenir un. La partie B le fait avec la VM 105 de l'atelier 2, pour comparer : tout ce que cloud-init fait seul doit alors se faire à la main, clone par clone.

Résultat à obtenir :

  • Partie A : la VM 100 convertie en template, et deux clones complets — VM 101 et VM 102 — démarrant chacun avec une adresse IP statique distincte.
  • Partie B : un template 106 tiré de la VM 105, nettoyé à la main. Puis un clone 107, personnalisé dans sa console, en 10.<site>.<N>.58, avec ses propres machine-id et clés SSH.
Atelier 9 : templates et clones

Les deux premiers blocs suivent la partie A, les deux suivants la partie B. Cliquez sur chaque bloc pour son détail.

Arborescence attendue

Partie A
VM 100 « debian13-template »   ← TEMPLATE (ne démarre plus)
├── clone complet → VM 101 « vm-web-01 »   IP fixe 10.<site>.<N>.56
└── clone complet → VM 102 « vm-web-02 »   IP fixe 10.<site>.<N>.57

Partie B
VM 105 « vm-debian » (atelier 2)
└── clone complet → VM 106 « debian-modele », nettoyée → TEMPLATE
    └── clone lié → VM 107 « vm-classique-01 »   IP fixe 10.<site>.<N>.58, réglée à la main

Ce que vous devez faire

Partie A — un template cloud-init

  1. Convertir la VM 100 en template.
  2. Cloner le template pour créer la VM 101 (clone complet, pas lié — demandez-vous pourquoi le clone complet est préférable ici).
  3. Personnaliser le clone avant de le démarrer : lui donner son propre nom d'hôte et son adresse IP fixe via cloud-init.
  4. Déployer un second clone, VM 102, avec une IP différente — et vérifier que les deux VMs coexistent sans collision de nom ni d'adresse.

Partie B — un template sans cloud-init

  1. Cloner la VM 105 en VM 106 (clone complet), carte réseau débranchée : le clone porte la même adresse que la VM 105.
  2. Effacer son identité dans sa console : machine-id et clés SSH de la machine. Puis l'éteindre et la convertir en template.
  3. Cloner le template en VM 107, la démarrer carte débranchée, et relever ce dont elle a hérité.
  4. La personnaliser à la main : nom, adresse .58, clés SSH. Rebrancher la carte, redémarrer, et prouver depuis le nœud qu'elle ne se confond pas avec la VM 105.

💡 Clone lié ou clone complet ? Le clone lié est instantané mais reste dépendant du template ; le clone complet est autonome. Sur des VMs de production, on privilégie l'autonomie.

Cliquez pour vous aider

Étape 1 — Convertir la VM en template

VM 100 → clic droit → Convert to Template → confirmer.

Pas de conversion inverse officielle. Une fois la VM convertie, elle ne peut plus démarrer directement — seuls les clones peuvent l'être.

Ni l'interface web ni une sous-commande qm dédiée n'offrent de "dé-templater" une VM. Le seul contournement (non officiellement documenté) consiste à éditer directement le fichier de configuration /etc/pve/qemu-server/100.conf pour retirer la ligne template: 1.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Figer la VM 100 en modèle
qm template 100

Résultat attendu :

  Renamed "vm-100-disk-0" to "base-100-disk-0" in volume group "pve"
  Logical volume pve/base-100-disk-0 changed.

Seul le disque système est renommé : le préfixe base- signale un disque devenu la base, en lecture seule, de tous les futurs clones. Le lecteur cloud-init, lui, reste vm-100-cloudinit : chaque clone reçoit son propre lecteur, régénéré à son premier démarrage. qm config 100 montre désormais la ligne template: 1.

Le template dans l'arborescence

La VM 100 a changé d'icône (une page stylisée) et passé en bas de la liste. Son clic droit ne propose plus que Clone : ni Start, ni Console. Son résumé ne montre que la configuration — processeurs, mémoire, disque de 20 Gio — sans aucune mesure d'activité.

Étape 2 — Cloner le template pour créer une VM de production

VM 100 (template) → clic droit → Clone : Target node pxe2<N>1, VM ID 101, Name vm-web-01, Mode Full Clone, Target Storage local-lvm → Clone.

Fenêtre Clone d'un template

La fenêtre telle qu'elle s'ouvre. Attention au mode : Proxmox propose Linked Clone par défaut sur un template.

Il faut le passer à Full Clone, ce qui débloque le choix du Target Storage. Le VM ID proposé est le premier libre.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Clone complet : un disque indépendant, copié sur local-lvm
qm clone 100 101 --name vm-web-01 --full --storage local-lvm

Résultat attendu :

create full clone of drive scsi0 (local-lvm:base-100-disk-0)
  Logical volume "vm-101-disk-0" created.
transferred 20.0 GiB of 20.0 GiB (100.00%)

La copie des 20 Gio a pris environ 7 secondes : sur un pool thin, seuls les blocs réellement écrits (moins de 1 Gio ici) sont recopiés.

Full Clone vs Linked Clone :

  • Full Clone : copie complète du disque — VM totalement indépendante du template. Prend plus d'espace mais peut être déplacée ou sauvegardée librement.
  • Linked Clone : partage les blocs communs avec le template (copy-on-write) — démarrage instantané, minimal en espace. La VM ne peut pas migrer sans le template.

Étape 3 — Personnaliser le clone avant démarrage

VM 101 → Cloud-Init → IP Config (net0) → Edit : 10.<site>.<N>.56/24, Gateway 10.<site>.<N>.1 → OK → Regenerate Image.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Le clone reçoit SA propre adresse ; le nom d'hôte vient du nom de la VM
qm set 101 \
  --ciuser devops \
  --ipconfig0 ip=10.<site>.<N>.56/24,gw=10.<site>.<N>.1

Démarrez : VM 101 → Start. Attendez 30 secondes.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Se connecter au clone et vérifier son identité
ssh devops@10.<site>.<N>.56
hostname   # le nom donné par cloud-init
ip addr show eth0   # l'adresse fixe de la VM

Résultat attendu (lab 10.59.1.x) : vm-web-01, puis eth0 UP 10.59.1.56/24 ; vm-web-02 en 10.59.1.57/24. Les deux clones répondaient en SSH 15 secondes après leur démarrage.

Ce qui vient de se passer : en moins d'une minute, une VM Debian 13 complète a été déployée avec son hostname, son IP et sa clé SSH. Sans aucune installation manuelle. C'est exactement ce que font les providers cloud (AWS — Amazon Web Services —, Azure, GCP — Google Cloud Platform) à chaque création d'instance.

Étape 4 — Déployer un second clone avec une IP différente

Répétez l'opération pour la VM 102 : VM 100 → Clone, VM ID 102, Name vm-web-02, Full Clone. Puis Cloud-Init : 10.<site>.<N>.57/24, Gateway 10.<site>.<N>.1.

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Second clone, seconde adresse
qm clone 100 102 --name vm-web-02 --full --storage local-lvm
qm set 102 --ipconfig0 ip=10.<site>.<N>.57/24,gw=10.<site>.<N>.1   # son adresse fixe
qm start 102   # démarrer le clone

Validation finale

Dans le Shell du nœud (interface web → votre nœud → Shell) :

# Les trois VM, puis le nom et l'identifiant système de chaque clone
qm list   # à lire : 100, 101, 102
ssh devops@10.<site>.<N>.56 hostname                 # le nom du clone 101
ssh devops@10.<site>.<N>.56 cat /etc/machine-id      # son identifiant
ssh devops@10.<site>.<N>.57 hostname                 # le nom du clone 102
ssh devops@10.<site>.<N>.57 cat /etc/machine-id      # son identifiant

Résultat attendu (les lignes qui comptent) :

       100 debian13-template    stopped    2048              20.00 0
       101 vm-web-01            running    2048              20.00 37513
       102 vm-web-02            running    2048              20.00 37681
vm-web-01
<32 caractères hexadécimaux>
vm-web-02
<32 autres caractères hexadécimaux>

Le template 100 stopped, les VM 101 et 102 running, deux noms, deux adresses, aucune collision. Les deux machine-id doivent être différents : sur le lab, 0ecd8b4b61ab4e26965c29f31bb2679c et 11e7b2f2090b46f09d50e58ed09d8660. S'ils sont identiques, le nettoyage de l'atelier 8 (étape 5) a été oublié.

Le nœud avec ses deux clones

Le CT 200 et les deux clones tournent. Regardez la colonne Host Mem… : chaque VM occupe environ 20 % de la mémoire du nœud.

Surveillez la mémoire du nœud. Votre nœud dispose de 4 Go. Deux VM de 2 Go plus le CT 200 dépassent cette capacité sur le papier : c'est le ballooning (plancher de 512 Mio, atelier 7) qui rend la cohabitation possible.

Sur le lab, free -m affichait 3846 Mo au total, 3240 utilisés et 605 disponibles. Arrêtez les VM dont vous n'avez plus besoin (qm shutdown), avant d'en démarrer d'autres.

Partie B — Un template sans cloud-init, à partir de la VM 105

Machine d'exemple : nœud pxe211 (Proxmox VE 9.2.21, lab 10.59.1.x). La VM 105 y est en 10.59.1.54 et le clone 107 en 10.59.1.58 ; chez vous, 10.<site>.<N>.54 et 10.<site>.<N>.58. Les commandes dans la VM se tapent dans sa Console : le mot de passe de devops est dawan.

Étape 6 — Cloner la VM 105, carte débranchée

Via l'interface : VM 105 → More → Clone : VM ID 106, Name debian-modele, Mode Full Clone → Clone. Puis VM 106 → Hardware → Network Device → Edit → cocher Disconnect → OK.

Dans le Shell du nœud :

qm clone 105 106 --name debian-modele --full   # clone complet de la VM 105
qm set 106 --net0 virtio,bridge=vmbr0,link_down=1   # la carte, débranchée
qm start 106                                  # démarrer le clone

Pourquoi débrancher : le clone est la copie exacte du disque de la VM 105, adresse fixe comprise. Branché, il entrerait en conflit avec elle.

Étape 7 — Effacer l'identité, puis faire le template

Dans la Console de la VM 106, connecté en devops :

hostname                     # ce que le clone a hérité : le nom
cat /etc/machine-id          # l'identifiant système
ls /etc/ssh/ssh_host_*       # les clés SSH de la machine
ip -br a show ens18          # la carte et son adresse

Résultat attendu : vm-debian, le machine-id de la VM 105 (c85ab6a3cfc54e329cc7f19c6da42284), six fichiers ssh_host_*, et ens18 DOWN 10.59.1.54/24. Le clone est la VM 105, à l'identique.

Dans la console de la VM 106 :

sudo truncate -s 0 /etc/machine-id                          # vider l'identifiant système
sudo rm -v /var/lib/dbus/machine-id /etc/ssh/ssh_host_*      # sa copie D-Bus, et les clés SSH de la machine
wc -c /etc/machine-id                                       # vérifier : 0 octet
ls /var/lib/dbus/ /etc/ssh/                                 # plus de copie, plus de clés
sudo poweroff                                               # éteindre

Résultat attendu : les sept fichiers supprimé, puis 0 /etc/machine-id, un dossier /var/lib/dbus/ vide, et plus aucune clé ssh_host_* dans /etc/ssh/.

Vider /etc/machine-id ne suffit pas sur une Debian installée depuis l'ISO. Sur le lab, au premier essai, sans supprimer /var/lib/dbus/machine-id : le clone a redémarré avec le machine-id de la VM 105, c85ab6a3cfc54e329cc7f19c6da42284.

Au démarrage, systemd recrée /etc/machine-id à partir de cette copie si elle existe. L'image cloud de la partie A n'a pas ce piège : cloud-init clean --machine-id s'en charge.

Puis, la VM éteinte : VM 106 → More → Convert to template, ou en ligne de commande.

Dans le Shell du nœud :

qm template 106   # convertir en template

Étape 8 — Un clone, et ce dont il hérite

Via l'interface : clic droit sur le template 106 → Clone : VM ID 107, Name vm-classique-01, Mode Linked Clone (proposé d'office) → Clone. La carte reste débranchée : le clone hérite du réglage du template.

Dans le Shell du nœud :

qm clone 106 107 --name vm-classique-01   # clone lié, par défaut depuis un template
qm start 107                              # le démarrer

Dans la Console de la VM 107 :

hostname                     # le nom
ip -br a show ens18          # la carte
cat /etc/machine-id          # l'identifiant, neuf
systemctl is-active ssh      # le service SSH

Résultat attendu :

vm-debian
ens18            DOWN           10.59.1.54/24
f298cc1603ad42aca68c84b1650c883a
failed

Le machine-id est neuf : le nettoyage a fonctionné. Mais le nom et l'adresse sont ceux de la VM 105, et le service SSH est en échec : il n'a plus de clés de machine. Tout ce que cloud-init règle seul, dans la partie A, reste à faire à la main.

Étape 9 — Personnaliser le clone à la main

Dans la Console de la VM 107 :

sudo hostnamectl set-hostname vm-classique-01        # son propre nom
grep -rn "address" /etc/network/interfaces /etc/network/interfaces.d/   # dans quel fichier est l'adresse de ens18 ?
sudo nano /etc/network/interfaces                    # ou le fichier que grep a trouvé : remplacer .54 par .58 sur la ligne address
sudo ssh-keygen -A                                   # générer ses propres clés SSH de machine

Où est l'adresse ? Cela dépend de l'installation de la VM 105 (atelier 2, étape 3). Si l'installateur a écrit l'adresse fixe, elle est dans /etc/network/interfaces.

Si vous l'avez corrigée à la main, elle est dans /etc/network/interfaces.d/ens18. Modifiez le fichier existant : n'en créez pas un second, sinon ens18 serait déclarée deux fois.

Le bloc de ens18, une fois modifié (exemple : stagiaire 2 à Paris) :

iface ens18 inet static
    address 10.75.2.58/24
    gateway 10.75.2.1

La passerelle est 10.<site>.<N>.1, celle de votre réseau. 192.168.<site>.1 est le serveur DNS : il ne va pas sur la ligne gateway.

Résultat attendu : après hostnamectl, sudo affiche impossible de résoudre l'hôte vm-classique-01 : le nouveau nom n'est connu qu'au prochain démarrage, et sudo attend plusieurs secondes avant de répondre. ssh-keygen -A répond generating new host keys: RSA ECDSA ED25519.

Redémarrez d'abord la VM, carte toujours débranchée (VM 107 → Reboot) : c'est au démarrage qu'elle prend sa nouvelle adresse. Puis rebranchez la carte : VM 107 → Hardware → Network Device → Edit → décocher Disconnect.

Rebrancher avant de redémarrer crée un conflit d'adresse. Sur le lab : la carte rebranchée avant le redémarrage portait encore .54. Le nœud a joint la VM 107 à la place de la VM 105, puis a gardé la mauvaise correspondance après le redémarrage.

ip neigh flush 10.<site>.<N>.54, dans le Shell du nœud, l'a effacée.

Étape 10 — Vérifier depuis le nœud

Dans le Shell du nœud :

ping -c 2 10.<site>.<N>.58                                    # le clone répond à sa nouvelle adresse
ssh-keyscan -t ed25519 10.<site>.<N>.58 | ssh-keygen -lf -   # empreinte de sa clé SSH
ssh-keyscan -t ed25519 10.<site>.<N>.54 | ssh-keygen -lf -   # celle de la VM 105

Résultat attendu : 2 received, 0% packet loss, puis deux empreintes différentes : SHA256:jbNlPFQIM9zSgk5FQy4CQJmUw7VdpmRqvasFOxrjGyk pour la VM 107, SHA256:YYdxFjHDeoTahliKT1HXZ9ZQ5EZlLpT1ZKcUPa3Ue6I pour la VM 105. Deux machines distinctes, nées du même disque.

Partie A — template cloud-init Partie B — template d'une VM installée
Point de départ Image cloud de la distribution Une VM installée depuis l'ISO
Nettoyage avant conversion cloud-init clean --logs --machine-id machine-id, sa copie D-Bus et les clés SSH, effacés à la main
Nom, adresse, compte Injectés par Proxmox au premier démarrage Réglés à la main dans la console de chaque clone
Clés SSH de la machine Générées au premier démarrage ssh-keygen -A à la main
Cent clones Une boucle de qm clone et qm set Cent passages dans une console

Le template d'une VM installée convient pour quelques machines, ou pour un système qui n'a pas d'image cloud. Dès qu'on déploie en série, cloud-init fait le travail de l'étape 9 à votre place.


Dépannage — Erreurs fréquentes

Console noVNC noire sur une VM cloud Ubuntu. --vga serial0 redirige la sortie vers le port série. Remède : Utiliser l'onglet Console → xterm.js, pas noVNC.

qm cloudinit dump n'affiche pas la clé SSH attendue. Fichier authorized_keys non régénéré après modification. Remède : Cliquer Regenerate Image dans l'onglet Cloud-Init après toute modification.

Deux clones ont le même machine-id. Template converti sans nettoyage après un démarrage.

Ou, sur une VM installée depuis l'ISO, /etc/machine-id vidé mais /var/lib/dbus/machine-id laissé en place : systemd en recopie l'identifiant (atelier 9, partie B). Remède : Refaire la préparation du template : cloud-init clean --machine-id pour une image cloud ; truncate -s 0 /etc/machine-id et rm /var/lib/dbus/machine-id pour une VM installée.

Pool local-lvm proche de la saturation. Multiples VMs/templates non nettoyés, seuil des 70% dépassé. Remède : lvs -o name,size,data_percent pve/data, supprimer les VMs de test obsolètes.

Récapitulatif des commandes essentielles

Situation Commande
Créer une VM / importer un disque cloud qm create / qm disk import <vmid> <image> <storage>
Attacher et redimensionner un disque qm set <vmid> --scsi0 ... / qm resize <vmid> scsi0 +NG
Configurer cloud-init qm set <vmid> --ciuser ... --cipassword ... --ipconfig0 ...
Convertir en template / cloner qm template <vmid> / qm clone <vmid> <new> --full --storage ...
Snapshot / rollback qm snapshot <vmid> <nom> / qm rollback <vmid> <nom>
Sauvegarde / restauration vzdump <vmid> --mode snapshot / qmrestore <archive> <nouveau-vmid>
Interroger l'agent QEMU qm guest cmd <vmid> network-get-interfaces