1,837 25/03/2026 07/04/2026 9 min

In KVM/libvirt la rete è spesso il primo punto in cui un host “sembra” sano ma il guest no. Il caso tipico non è l’installazione base. È la VM che risponde, ma ha jitter, throughput basso o pause brevi dopo uno snapshot o una live migration.

Qui confronto due approcci reali: bridge sulla LAN e NAT con rete privata libvirt. Non sono equivalenti. Servono a problemi diversi, con effetti diversi su latenza, troubleshooting e manutenzione.

Scenario concreto: un guest Debian 12 con virtio-net, disco qcow2, snapshot prima di un deploy e poi una live migration verso un altro nodo. Dopo il passaggio, il sito dentro la VM resta online ma il backend mostra tempi di risposta più alti. Il nodo host non è saturo. Il collo di bottiglia è altrove.

Prerequisiti

Prima di toccare bridge o NAT, conviene avere chiari questi punti.

  • Host KVM con libvirt attivo e accesso shell root o sudo.
  • Guest con driver virtio per rete e disco.
  • Almeno due schemi di rete già disponibili o configurabili.
  • Accesso a virsh, ip, ethtool e qemu-img.
  • Un caso d’uso preciso: VM esposta in LAN oppure VM isolata per test o staging.

Note: se il guest deve ricevere traffico diretto da altre macchine della rete, il bridge è quasi sempre la prima opzione da valutare. Se invece vuoi isolamento forte e routing semplice, NAT resta più pulito.

Warning: non cambiare schema di rete e storage nello stesso intervento. Se il guest peggiora, non saprai se la causa è il bridge, il disco o il live migration path.

Step numerati

1) Decidi se il problema è visibilità di rete o isolamento

Questo step evita il classico errore: usare il bridge solo perché “sembra più performante”. Il bridge serve quando la VM deve stare nella stessa LAN del resto dell’infrastruttura. NAT serve quando vuoi controllo e prevedibilità.

Con bridge, il guest prende un IP della rete fisica o comunque è direttamente raggiungibile. Con NAT, il guest esce tramite l’host e non espone direttamente la sua interfaccia al segmento LAN.

Bridge: meglio per server esposti, clustering, monitoring esterno e servizi che devono annunciare il proprio IP reale.
NAT: meglio per ambienti isolati, test, laboratori e guest che non devono essere raggiungibili dall’esterno.

Controllo rapido delle reti libvirt già presenti:

virsh net-list --all

# Output:

 Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes
 lan-br    inactive no          yes

Qui il punto non è il nome. È capire se stai usando la rete default di libvirt, spesso NAT, oppure una rete bridge già predisposta.

2) Verifica il tipo di bridge o la NAT chain prima di cambiare la VM

Se il guest è lento dopo snapshot, spesso si cerca subito nel disco. Ma la rete può essere il vero limite, soprattutto se il traffico attraversa un bridge software mal configurato o una catena NAT congestionata.

Per un bridge reale, controlla il device host e le porte collegate:

ip link show type bridge
bridge link

# Output:

3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP mode DEFAULT group default qlen 1000

4: vnet0: master br0 state forwarding priority 32 cost 100

Per NAT, verifica che il forwarding sia coerente e che la rete libvirt non sia stata sovraccaricata da regole extra:

iptables -t nat -S | grep -E 'LIBVIRT|MASQUERADE'
# oppure, se usi nftables:
nft list ruleset | grep -n libvirt

# Output:

-A POSTROUTING -s 192.168.122.0/24 -j MASQUERADE

Note: il bridge non accelera automaticamente tutto. Se il NIC host ha offload disabilitati o il path verso lo switch è limitato, il vantaggio può sparire.

3) Confronta il comportamento della VM con virtio e con e1000

La scelta del modello di scheda rete conta più di quanto si dica nei tutorial rapidi. Con bridge o NAT, un guest con e1000 può sembrare stabile ma consumare più CPU. virtio-net riduce overhead e migliora il throughput.

Controlla la configurazione del dominio:

virsh dumpxml vm-prod | sed -n '/<interface/,/<\/interface>/p'

# Output:

<interface type='bridge'>
  <source bridge='br0'/>
  <model type='virtio'/>
</interface>

Se trovi e1000, valuta subito il cambio. È spesso la causa nascosta del “guest lento” quando il carico di rete sale.

Per misurare in modo semplice, confronta il traffico con iperf3 dentro il guest e sull’host:

iperf3 -s
iperf3 -c 192.168.1.50 -P 4 -t 20

# Output:

[SUM]   0.00-20.00  sec  9.62 GBytes  4.13 Gbits/sec

Se il throughput crolla dopo snapshot o migrazione, il problema può essere il path di rete, non il driver in sé.

4) Se scegli bridge, configura il caso d’uso reale e non solo il file XML

Il bridge è la scelta giusta se la VM deve vivere come un nodo della LAN. Questo vale per reverse proxy, database replicati, sistemi di monitoring o nodi che ricevono connessioni dirette.

Su host Linux con NetworkManager o systemd-networkd, il bridge va definito coerentemente. Esempio minimale con libvirt e bridge già esistente:

virsh attach-interface --domain vm-prod --type bridge --source br0 --model virtio --config --live

# Output:

Interface attached successfully

Qui il vantaggio è la semplicità operativa: il guest è direttamente visibile in rete, i log e il monitoring lo raggiungono senza NAT, e il troubleshooting è più lineare.

Warning: il bridge richiede attenzione su STP, VLAN tagging e promisc mode del NIC host. Se il traffico sparisce dopo una migrazione, controlla prima questi tre punti.

Verifica MTU e stato porte, perché dopo live migration un mismatch può creare micro-interruzioni:

