KVM mora no seu kernel

KVM mora no seu kernel

Tem uma boa chance de você estar lendo isso numa máquina rodando Linux. E se for esse o caso, você tem um hypervisor completo instalado agora mesmo, sem ter feito nada pra isso. O KVM entrou no kernel Linux em 2007 e nunca mais saiu. Tá lá, esperando você usar.

Esse post é sobre entender o que diabos é KVM, como ele se relaciona com QEMU e libvirt, e como sair de zero até uma VM funcionando de verdade. Sem comandos quebrados, sem flags depreciadas, sem lero-lero.

Antes de qualquer coisa: seu CPU suporta?

KVM depende de extensões de hardware do processador. Na Intel é vmx, na AMD é svm. Sem isso, não tem KVM; tem só QEMU em modo de emulação pura, que é lento.

# Checar suporte — zero significa sem suporte, qualquer número > 0 é bom
grep -c '(vmx|svm)' /proc/cpuinfo

# Versão mais explícita
lscpu | grep -i virtualization
# Intel: "VT-x"
# AMD: "AMD-V"

Se retornar 0, pode ser que a virtualizção esteja desabilitada na BIOS/UEFI. Procure por "Intel VT-x", "AMD-V", "SVM" ou "Virtualization Technology" e habilite. Reinicia e testa de novo.

⚠️ Em VMs aninhadas (nested virtualization): se você está rodando Linux dentro de uma VM (Proxmox, VMware, etc.), a virtualização aninhada precisa estar habilitada no hypervisor pai. No Proxmox: CPU Type: host na VM. Sem isso, o KVM dentro da VM não enxerga as extensões.

O trio: KVM, QEMU e libvirt

Essa é a parte que todo tutorial pula e depois você fica confuso quando algo não funciona. São três coisas distintas que trabalham juntas:

KVM (Kernel-based Virtual Machine) é o módulo do kernel que faz a ponte entre o software e as extensões de hardware. Ele não cria VM nenhuma sozinho; é o motor. Expõe um dispositivo /dev/kvm que outros programas usam.

QEMU (Quick Emulator) é o emulador de hardware; cria os dispositivos virtuais que a VM enxerga: disco, placa de rede, GPU, USB. Quando usa QEMU com KVM, o código da VM roda quase na velocidade nativa (o hardware real executa as instruções). Quando usa QEMU sem KVM, tudo é emulado por software, o que funciona, mas é lento.

libvirt é a camada de gerenciamento em cima de tudo. É ela que fornece o virsh (CLI), o virt-manager (GUI) e a API que o Proxmox, oVirt e outros usam internamente. Você não precisa de libvirt pra usar KVM+QEMU, mas sem ela é você escrevendo comandos qemu-system-x86_64 de 30 flags na mão.

A analogia que uso:

  • KVM = o motor do carro
  • QEMU = o chassi, rodas e painel (o hardware completo)
  • libvirt = o painel de controle digital que facilita tudo

💡 Proxmox usa exatamente esse trio. Quando você cria uma VM no Proxmox, ele está chamando QEMU+KVM por baixo e usando uma versão customizada do libvirt pra gerenciar. Entender isso aqui faz tudo no Proxmox fazer mais sentido.

Instalando o stack completo

# Debian/Ubuntu
apt install -y qemu-system-x86 libvirt-daemon-system \
  libvirt-clients virtinst virt-manager \
  bridge-utils cpu-checker

# Fedora/RHEL/Rocky/Alma
dnf install -y @virtualization
systemctl enable --now libvirtd

# Arch
pacman -S qemu libvirt virt-manager virt-install bridge-utils
systemctl enable --now libvirtd

Adiciona seu usuário ao grupo libvirt (evita usar sudo em tudo):

usermod -aG libvirt $USER
# Precisa sair e entrar de novo na sessão pra aplicar

Verificar se tudo está funcionando:

# Confirmar que KVM está carregado
lsmod | grep kvm
# Deve mostrar kvm_intel (Intel) ou kvm_amd (AMD) + kvm

# Confirmar que libvirtd está rodando
systemctl status libvirtd

# Teste completo
virt-host-validate
# Cada linha deve mostrar PASS — WARN é aceitável, FAIL precisa de atenção

Criando a primeira VM

Com libvirt, o caminho mais direto é virt-install. Mas antes, precisamos de uma imagem ISO ou cloud-ready.

Com ISO (modo interativo)

# Baixar ISO (exemplo com Debian 12)
wget https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.9.0-amd64-netinst.iso

