Preparação completa de três servidores bare-metal como hypervisors KVM/Libvirt — a camada física que sustenta todo o ecossistema desta wiki: os templates criados com Packer e os laboratórios da série Terraform rodam exatamente nestes hosts, usando os pools de storage definidos aqui.
| Servidor | RAM | Disco | IP | Hostname | SO |
|---|---|---|---|---|---|
| IBM System x3550 M2 | 64 GB | 1.6 TB | 192.168.0.250 |
kvm-01 | Debian 13 |
| IBM System x3550 M2 | 64 GB | 1.6 TB | 192.168.0.251 |
kvm-02 | Debian 13 |
| IBM System x3550 M4 | 128 GB | 1.2 TB | 192.168.0.252 |
kvm-03 | Debian 13 |
Gerenciamento: toda a administração é feita a partir da estação de trabalho (Ubuntu 24.04) com virt-manager, SSH e Terraform — os hypervisors ficam headless.
Para que as VMs recebam IPs diretamente da rede física (em vez de ficarem atrás do NAT do libvirt), a interface física entra numa bridge Linux. Instale o suporte:
sudo apt install bridge-utils vim
enp11s0f0)# /etc/network/interfaces
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# Interface física: sem IP próprio — pertence à bridge
allow-hotplug enp11s0f0
iface enp11s0f0 inet manual
# Bridge
auto br0
iface br0 inet static
bridge_ports enp11s0f0
bridge_stp off
bridge_fd 0
bridge_maxwait 0
address 192.168.0.250 # kvm-02: 192.168.0.251
netmask 255.255.255.0
gateway 192.168.0.1
dns-nameservers 192.168.0.1
# IPv6 autoconfigurado na bridge
iface br0 inet6 auto
eno1)Mesmo conteúdo, trocando a interface física para eno1 e o endereço para 192.168.0.252:
# Interface física
allow-hotplug eno1
iface eno1 inet manual
iface eno1 inet6 manual
# Bridge
auto br0
iface br0 inet static
bridge_ports eno1
bridge_stp off
bridge_fd 0
bridge_maxwait 0
address 192.168.0.252
netmask 255.255.255.0
gateway 192.168.0.1
dns-nameservers 192.168.0.1
iface br0 inet6 auto
Dica real do laboratório: durante a configuração do kvm-03, o sudo reclamava
não foi possível resolver máquina kvm-03. O hostname novo ainda não estava no/etc/hosts— adicione127.0.1.1 kvm-03para silenciar o aviso.
Com forwarding ativo, o kernel ignora RAs por padrão — a bridge não autoconfiguraria IPv6. O valor accept_ra=2 força a aceitação mesmo com forwarding:
# Teste imediato
sudo sysctl -w net.ipv6.conf.br0.accept_ra=2
sudo sysctl -w net.ipv6.conf.br0.forwarding=1
# /etc/sysctl.d/99-libvirt-ipv6.conf — persistência
# Permitir Router Advertisement na bridge mesmo com forwarding
net.ipv6.conf.br0.accept_ra=2
net.ipv6.conf.br0.forwarding=1
# Garantir que a bridge aceite redirecionamentos
net.ipv6.conf.br0.accept_redirects=1
sudo sysctl -p /etc/sysctl.d/99-libvirt-ipv6.conf
sudo systemctl restart networking && exit # a sessão SSH cai — religue
ssh 192.168.0.250 # e .251, .252
ip a show br0
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP ...
inet 192.168.0.250/24 brd 192.168.0.255 scope global br0
inet6 2804:2084:523:2b01:a8a2:6cff:febe:777a/64 scope global dynamic mngtmpaddr proto kernel_ra
inet6 fe80::a8a2:6cff:febe:777a/64 scope link proto kernel_ll
Confirme em cada host: IPv4 estático correto + IPv6 global via kernel_ra (prova de que o RA está funcionando) + link-local.
sudo apt install libvirt-daemon-system virt-install libosinfo-bin genisoimage ovmf guestfs-tools
| Pacote | Papel |
|---|---|
libvirt-daemon-system |
Daemon libvirtd + rede default NAT |
virt-install |
Criação de VMs por linha de comando |
libosinfo-bin |
osinfo-query — banco de variantes de SO |
genisoimage |
Gera ISOs de cloud-init (mkisofs) |
ovmf |
Firmware UEFI para as VMs |
guestfs-tools |
Inspeção/edição de imagens (virt-customize etc.) |
sudo virsh version --daemon
Compilado usando a biblioteca: libvir 11.3.0
Hypervisor em execução: QEMU 10.0.7
Executando em daemon: 11.3.0
Adicione seu usuário aos grupos (evita sudo para cada virsh) e reinicie para aplicar:
getent group | egrep 'libvirt|kvm|qemu'
sudo usermod -aG kvm,libvirt $USER
sudo reboot
$ sudo systemctl status libvirtd
● libvirtd.service - libvirt legacy monolithic daemon
Active: active (running) ...
O /datastore é uma partição dedicada criada na instalação do SO. Três pools com papéis distintos:
sudo mkdir -p /datastore/{images,isos,templates}
images — discos qcow2 das VMs em execução (pool default);templates — golden images prontas para clonagem — é daqui que a série Terraform lê os backing stores e onde o Packer grava suas saídas;isos — imagens de instalação (.iso).sudo virsh pool-define-as --name default --type dir --target /datastore/images
sudo virsh pool-define-as --name isos --type dir --target /datastore/isos
sudo virsh pool-define-as --name templates --type dir --target /datastore/templates
sudo virsh pool-autostart default
sudo virsh pool-autostart isos
sudo virsh pool-autostart templates
sudo virsh pool-start default
sudo virsh pool-start isos
sudo virsh pool-start templates
$ sudo virsh pool-list
Nome Estado Auto-iniciar
------------------------------------
default ativo sim
isos ativo sim
templates ativo sim
O pool
defaulté redefinido de propósito: por padrão ele aponta para/var/lib/libvirt/images(partição raiz). Aqui o redefinimos para/datastore/images, mantendo o nome que as ferramentas assumem por padrão.
O Debian confina o QEMU via AppArmor — VMs que tentem usar discos fora dos caminhos padrão são bloqueadas com Permission denied. A exceção vai no mecanismo de override local (não edite o perfil principal):
sudo mkdir -p /etc/apparmor.d/local/abstractions
sudo vim /etc/apparmor.d/local/abstractions/libvirt-qemu
# Permissões para os pools
/datastore/images/ r,
/datastore/images/** rwk,
/datastore/templates/ r,
/datastore/templates/** rwk,
/datastore/isos/ r,
/datastore/isos/** r,
sudo systemctl reload apparmor
sudo systemctl restart libvirtd
sudo journalctl -xe | grep -i apparmor # não deve haver DENIED para /datastore
# ISO de instalação no pool correto
sudo wget -4 -T 30 --read-timeout=60 \
https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.4.0-amd64-netinst.iso \
-P /datastore/isos
# Confirmar a variante de SO reconhecida
osinfo-query os | grep debian
sudo virt-install \
--virt-type kvm \
--machine q35 \
--name debian13 \
--description "Debian Trixie" \
--boot uefi \
--cdrom /datastore/isos/debian-13.4.0-amd64-netinst.iso \
--os-variant debian13 \
--disk pool=default,size=32,format=qcow2,bus=virtio,cache=none \
--memory 4096 \
--vcpus 2 \
--cpu host-passthrough \
--network=default,model=virtio \
--graphics spice \
--noautoconsole
O nome do arquivo importa:
--cdromdeve apontar para a ISO que você baixou de fato — o download muda a cada point release do Debian (current/). Confira comls /datastore/isos/antes de instalar.
Windows 11 exige UEFI com Secure Boot e TPM 2.0 — o libvirt emula ambos (swtpm):
sudo virt-install \
--name win11 \
--os-variant win11 \
--virt-type kvm \
--machine q35 \
--vcpus 4 \
--memory 8192 \
--boot uefi,loader_secure=yes \
--tpm backend.type=emulator,backend.version=2.0,model=tpm-tis \
--cpu host-passthrough \
--disk pool=default,size=64,format=qcow2,bus=virtio,cache=none \
--cdrom /datastore/isos/Win11_22H2_English_x64v1.iso \
--disk path=/datastore/isos/virtio-win-0.1.285.iso,device=cdrom \
--network network=default,model=virtio \
--graphics spice \
--noautoconsole
O segundo CD-ROM carrega os drivers virtio-win — sem eles o instalador do Windows não enxerga o disco virtio.
ssh-keygen -t ed25519 -f ~/.ssh/kvm
ssh-copy-id -i ~/.ssh/kvm.pub 192.168.0.250
ssh-copy-id -i ~/.ssh/kvm.pub 192.168.0.251
ssh-copy-id -i ~/.ssh/kvm.pub 192.168.0.252
# ~/.ssh/config — um bloco por hypervisor, sem duplicar nomes
Host kvm-01
HostName 192.168.0.250
User gean
IdentityFile ~/.ssh/kvm
Host kvm-02
HostName 192.168.0.251
User gean
IdentityFile ~/.ssh/kvm
Host kvm-03
HostName 192.168.0.252
User gean
IdentityFile ~/.ssh/kvm
qemu+sshsudo apt install virt-manager
virsh -c qemu+ssh://gean@kvm-02/system list
virsh -c qemu+ssh://gean@kvm-02/system console debian13
virt-manager --connect qemu+ssh://gean@kvm-01/system
virt-manager --connect qemu+ssh://gean@kvm-02/system
virt-manager --connect qemu+ssh://gean@kvm-03/system
Para uma sessão focada em um host, exporte a URI padrão:
export LIBVIRT_DEFAULT_URI="qemu+ssh://gean@192.168.0.250/system"
virsh list --all
virsh dominfo debian13
Ou crie aliases no ~/.bashrc:
alias virsh-kvm-01='virsh -c qemu+ssh://gean@192.168.0.250/system'
alias virsh-kvm-02='virsh -c qemu+ssh://gean@192.168.0.251/system'
alias virsh-kvm-03='virsh -c qemu+ssh://gean@192.168.0.252/system'
Reinstalou um hypervisor? O fingerprint muda e o SSH recusa a conexão. Limpe a entrada antiga com
ssh-keygen -R 192.168.0.251antes dossh-copy-id.
defaultA rede default do libvirt faz NAT IPv4 automaticamente, mas não o equivalente em IPv6. Para que as VMs dessa rede tenham saída IPv6, adicionamos o masquerade v6 no host (saída pela br0):
sudo ip6tables -t nat -A POSTROUTING -o br0 -j MASQUERADE
sudo apt install iptables-persistent
sudo netfilter-persistent save
sudo cat /etc/iptables/rules.v4
sudo cat /etc/iptables/rules.v6
Escopo: esta regra atende apenas a rede NAT
defaultdo libvirt (virbr0). VMs penduradas diretamente nabr0recebem IPv6 global via RA e não passam por NAT. É uma solução de laboratório — o ideal é IPv6 roteado com prefixo delegado.
Com os três hypervisors prontos, o ciclo continua:
templates;