ip link show br0
ip link show vnet0
ethtool eth0 | grep -E 'Speed|Duplex|Auto-negotiation'

# Output:

mtu 1500
Speed: 10000Mb/s
Duplex: Full

5) Se scegli NAT, usalo quando vuoi stabilità e meno esposizione

NAT è più adatto quando il guest non deve avere IP pubblico o IP di LAN. È utile per ambienti di test, automazione, build worker e host temporanei.

La rete default di libvirt è spesso pronta e meno fragile. Non devi coinvolgere switch, VLAN o policy di rete esterne. Questo riduce errori di configurazione dopo snapshot o restore.

virsh net-start default
virsh net-autostart default
virsh domifaddr vm-lab

# Output:

 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet1      52:54:00:ab:cd:ef    ipv4         192.168.122.101/24

Se il guest è lento in NAT, spesso il limite è la CPU host o il firewall del nodo, non la rete virtuale in sé. In laboratorio questo schema è più facile da replicare e da ripristinare.

Note: NAT è anche più tollerante ai cambi di host durante le live migration, perché non dipende dal dominio di broadcast della LAN fisica.

6) Gestisci snapshot qcow2 senza confondere rete e storage

Lo snapshot non dovrebbe cambiare la tua diagnosi di rete. Eppure spesso lo fa, perché il file qcow2 cresce, la chain si allunga e le I/O pause diventano visibili lato applicazione.

Controlla prima la catena del disco:

qemu-img info --backing-chain /var/lib/libvirt/images/vm-prod.qcow2

# Output:

image: vm-prod.qcow2
file format: qcow2
virtual size: 80 GiB

Se usi snapshot esterni, il guest può sembrare “lento in rete” perché i write burst rallentano il backend. Il sintomo tipico è un aumento del tempo di risposta HTTP, non un down totale.

Per un confronto pratico, misura la latenza di scrittura prima e dopo snapshot:

fio --name=randwrite --filename=/dev/vda --rw=randwrite --bs=4k --iodepth=16 --numjobs=1 --runtime=30 --time_based

# Output:

WRITE: bw=18.4MiB/s, iops=4710, lat=3.21ms

Se la latenza sale molto dopo snapshot, la rete è spesso innocente. Il problema è la combinazione tra qcow2, cache mode e storage sottostante.

7) Scegli il modello giusto in base al sintomo, non per preferenza

Questo è il confronto utile. Bridge e NAT non si scelgono per moda. Si scelgono in base al sintomo dominante.

  • Bridge se il guest deve essere un nodo reale della LAN, ricevere traffico diretto o partecipare a test di rete realistici.
  • NAT se vuoi isolamento, meno dipendenze dall’infrastruttura esterna e ripristino rapido dopo modifiche.
  • Bridge se hai bisogno di monitoraggio esterno con IP stabile e regole firewall semplici lato servizio.
  • NAT se il problema principale è evitare conflitti di IP, VLAN o policy di switch.

Se il guest è lento solo dopo snapshot, non partire dal bridge. Misura prima CPU steal, iowait e latenza disco. Poi guarda la rete.

virsh domstats vm-prod --cpu-total --balloon --block --interface

# Output:

block.rd.reqs=124
interface.rx.bytes=893421123
cpu.time=982341000000

Verifica finale

La verifica finale deve dirti se hai scelto bene il modello e se il collo di bottiglia è sparito.

  1. Controlla che il guest abbia l’interfaccia prevista, bridge o NAT, senza device duplicati.
  2. Verifica che il modello sia virtio e non una scheda legacy.
  3. Misura un transfer reale con iperf3 o curl verso un servizio interno.
  4. Confronta latenza applicativa prima e dopo snapshot o migration.
  5. Se usi bridge, verifica reachability da un host esterno alla macchina KVM.
  6. Se usi NAT, verifica DNS, default route e masquerade.

Un buon test pratico è questo: una richiesta HTTP al backend del guest e una misura ICMP o TCP dalla stessa subnet. Se la rete è sana ma l’app resta lenta, il problema è quasi certamente storage o CPU scheduling.

Note: dopo una live migration, controlla anche i contatori di drops sull’host e nel guest. Un bridge sano non dovrebbe mostrare errori ripetuti su RX/TX.

Troubleshooting

Errore 1: “Network is unreachable”

Causa: il guest ha perso la route predefinita dopo cambio di rete o migration.

Fix:

ip route
ip route replace default via 192.168.122.1 dev ens3

# Output:

default via 192.168.122.1 dev ens3

Errore 2: “Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied”

Causa: il tuo utente non ha accesso al socket di libvirt o il gruppo non è corretto.

Fix:

sudo usermod -aG libvirt $USER
newgrp libvirt

# Output:

uid=1000(user) gid=1000(user) groups=1000(user),108(libvirt)

Errore 3: “guest unexpectedly closed the connection”

Causa: il guest perde il path di rete o subisce un reset durante snapshot o migration, spesso per driver non ottimale o MTU incoerente.

Fix:

virsh domif-setlink vm-prod vnet0 up --config --live
ip link set dev br0 mtu 1500

# Output:

Link state updated successfully

Conclusione

Bridge e NAT non sono due modi per fare la stessa cosa. Il bridge è la scelta giusta quando la VM deve comportarsi come un nodo della rete reale. Il NAT è più adatto quando vuoi isolamento e meno variabili operative.

Se il guest resta lento dopo snapshot o live migration, non fermarti al primo sospetto. Misura rete, disco e driver in questo ordine. Il prossimo passo concreto è creare due profili di VM, uno bridge e uno NAT, e confrontarli con lo stesso workload per capire quale schema regge meglio il tuo scenario.