# Criar VM
virt-install \
  --name debian-12-teste \
  --memory 2048 \
  --vcpus 2 \
  --disk size=20,format=qcow2 \
  --cdrom debian-12.9.0-amd64-netinst.iso \
  --os-variant debian12 \
  --network network=default \
  --graphics vnc \
  --noautoconsole

⚠️ --disk tamanho= não existe. A flag correta é --disk size= (em inglês). Erro comum em tutoriais PT-BR que copiam sem testar.

Pra descobrir o --os-variant correto:

osinfo-query os | grep -i debian
# Filtre pelo distro que quiser — ubuntu, centos, fedora, etc.

Com imagem cloud-ready (modo automático)

Se você leu o post anterior sobre Cloud-init, sabe que essa é a forma mais rápida. Com virt-install você também pode usar imagens cloud direto:

# Baixar imagem Debian 12 cloud
wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2

# Expandir o disco antes (imagem base vem com ~2GB)
qemu-img resize debian-12-genericcloud-amd64.qcow2 +18G

# Criar cloud-config básico
cat > cloud-config.yaml << 'EOF'
#cloud-config
users:
  - name: rapha
    groups: sudo
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh_authorized_keys:
      - ssh-ed25519 AAAA... sua_chave_aqui
EOF

# Gerar disco de cloud-init
cloud-localds cloud-init.iso cloud-config.yaml

# Criar VM com a imagem cloud
virt-install \
  --name debian-cloud \
  --memory 2048 \
  --vcpus 2 \
  --disk debian-12-genericcloud-amd64.qcow2,format=qcow2 \
  --disk cloud-init.iso,device=cdrom \
  --os-variant debian12 \
  --network network=default \
  --import \
  --noautoconsole

Gerenciando com virsh

O virsh é a CLI do libvirt. Depois que você pega o jeito, é mais rápido que qualquer interface gráfica.

# Listar VMs
virsh list --all          # todas (inclusive desligadas)
virsh list                # só as que estão rodando

# Controle básico
virsh start debian-12-teste
virsh shutdown debian-12-teste    # shutdown gracioso (pede pra SO desligar)
virsh destroy debian-12-teste     # força desligamento (como tirar da tomada)
virsh reboot debian-12-teste

# Suspender e retomar (salva estado em memória — rápido)
virsh suspend debian-12-teste
virsh resume debian-12-teste

# Informações
virsh dominfo debian-12-teste     # info geral
virsh domifaddr debian-12-teste   # IPs da VM (precisa do guest agent)
virsh vcpuinfo debian-12-teste    # info de CPU

Conectar no console

# Console serial (funciona sem rede)
virsh console debian-12-teste
# Ctrl+] pra sair

# VNC (interface gráfica da VM)
virt-viewer debian-12-teste

Gerenciar discos e snapshots

# Snapshot (salva o estado atual — útil antes de atualizações arriscadas)
virsh snapshot-create-as debian-12-teste snap-antes-atualizacao \
  --description "Estado antes da atualização do kernel"

# Listar snapshots
virsh snapshot-list debian-12-teste

# Restaurar snapshot
virsh snapshot-revert debian-12-teste snap-antes-atualizacao

# Ver informações do disco
qemu-img info /var/lib/libvirt/images/debian-12-teste.qcow2

# Expandir disco de uma VM existente
virsh blockresize debian-12-teste \
  /var/lib/libvirt/images/debian-12-teste.qcow2 30G
# Depois precisa expandir a partição DENTRO da VM também (growpart, resize2fs)

Configuração em XML

O libvirt descreve cada VM em XML. Parece burocrático mas é poderoso: dá pra versionar, copiar, modificar:

# Ver a configuração atual
virsh dumpxml debian-12-teste

# Editar (abre no $EDITOR)
virsh edit debian-12-teste

# Exportar para arquivo
virsh dumpxml debian-12-teste > debian-12-backup.xml

# Importar/recriar uma VM a partir do XML
virsh define debian-12-backup.xml

💡 Guardar o XML de VMs importantes é uma forma simples de backup da configuração. O disco você faz backup separado; o XML garante que você consegue recriar a VM com as mesmas configs se precisar.

Migração entre hosts

Uma das grandes vantagens do KVM/libvirt é migração de VMs entre hosts. Com storage compartilhado (NFS, Ceph), dá pra fazer migração ao vivo sem desligar:

# Migração simples (VM desligada, sem storage compartilhado)
virsh migrate --offline debian-12-teste \
  qemu+ssh://192.168.1.20/system \
  --copy-storage-all

