Clone uma VM no Virt-Manager com virt-clone e virt-sysprep
Clonar uma VM copia bytes, não identidade.
O Virt-Manager (a interface gráfica do libvirt) copia um disco KVM e atribui ao clone um UUID e um MAC. O sistema convidado (guest) mantém seu machine-id e as chaves de host SSH até que o virt-sysprep os remova.
Este guia prático utiliza um convidado Ubuntu 26.04 e uma imagem qcow2 de 14 GB armazenada em /mnt/extra2/vms. Os comandos de disco são os mesmos para outros convidados Linux. O virt-sysprep não opera em convidados Windows.

O host já precisa ter KVM e libvirt. Como instalar KVM no Ubuntu 24.04 é a configuração necessária, e ela inclui o virtinst, que fornece o virt-clone. O virt-sysprep, virt-customize, virt-cat e guestfish vêm de um pacote separado:
sudo apt install -y libguestfs-tools
O que realmente clona uma VM
O libvirt divide a tarefa entre três ferramentas. O virt-clone copia as imagens de disco e define um novo domínio com o mesmo hardware virtual. Ele altera o nome do domínio, o UUID e o MAC do lado do host. Senhas, o nome do host, endereços estáticos e arquivos dentro do convidado não são alterados, o que é o comportamento documentado pela virt-clone(1).
O virt-sysprep abre o disco com o libguestfs e edita o sistema de arquivos do convidado. O manual do virt-sysprep(1) é explícito em dizer que a edição é feita in loco (no próprio arquivo): não existe uma flag de arquivo de saída, portanto a imagem que você passa em -a é a imagem que será alterada. Copie ou clone primeiro se ainda precisar da fonte.
O qemu-img info relata se esse arquivo é independente (standalone) ou o topo de uma cadeia de backup (backing chain). O qemu-img convert escreve um novo arquivo com a cadeia resolvida.
Aplique “flatten” (achate) antes do sysprep quando houver uma linha de backup. Execute o sysprep na cópia, depois derive cada convidado em execução a partir desse arquivo.
Clonando o disco no Virt-Manager
Desligue o convidado. O virt-clone rejeita um domínio em execução, e uma cópia de um qcow2 ao vivo não é um sistema de arquivos consistente.
No Virt-Manager, clique com o botão direito no convidado e escolha Clone. Defina o novo nome. Na etapa de armazenamento, dê a cada disco um novo caminho. Deixar o caminho original no lugar define um segundo domínio que abre o mesmo arquivo, então ambos os convidados escrevem nos mesmos blocos.
O novo arquivo é colocado ao lado da fonte. Um pool padrão usa /var/lib/libvirt/images/. Um disco que já está em /mnt/extra2/vms é clonado para esse diretório. Anote o caminho que o virt-clone imprime, ou leia-o de volta:
virsh domblklist ubuntu26.04-base14gb-clone
O equivalente na linha de comando, com o nome e o caminho do disco escolhidos explicitamente:
virt-clone --original ubuntu26.04-base14gb \
--name ubuntu26.04-base14gb-clone \
--file /mnt/extra2/vms/ubuntu26.04-base14gb-clone.qcow2
--auto-clone inventa o nome e o caminho do disco. Isso é conveniente para uma cópia descartável. Um caminho de template é mais fácil de manter quando você mesmo passa --name e --file. Omita --mac, ou passe --mac RANDOM, e o virt-clone gerará um endereço na faixa do QEMU 52:54:00:xx:xx:xx.
--reflink solicita uma cópia leve. O manual do virt-clone do Ubuntu 26.04 limita essa flag a imagens raw no mesmo sistema de arquivos btrfs, portanto ela ignora esses arquivos qcow2. Um overlay qcow2 é uma configuração separada, coberta com qemu-img create -b abaixo.
Seu clone tem um arquivo de backup?
Execute isto no novo disco antes de tratá-lo como independente:
qemu-img info --backing-chain /mnt/extra2/vms/ubuntu26.04-base14gb-clone.qcow2
Uma imagem independente lista file format, virtual size e disk size. Um overlay também lista uma linha backing file: apontando para a imagem através da qual ele lê. virtual size é o tamanho do disco do convidado, aqui cerca de 14 GB. disk size é quanto espaço o arquivo atualmente ocupa, o que é pequeno para um overlay novo e cresce conforme o convidado escreve.
O virt-clone não é a fonte usual dessa linha. Um overlay vem de qemu-img create -b, de um snapshot somente de disco, ou de uma ferramenta que criou um delta qcow2 propositalmente. A verificação de info é o que distingue esses casos de uma cópia completa.
Mantenha o overlay apenas quando a base permanecer onde está e não for escrita novamente. Cada escrita do clone cai no arquivo pequeno; leituras que não encontram o dado no overlay vêm da base. Mover ou editar a base quebra todos os convidados que a nomeiam.
Para criar um arquivo independente, converta o overlay. -p imprime o progresso. O destino é um novo arquivo; o overlay e a base permanecem como estão:
qemu-img convert -p -O qcow2 \
/mnt/extra2/vms/ubuntu26.04-base14gb-clone.qcow2 \
/mnt/extra2/vms/ubuntu26.04-base14gb-flat.qcow2
Execute qemu-img info no arquivo flat e confirme que não há uma linha backing file:. Um template é esse arquivo independente. Overlays são como você gera convidados a partir dele mais tarde, não o próprio template.
Um reflink btrfs é um terceiro caso. cp --reflink=auto pode compartilhar extensões físicas entre dois arquivos, e qemu-img info ainda não mostra um arquivo de backup, porque cada caminho é uma imagem completa. Essa cópia é independente na camada qcow2, mesmo que o sistema de arquivos ainda não tenha duplicado cada bloco.
virt-sysprep: resetando a identidade
Copie a imagem independente, depois execute sysprep na cópia. --reflink=auto compartilha extensões quando o sistema de arquivos suporta e, caso contrário, faz uma cópia normal, incluindo no ext4. -n é uma execução de teste (dry run) que descarta suas escritas:
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
Em um pool padrão do Ubuntu, a imagem muitas vezes tem modo 0600 e é propriedade de libvirt-qemu. O manual recomenda dar acesso de escrita ao seu usuário em vez de executar como root. Quando o usuário qemu é o dono do arquivo, sudo virt-sysprep -a ... é a chamada que pode abri-lo. O convidado deve estar desligado, e nada mais deve ter a imagem aberta.
--hostname é uma opção de customização, e customização faz parte do conjunto de operações padrão, portanto ela é executada na mesma chamada. Não existe uma operação padrão separada que limpe /etc/hostname sozinha. --operations substitui esse conjunto padrão quando você o passa; --operations defaults,-ssh-userdir mantém os padrões e desliga uma operação.
Estas são as operações que decidem se o clone colide com o original. A lista é a do manual atual do virt-sysprep, que vale a pena ler porque uma lista curta de --operations remove silenciosamente o restante:
| Operação | Padrão | Efeito no convidado |
|---|---|---|
| machine-id | sim | Limpa o ID da máquina. O systemd gera um novo na próxima inicialização quando /etc/machine-id está vazio. |
| ssh-hostkeys | sim | Remove /etc/ssh/ssh_host_*. A próxima inicialização cria novas chaves de host. |
| ssh-userdir | sim | Remove .ssh sob /root e /home/*, incluindo authorized_keys e chaves privadas armazenadas no convidado. |
| dhcp-client-state | sim | Remove locações de cliente DHCP. |
| udev-persistent-net | sim | Remove regras udev que mapeiam um MAC antigo para um nome fixo como eth0. |
| net-hwaddr | sim | Remove HWADDR de arquivos ifcfg-* do Fedora e RHEL. Não edita o netplan do Ubuntu. |
| lvm-uuids, lvm-system-devices | sim | Atribui novos UUIDs LVM e remove /etc/lvm/devices/system.devices, o que de outra forma prende o convidado aos WWIDs do disco de origem. |
| logfiles, bash-history, tmp-files | sim | Remove logs, histórico de shell e arquivos temporários. |
ssh-userdir é a que surpreende pessoas clonando uma máquina em que ainda fazem login. O template não deve carregar as chaves privadas da fonte, portanto mantenha a operação ligada e injete uma chave por instância mais tarde. Para uma cópia única que deve manter o authorized_keys existente, passe --operations defaults,-ssh-userdir.
user-account não está no conjunto padrão, e as senhas permanecem a menos que você passe --password ou --root-password. fs-uuids também está desligado por padrão. O manual diz que ele não atualiza todas as referências, incluindo /etc/fstab, e que ativá-lo provavelmente tornará o convidado não iniciável (unbootable).
Imagens do Ubuntu Server geralmente têm cloud-init, e o virt-sysprep não tem uma operação para o cloud-init. Um antigo ID de instância sob /var/lib/cloud faz o clone pular a configuração da primeira inicialização. Limpe-o no template e diga ao cloud-init para manter o hostname que --hostname escreveu:
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'
O mesmo manual adverte contra clonar um convidado que usa criptografia de disco interno completa para distribuição: todas as cópias compartilham a chave do volume. Ele também nota que arquivos excluídos são desvinculados (unlinked), não apagados (scrubbed). --scrub sobrescreve um arquivo nomeado, e virt-sparsify pode remover espaço liberado da imagem.
Como o clone obtém seu endereço IP
virt-sysprep não tem uma operação que reescreva um endereço. Um convidado que usava DHCP pede novamente. O clone tem um novo MAC, um machine-id vazio e nenhum arquivo de locação antigo, portanto o servidor DHCP na rede default do libvirt o trata como um novo cliente.
Um bloco estático addresses: no netplan é copiado com o disco, e ambos os convidados então o reivindicam. Leia os arquivos antes da primeira inicialização. virt-ls e virt-cat são as ferramentas de uso único; guestfish --ro -a <disk> -i é a mesma inspeção como um shell, após o qual ls /etc/netplan e cat são executados contra o convidado:
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
Imagens de instalador muitas vezes usam 00-installer-config.yaml ou 01-netcfg.yaml. Imagens de nuvem usam 50-cloud-init.yaml, que o cloud-init recriará a menos que a configuração de rede esteja desabilitada. O Netplan mescla todos os arquivos YAML no diretório, portanto um arquivo estático residual ainda se aplica depois que você adiciona um arquivo DHCP.
Para tornar o template um cliente DHCP, remova esses arquivos e faça upload de um substituto. Use o nome da interface que o virt-cat mostrou. Em um convidado instalado sob KVM, esse nome frequentemente é ens3 ou enp1s0, e o virt-clone mantém o mesmo slot PCI virtual, portanto o nome permanece válido:
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}'
Para um endereço estático, gateway e DNS, use o mesmo upload com o YAML de Como alterar um endereço IP estático no Ubuntu Server. Cada instância então precisa do seu próprio arquivo, aplicado ao disco da instância em vez do template.
O nome no YAML tem que existir dentro do convidado. Um disco movido de hardware físico frequentemente nomeia a NIC enp2s0, enquanto o mesmo sistema sob virtio apresenta um nome diferente, e o netplan então configura uma interface que não está lá. Para um template que deve iniciar em mais de um tipo de máquina, fixe o kernel em eth0 e use essa chave no netplan. O Ubuntu usa fontes de /etc/default/grub.d/*.cfg enquanto constrói 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 é executado dentro do appliance libguestfs. Se grub-probe não consegue ver o disco de boot lá, o comando falha e o cmdline permanece inalterado. Nesse caso, defina o nome da interface no netplan para o nome que o convidado já usa e pule a troca para eth0.
Personalização por instância com virt-customize
Inicie as instâncias a partir de cópias do arquivo limpo. Não aponte um domínio para o próprio template.
Uma cópia completa não tem dependência de runtime no template:
cp --reflink=auto \
/mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
/mnt/extra2/vms/ubuntu26.04-vm1.qcow2
Um overlay armazena apenas os blocos que vm1 escreve. -F qcow2 registra o formato da base para que o QEMU não precise sondá-lo (probe):
qemu-img create -f qcow2 \
-b /mnt/extra2/vms/ubuntu26.04-base14gb-clean.qcow2 \
-F qcow2 \
/mnt/extra2/vms/ubuntu26.04-vm1.qcow2
O caminho da base é armazenado dentro do overlay. Ele tem que manter esse caminho, e tem que permanecer somente leitura, para todos os convidados construídos desta forma.
As notas de segurança do virt-sysprep descrevem uma segunda passada em cada disco novo. O sysprep escreve uma semente aleatória (seed) no template; convidados clonados a partir desse arquivo de outra forma começariam com a mesma semente, o que torna as chaves de host SSH da primeira inicialização e os números de sequência TCP previsíveis. --enable customize reescreve a semente. --hostname e --ssh-inject são opções de customização, portanto pertencem ao mesmo comando. Substitua a conta que realmente existe na imagem por ubuntu:
virt-sysprep --enable customize \
-a /mnt/extra2/vms/ubuntu26.04-vm1.qcow2 \
--hostname vm1 \
--ssh-inject "ubuntu:file:${HOME}/.ssh/id_ed25519.pub"
Entregue o arquivo da instância ao libvirt, não o template. Se você o criou como seu usuário fora de um pool de armazenamento, libvirt-qemu precisa de acesso de leitura ou o domínio falha na inicialização com um erro de permissão no qcow2.
Importando para o Virt-Manager
Para cada disco de instância, abra o Virt-Manager, escolha Nova Máquina Virtual e selecione Importar imagem de disco existente. Aponte para ubuntu26.04-vm1.qcow2. A entrada de SO deve ser Ubuntu 26.04 quando o banco de dados osinfo do host a tiver.
O short id correspondente é ubuntu26.04. Verifique o banco de dados do host antes de confiar nele:
osinfo-query os | grep ubuntu26
Se isso não imprimir nada, o banco de dados instalado é mais antigo que a entrada 26.04. --os-variant ubuntu24.04 ainda seleciona um tipo de máquina amigável ao virtio para um convidado que já está instalado. --import diz ao virt-install que o disco já contém um SO.
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 anexa a rede NAT cuja instância dnsmasq distribui a locação DHCP. Após o boot:
virsh domifaddr ubuntu26.04-vm1 --source lease
virsh dumpxml ubuntu26.04-vm1 | grep "<mac"
--source lease lê essa tabela dnsmasq. Permanece vazio para um endereço estático, para uma ponte, ou para uma NIC que não está em uma rede virtual do libvirt. Esses convidados precisam de qemu-guest-agent na imagem e virsh domifaddr ubuntu26.04-vm1 --source agent, ou uma verificação ARP com --source arp. virsh net-dhcp-leases default lista todas as locações na rede NAT quando você quer a visão do pool em vez de um domínio.
Escolhendo uma estratégia de clone: cópia completa, overlay ou reflink
| Estratégia | Espaço por VM | Tempo para criar | Restrição | Usar quando |
|---|---|---|---|---|
Cópia completa, ou cp --reflink=auto |
cerca de 14 GB lógicos; reflink compartilha blocos até que mudem | minutos, ou quase instantâneo com reflink | reflink precisa de um sistema de arquivos que suporte, como btrfs | um convidado que deve sobreviver ao template |
| Overlay qcow2 | megabytes no início | segundos | caminho da base deve permanecer, e a base deve permanecer somente leitura | muitos convidados similares de uma imagem selada |
virt-clone --reflink |
imagem raw, extensões compartilhadas | quase instantâneo | discos raw no mesmo sistema de arquivos btrfs; qcow2 é ignorado | imagens raw já armazenadas em btrfs |
Um convidado que você espera manter por meses é uma cópia completa ou um reflink. Um convidado de curta duração pode ser um overlay, desde que o arquivo base ainda esteja lá quando ele executar. Proxmox é o outro caminho self-hosted quando você quer um modelo de template e clone de estilo datacenter em sua própria interface web. Multipass inicia imagens de nuvem Ubuntu para um único usuário e aplica cloud-init por conta própria, o que é um fluxo de trabalho diferente de selar um disco que você já instalou.
Solução de problemas: quando o clone não inicia
Sem endereço. Use virt-cat no arquivo netplan e compare a chave da interface com ip link no console. Uma entrada match: macaddress ainda definida para o MAC da fonte descarta a nova NIC. Uma chave que nomeia uma interface que o convidado não tem faz o mesmo. Corrija o arquivo no disco, ou aplique o cmdline eth0 acima e reconstrua a instância a partir do template.
Endereço ativo, o mesmo que o original. O bloco estático addresses: ainda está em um dos arquivos netplan. O virt-sysprep não o removeu. Faça upload de um substituto e remova os outros arquivos YAML em /etc/netplan.
SSH diz que a chave de host mudou, ou aceita o clone como o original. As chaves de host são compartilhadas quando ssh-hostkeys não foi executado no arquivo que o domínio abre. Confirme com virsh domblklist que o domínio usa o disco sysprepped, depois verifique qemu-img info para garantir que você não syspreparou um overlay enquanto o convidado inicia de um caminho diferente. Se o clone manteve o IP original propositalmente, clientes que armazenaram a chave antiga em known_hosts avisarão até que essa linha seja removida. Esse aviso é a regeneração descrita pelo manual.
Login por chave falha em um clone de uma máquina que você conseguia acessar antes. O sysprep padrão removeu .ssh dos diretórios home. Injete uma chave com --ssh-inject, ou reexecute com --operations defaults,-ssh-userdir se esta cópia deveria tê-las mantido.
Volumes LVM ausentes após o boot. O convidado tem /etc/lvm/devices/system.devices da fonte, e o WWID do disco virtual mudou. A operação padrão lvm-system-devices remove esse arquivo. Uma lista --operations escolhida à mão tem que incluí-lo, e lvm-uuids, quando o convidado usa LVM.
Um clone ou um template
Uma máquina extra única é virt-clone, uma verificação de arquivo de backup e virt-sysprep no novo disco. Uma frota (fleet) é um arquivo independente selado, depois uma cópia ou um overlay por convidado, com --enable customize no próprio disco desse convidado antes de ele iniciar.
Overlays tornam o arquivo selado parte do caminho de runtime de todos os convidados que o nomeiam. Cópias completas e reflinks não. Escolha essa dependência com a vida útil do convidado, e deixe fs-uuids desligado para que o bootloader e /etc/fstab ainda correspondam ao sistema de arquivos.
Links úteis
- Ferramentas de Desenvolvimento: O Guia Completo para Fluxos de Trabalho Modernos de Desenvolvimento
- [Como instalar Ubuntu 24.04 & ferramentas úteis](https://www.glukhov.org/pt/developer-tools/local-dev-platforms/install-linux-ubuntu-24-04/ “Como instalar o Ubuntu 24.04 - passos e pacotes e ferramentas úteis”})
- GNOME Boxes: Recursos, Vantagens, Desafios e Alternativas
Referências
- virt-clone(1) no Ubuntu 26.04, incluindo
--auto-clone,--filee--reflink - virt-sysprep(1) operações, edições in loco e a nota sobre a semente aleatória
- virt-customize(1) para
--hostname,--ssh-inject,--uploade--run-command - qemu-img
info,convertecreate -b/-F - virt-install(1)
--importe--os-variant - Entrada do Ubuntu 26.04 no osinfo-db, short id
ubuntu26.04 - machine-id(5) sobre como um
/etc/machine-idvazio é substituído na inicialização