Cloner une VM dans Virt-Manager avec virt-clone et virt-sysprep
Cloner une VM copie des octets, pas une identité.
Virt-Manager (l’interface graphique de libvirt) copie un disque KVM et assigne au clone un UUID et une adresse MAC. L’invité conserve son machine-id et ses clés hôte SSH jusqu’à ce que virt-sysprep les efface.
Ce guide utilise un invité Ubuntu 26.04 et une image qcow2 de 14 GB stockée dans /mnt/extra2/vms. Les commandes disques sont identiques pour d’autres invités Linux. virt-sysprep ne fonctionne pas sur les invités Windows.

L’hôte doit déjà disposer de KVM et de libvirt. Installer KVM sur Ubuntu 24.04 est la configuration nécessaire, et elle installe virtinst, qui fournit virt-clone. virt-sysprep, virt-customize, virt-cat et guestfish proviennent d’un package séparé :
sudo apt install -y libguestfs-tools
Ce qui clone réellement une VM
libvirt répartit la tâche entre trois outils. virt-clone copie les images disques et définit un nouveau domaine avec le même matériel virtuel. Il modifie le nom du domaine, l’UUID et l’adresse MAC côté hôte. Les mots de passe, le nom d’hôte, les adresses statiques et les fichiers dans l’invité restent inchangés, c’est le comportement documenté par virt-clone(1).
virt-sysprep ouvre le disque avec libguestfs et modifie le système de fichiers de l’invité. Le manuel virt-sysprep(1) est explicite : la modification est faite sur place ; il n’y a pas d’option de fichier de sortie, donc l’image que vous passez à -a est l’image qui change. Copiez ou clonez d’abord si vous avez encore besoin de la source.
qemu-img info indique si ce fichier est autonome ou le sommet d’une chaîne de backings. qemu-img convert écrit un nouveau fichier avec la chaîne résolue.
Aplatir avant le sysprep quand une ligne backing est présente. Faire le sysprep de la copie, puis dériver chaque invité exécuté à partir de ce fichier.
Cloner le disque dans Virt-Manager
Éteindre l’invité. virt-clone rejette un domaine en cours d’exécution, et une copie d’un qcow2 en cours d’exécution n’est pas un système de fichiers cohérent.
Dans Virt-Manager, clic droit sur l’invité et choisir Clone. Définir le nouveau nom. À l’étape du stockage, donner un nouveau chemin à chaque disque. Laisser le chemin d’origine en place définit un second domaine qui ouvre le même fichier, donc les deux invités écrivent sur les mêmes blocs.
Le nouveau fichier est placé à côté de la source. Un pool par défaut utilise /var/lib/libvirt/images/. Un disque qui se trouve déjà dans /mnt/extra2/vms est cloné dans ce répertoire. Noter le chemin que virt-clone affiche, ou le relire :
virsh domblklist ubuntu26.04-base14gb-clone
L’équivalent en ligne de commande, avec le nom et le chemin du disque choisis explicitement :
virt-clone --original ubuntu26.04-base14gb \
--name ubuntu26.04-base14gb-clone \
--file /mnt/extra2/vms/ubuntu26.04-base14gb-clone.qcow2
--auto-clone invente le nom et le chemin du disque. C’est pratique pour une copie jetable. Un chemin de modèle est plus facile à conserver quand vous passez vous-même --name et --file. Omettre --mac, ou passer --mac RANDOM, et virt-clone génère une adresse dans la plage QEMU 52:54:00:xx:xx:xx.
--reflink demande une copie légère. Le manuel de virt-clone pour Ubuntu 26.04 limite cette option aux images brutes sur le même système de fichiers btrfs, donc elle ignore ces fichiers qcow2. Un overlay qcow2 est une configuration séparée, couverte avec qemu-img create -b ci-dessous.
Votre clone a-t-il un fichier backing ?
Exécuter ceci sur le nouveau disque avant de le traiter comme indépendant :
qemu-img info --backing-chain /mnt/extra2/vms/ubuntu26.04-base14gb-clone.qcow2
Une image autonome liste file format, virtual size et disk size. Un overlay liste également une ligne backing file: pointant vers l’image qu’il lit. virtual size est la taille du disque de l’invité, ici environ 14 GB. disk size est la place que le fichier occupe actuellement, ce qui est petit pour un overlay neuf et augmente au fur et à mesure que l’invité écrit.
virt-clone n’est pas la source habituelle de cette ligne. Un overlay provient de qemu-img create -b, d’une seule instantanée disque, ou d’un outil qui a créé volontairement une delta qcow2. La vérification info est ce qui distingue ces cas d’une copie complète.
Conserver l’overlay seulement si la base restera en place et ne sera pas réécrite. Chaque écriture depuis le clone atterrit dans le petit fichier ; les lectures qui manquent dans l’overlay proviennent de la base. Déplacer ou éditer la base casse tous les invités qui l’appellent.
Pour créer un fichier autonome, convertir l’overlay. -p affiche la progression. La destination est un nouveau fichier ; l’overlay et la base restent tels qu’ils sont :
qemu-img convert -p -O qcow2 \
/mnt/extra2/vms/ubuntu26.04-base14gb-clone.qcow2 \
/mnt/extra2/vms/ubuntu26.04-base14gb-flat.qcow2
Exécuter qemu-img info sur le fichier plat et confirmer qu’il n’y a pas de ligne backing file:. Un modèle est ce fichier autonome. Les overlays sont la façon de tamponner des invités à partir de lui plus tard, pas le modèle lui-même.
Un reflink btrfs est un troisième cas. cp --reflink=auto peut partager des étendues physiques entre deux fichiers, et qemu-img info n’affiche toujours pas de fichier backing, car chaque chemin est une image complète. Cette copie est indépendante au niveau qcow2, même si le système de fichiers n’a pas encore dupliqué tous les blocs.
virt-sysprep : réinitialiser l’identité
Copier l’image autonome, puis faire le sysprep de la copie. --reflink=auto partage les étendues si le système de fichiers le supporte, sinon il effectue une copie normale, y compris sur ext4. -n est une exécution à sec qui jette ses écritures :
cp --reflink=auto \
/mnt/extra2/vms/ubuntu26.04-base14gb-flat.qcow2 \
/mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2
virt-sysprep -n -a /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2
virt-sysprep -a /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
--hostname ubuntu-template
Sur un pool Ubuntu par défaut, l’image a souvent le mode 0600 et est possédée par libvirt-qemu. Le manuel recommande de donner à votre utilisateur l’accès en écriture plutôt que d’exécuter en root. Quand l’utilisateur qemu possède le fichier, sudo virt-sysprep -a ... est l’appel qui peut l’ouvrir. L’invité doit être éteint, et rien d’autre ne doit avoir l’image ouverte.
--hostname est une option de personnalisation, et la personnalisation fait partie de l’ensemble d’opérations par défaut, donc elle s’exécute dans le même appel. Il n’y a pas d’opération par défaut séparée qui efface /etc/hostname seule. --operations remplace cet ensemble par défaut quand vous le passez ; --operations defaults,-ssh-userdir conserve les valeurs par défaut et désactive une opération.
Ces sont les opérations qui décident si le clone entre en collision avec l’original. La liste est celle du manuel virt-sysprep actuel, qui vaut la peine d’être lu car une liste courte de --operations supprime silencieusement le reste :
| Opération | Par défaut | Effet sur l’invité |
|---|---|---|
| machine-id | oui | Efface l’ID de machine. systemd en génère un nouveau au prochain démarrage quand /etc/machine-id est vide. |
| ssh-hostkeys | oui | Supprime /etc/ssh/ssh_host_*. Le prochain démarrage crée de nouvelles clés hôte. |
| ssh-userdir | oui | Supprime .ssh sous /root et /home/*, y compris authorized_keys et les clés privées stockées dans l’invité. |
| dhcp-client-state | oui | Supprime les baux de client DHCP. |
| udev-persistent-net | oui | Supprime les règles udev qui associent une ancienne MAC à un nom fixe comme eth0. |
| net-hwaddr | oui | Supprime HWADDR des fichiers ifcfg-* de Fedora et RHEL. Il n’édite pas le netplan d’Ubuntu. |
| lvm-uuids, lvm-system-devices | oui | Assigner de nouveaux UUIDs LVM et supprime /etc/lvm/devices/system.devices, qui sinon attache l’invité aux WWIDs du disque source. |
| logfiles, bash-history, tmp-files | oui | Supprime les journaux, l’historique du shell et les fichiers temporaires. |
ssh-userdir est celle qui surprend les gens qui clonent une machine à laquelle ils sont encore connectés. Le modèle ne devrait pas contenir les clés privées de la source, donc laisser l’opération activée et injecter une clé par instance plus tard. Pour une copie à usage unique qui doit conserver les authorized_keys existantes, passer --operations defaults,-ssh-userdir.
user-account n’est pas dans l’ensemble par défaut, et les mots de passe restent à moins de passer --password ou --root-password. fs-uuids est également désactivé par défaut. Le manuel dit qu’il ne met pas à jour toutes les références, y compris /etc/fstab, et que l’activer risque de rendre l’invité non démarrable.
Les images Ubuntu Server ont généralement cloud-init, et virt-sysprep n’a pas d’opération cloud-init. Un ancien ID d’instance sous /var/lib/cloud fait sauter la configuration du premier démarrage au clone. Nettoyez-le sur le modèle, et dites à cloud-init de laisser le nom d’hôte que --hostname a écrit :
virt-customize -a /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
--run-command 'if command -v cloud-init >/dev/null 2>&1; then cloud-init clean --logs --seed; fi' \
--write '/etc/cloud/cloud.cfg.d/99-preserve-hostname.cfg:preserve_hostname: true'
Le même manuel met en garde contre le clonage d’un invité qui utilise le chiffrement complet du disque interne pour la distribution : toutes les copies partagent la clé du volume. Il note également que les fichiers supprimés sont déliés, pas purgés. --scrub écrase un fichier nommé, et virt-sparsify peut supprimer l’espace libéré de l’image.
Comment le clone obtient son adresse IP
virt-sysprep n’a pas d’opération qui réécrit une adresse. Un invité qui utilisait le DHCP redemande. Le clone a une nouvelle MAC, un machine-id vide et aucun ancien fichier de bail, donc le serveur DHCP sur le réseau default de libvirt le traite comme un nouveau client.
Un bloc addresses: statique dans netplan est copié avec le disque, et les deux invités l’affirment ensuite. Lire les fichiers avant le premier démarrage. virt-ls et virt-cat sont les outils à usage unique ; guestfish --ro -a <disk> -i est la même inspection qu’un shell, après quoi ls /etc/netplan et cat s’exécutent sur l’invité :
virt-ls -a /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 /etc/netplan
virt-cat -a /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
/etc/netplan/00-installer-config.yaml
Les images d’installation utilisent souvent 00-installer-config.yaml ou 01-netcfg.yaml. Les images cloud utilisent 50-cloud-init.yaml, que cloud-init recréera sauf si la configuration réseau est désactivée. Netplan fusionne tous les fichiers YAML du répertoire, donc un fichier statique restant s’applique toujours après l’ajout d’un fichier DHCP.
Pour faire du modèle un client DHCP, supprimer ces fichiers et en téléverser un de remplacement. Utiliser le nom d’interface que virt-cat a affiché. Sur un invité installé sous KVM, ce nom est souvent ens3 ou enp1s0, et virt-clone conserve le même slot PCI virtuel, donc le nom reste valide :
cat > /tmp/99-dhcp.yaml <<'EOF'
network:
version: 2
ethernets:
ens3:
dhcp4: true
EOF
virt-customize -a /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
--delete '/etc/netplan/*.yaml' \
--upload /tmp/99-dhcp.yaml:/etc/netplan/99-dhcp.yaml \
--write '/etc/cloud/cloud.cfg.d/99-disable-network.cfg:network: {config: disabled}'
Pour une adresse statique, une passerelle et des DNS, utiliser le même téléversement avec le YAML de Comment changer une adresse IP statique dans Ubuntu Server. Chaque instance a ensuite besoin de son propre fichier, appliqué au disque de l’instance plutôt qu’au modèle.
Le nom dans le YAML doit exister à l’intérieur de l’invité. Un disque déplacé depuis du matériel physique nomme souvent l’interface réseau enp2s0, tandis que le même système sous virtio présente un nom différent, et netplan configure alors une interface qui n’est pas là. Pour un modèle qui doit démarrer sur plus d’un type de machine, épingler le noyau à eth0 et utiliser cette clé dans netplan. Ubuntu source /etc/default/grub.d/*.cfg lors de la construction de grub.cfg :
virt-customize -a /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
--write '/etc/default/grub.d/99-eth0.cfg:GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX net.ifnames=0 biosdevname=0"' \
--run-command 'update-grub'
update-grub s’exécute dans l’appareil libguestfs. Si grub-probe ne peut pas voir le disque de démarrage là-bas, la commande échoue et la cmdline est inchangée. Dans ce cas, définir le nom d’interface dans netplan au nom que l’invité utilise déjà, et sauter le basculement vers eth0.
Personnalisation par instance avec virt-customize
Démarrer les instances à partir de copies du fichier propre. Ne pas pointer un domaine vers le modèle lui-même.
Une copie complète n’a pas de dépendance d’exécution sur le modèle :
cp --reflink=auto \
/mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
/mnt/extra2/vms/ubuntu26.04-vm1.qcow2
Un overlay stocke uniquement les blocs écrits par vm1. -F qcow2 enregistre le format de la base pour que QEMU n’ait pas à le sonder :
qemu-img create -f qcow2 \
-b /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
-F qcow2 \
/mnt/extra2/vms/ubuntu26.04-vm1.qcow2
Le chemin de la base est stocké à l’intérieur de l’overlay. Il doit conserver ce chemin, et il doit rester en lecture seule, pour tous les invités construits ainsi.
Les notes de sécurité de virt-sysprep décrivent un second passage sur chaque nouveau disque. Sysprep écrit une graine aléatoire dans le modèle ; les invités clonés à partir de ce fichier commenceraient sinon avec la même graine, ce qui rend les clés hôte SSH du premier démarrage et les numéros de séquence TCP prévisibles. --enable customize réécrit la graine. --hostname et --ssh-inject sont des options de personnalisation, donc elles appartiennent à la même commande. Substituer le compte qui existe réellement dans l’image pour ubuntu :
virt-sysprep --enable customize \
-a /mnt/extra2/vms/ubuntu26.04-vm1.qcow2 \
--hostname vm1 \
--ssh-inject "ubuntu:file:${HOME}/.ssh/id_ed25519.pub"
Remettre le fichier d’instance à libvirt, pas le modèle. Si vous l’avez créé en tant que votre utilisateur en dehors d’un pool de stockage, libvirt-qemu a besoin d’un accès en lecture ou le domaine échoue au démarrage avec une erreur d’autorisation sur le qcow2.
Importer dans Virt-Manager
Pour chaque disque d’instance, ouvrir Virt-Manager, choisir Nouvelle machine virtuelle et sélectionner Importer une image disque existante. Pointer vers ubuntu26.04-vm1.qcow2. L’entrée du système d’exploitation doit être Ubuntu 26.04 quand la base de données osinfo de l’hôte l’a.
L’identifiant court correspondant est ubuntu26.04. Vérifier la base de données de l’hôte avant de s’y fier :
osinfo-query os | grep ubuntu26
Si cela n’affiche rien, la base de données installée est plus ancienne que l’entrée 26.04. --os-variant ubuntu24.04 sélectionne toujours un type de machine favorable à virtio pour un invité déjà installé. --import dit à virt-install que le disque contient déjà un système d’exploitation.
sudo virt-install --name ubuntu26.04-vm1 \
--memory 4096 --vcpus 2 \
--disk path=/mnt/extra2/vms/ubuntu26.04-vm1.qcow2,format=qcow2 \
--import \
--os-variant ubuntu26.04 \
--network network=default \
--noautoconsole
--network network=default attache le réseau NAT dont l’instance dnsmasq distribue le bail DHCP. Après le démarrage :
virsh domifaddr ubuntu26.04-vm1 --source lease
virsh dumpxml ubuntu26.04-vm1 | grep "<mac"
--source lease lit cette table dnsmasq. Il reste vide pour une adresse statique, pour un pont, ou pour une carte réseau qui n’est pas sur un réseau virtuel libvirt. Ces invités ont besoin de qemu-guest-agent dans l’image et de virsh domifaddr ubuntu26.04-vm1 --source agent, ou d’une recherche ARP avec --source arp. virsh net-dhcp-leases default liste tous les baux sur le réseau NAT quand vous voulez la vue du pool plutôt qu’un domaine.
Choisir une stratégie de clonage : copie complète, overlay ou reflink
| Stratégie | Espace par VM | Temps de création | Contrainte | Utiliser quand |
|---|---|---|---|---|
Copie complète, ou cp --reflink=auto |
environ 14 GB logiques ; reflink partage les blocs jusqu’à ce qu’ils changent | minutes, ou quasi-instantané avec reflink | reflink a besoin d’un système de fichiers qui le supporte, comme btrfs | un invité qui doit survivre au modèle |
| Overlay qcow2 | mégaoctets au début | secondes | le chemin de la base doit rester, et la base doit rester en lecture seule | beaucoup d’invités similaires à partir d’une image scellée |
virt-clone --reflink |
image brute, étendues partagées | quasi-instantané | disques brutes sur le même système de fichiers btrfs ; qcow2 est ignoré | images brutes déjà stockées sur btrfs |
Un invité que vous prévoyez de conserver pendant des mois est une copie complète ou un reflink. Un invité à durée courte peut être un overlay, tant que le fichier de base est encore là quand il tourne. Proxmox est l’autre voie auto-hébergée quand vous voulez un modèle de type centre de données et un modèle de clonage sur son propre interface web. Multipass lance des images cloud Ubuntu pour un seul utilisateur et applique cloud-init lui-même, ce qui est un flux de travail différent de celui qui scelle un disque déjà installé.
Dépannage : quand le clone ne démarre pas
Pas d’adresse. virt-cat le fichier netplan et comparer la clé d’interface avec ip link sur la console. Une entrée match: macaddress toujours définie sur la MAC source fait tomber la nouvelle carte réseau. Une clé qui nomme une interface que l’invité n’a pas fait la même chose. Corriger le fichier sur le disque, ou appliquer la cmdline eth0 ci-dessus et reconstruire l’instance à partir du modèle.
Adresse en haut, identique à l’original. Le bloc addresses: statique est toujours dans l’un des fichiers netplan. virt-sysprep ne l’a pas supprimé. Téléverser un remplacement et supprimer les autres fichiers YAML dans /etc/netplan.
SSH dit que la clé hôte a changé, ou accepte le clone comme l’original. Les clés hôte sont partagées quand ssh-hostkeys n’a pas été exécuté sur le fichier que le domaine ouvre. Confirmer avec virsh domblklist que le domaine utilise le disque sysprepped, puis vérifier qemu-img info pour que vous n’ayez pas syspreppé un overlay tandis que l’invité démarre depuis un chemin différent. Si le clone a conservé l’IP d’origine volontairement, les clients qui ont stocké l’ancienne clé dans known_hosts avertiront jusqu’à ce que cette ligne soit supprimée. Cet avertissement est la régénération décrite par le manuel.
La connexion par clé échoue sur un clone d’une machine à laquelle vous pouviez accéder avant. Le sysprep par défaut a supprimé .ssh des répertoires personnels. Injecter une clé avec --ssh-inject, ou ré-exécuter avec --operations defaults,-ssh-userdir si cette copie aurait dû les conserver.
Volumes LVM manquants après le démarrage. L’invité a /etc/lvm/devices/system.devices de la source, et le WWID du disque virtuel a changé. L’opération par défaut lvm-system-devices supprime ce fichier. Une liste --operations choisie à la main doit l’inclure, et lvm-uuids, quand l’invité utilise LVM.
Un clone ou un modèle
Une seule machine supplémentaire est virt-clone, une vérification de fichier backing, et virt-sysprep sur le nouveau disque. Une flotte est un fichier autonome scellé, puis une copie ou un overlay par invité, avec --enable customize sur le disque propre de cet invité avant son démarrage.
Les overlays font du fichier scellé partie du chemin d’exécution de tous les invités qui l’appellent. Les copies complètes et les reflinks ne le font pas. Choisir cette dépendance avec la durée de vie de l’invité, et laisser fs-uuids désactivé pour que le chargeur de démarrage et /etc/fstab correspondent toujours au système de fichiers.
Liens utiles
- Outils de développement : Le guide complet des flux de travail de développement modernes
- Comment installer Ubuntu 24.04 et les outils utiles
- GNOME Boxes : Fonctionnalités, avantages, défis et alternatives
Références
- virt-clone(1) sur Ubuntu 26.04, y compris
--auto-clone,--fileet--reflink - virt-sysprep(1) opérations, modifications sur place et la note sur la graine aléatoire
- virt-customize(1) pour
--hostname,--ssh-inject,--uploadet--run-command - qemu-img
info,convertetcreate -b/-F - virt-install(1)
--importet--os-variant - Entrée Ubuntu 26.04 de osinfo-db, identifiant court
ubuntu26.04 - machine-id(5) sur la façon dont un
/etc/machine-idvide est remplacé au démarrage