# Migração ao vivo (VM continua rodando)
virsh migrate --live debian-12-teste \
  qemu+ssh://192.168.1.20/system
# Funciona bem com storage compartilhado (NFS/Ceph) —
# sem storage compartilhado, vai ser lento e pode falhar em VMs com muita escrita de disco

⚠️ Migração ao vivo sem storage compartilhado é possível com --copy-storage-all, mas é lenta e arriscada em VMs com disco ativo. Em homelab, o mais prático é migração offline + copiar o disco depois.

QEMU puro: quando usar sem KVM

Tem casos em que você quer QEMU sem KVM, principalmente quando precisa emular uma arquitetura diferente. KVM só acelera quando a arquitetura da VM é a mesma do host. Pra cruzamento de arquiteturas, QEMU puro é o caminho:

# Emular um sistema ARM64 num host x86_64
qemu-system-aarch64 \
  -machine virt \
  -cpu cortex-a72 \
  -m 1024 \
  -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
  -drive file=imagem-arm64.qcow2,if=virtio \
  -netdev user,id=net0 \
  -device virtio-net-device,netdev=net0 \
  -nographic

# Emular RISC-V (pra compilar/testar software RISC-V)
qemu-system-riscv64 \
  -machine virt \
  -cpu rv64 \
  -m 1024 \
  -drive file=imagem-riscv64.qcow2,if=virtio \
  -nographic

Casos reais de uso:

  • Compilar software pra Raspberry Pi sem ter um Pi na mão
  • Testar firmware de roteadores (geralmente MIPS)
  • Desenvolvimento de sistemas embarcados (ARM Cortex-M)
  • CI/CD multiplataforma: testar binários em arquiteturas diferentes antes de deployar em hardware real

O trade-off é performance: emulação pura é de 10x a 50x mais lenta que execução nativa. Pra compilação e testes funcionais tudo bem. Pra rodar servidor de produção em arquitetura errada, esquece.

Redes no KVM/libvirt

O libvirt cria uma rede NAT padrão (default, geralmente 192.168.122.0/24) na instalação. Ela funciona pra maioria dos casos de desenvolvimento, mas pra homelab você provavelmente quer as VMs na mesma rede que o host:

# Ver redes disponíveis
virsh net-list --all

# Criar bridge no host (Debian/Ubuntu — editar /etc/network/interfaces)
# ou via nmcli (NetworkManager):
nmcli connection add type bridge ifname br0 con-name br0
nmcli connection add type ethernet ifname eth0 master br0
nmcli connection up br0

# Criar rede bridge no libvirt
cat > rede-bridge.xml << 'EOF'
<network>
  <name>bridge-rede</name>
  <forward mode="bridge"/>
  <bridge name="br0"/>
</network>
EOF

virsh net-define rede-bridge.xml
virsh net-start bridge-rede
virsh net-autostart bridge-rede

Com a bridge configurada, novas VMs podem usar --network network=bridge-rede e aparecer na rede local com IP próprio, sem NAT, sem port forwarding.

O que vem depois

KVM + libvirt são a fundação. A maioria das plataformas de virtualização que você vai encontrar no mundo real está construída em cima disso:

  • Proxmox VE = KVM + QEMU + libvirt (modificado) + interface web
  • oVirt/RHEV = KVM + libvirt + orquestração enterprise
  • OpenStack (componente Nova) = KVM + libvirt + orquestração em nuvem

Entender o que está acontecendo aqui embaixo faz com que qualquer coisa acima seja muito mais fácil de debugar. Quando uma VM no Proxmox não sobe, você sabe que o erro está em algum lugar entre o XML do libvirt e o QEMU. Quando a rede da VM não funciona, você sabe procurar na bridge do host antes de olhar pra qualquer interface web.

Conclusão

KVM não é uma ferramenta separada que você instala; é algo que já veio com seu sistema operacional. QEMU dá corpo a isso, e libvirt torna gerenciável. Três camadas, cada uma com uma responsabilidade clara.

A maioria das pessoas pula direto pra Proxmox ou VMware sem enteder o que tá embaixo. Não tem nada errado nisso pra uso no dia a dia. Mas quando algo quebra, e vai quebrar, saber que virsh dumpxml mostra a configuração exata da VM, que /var/log/libvirt/qemu/ tem os logs de erro, e que qemu-img check inspeciona integridade de disco faz uma diferença enorme.

Definitvamente vale o tempo de aprender. O Proxmox agradece.