User Tools

Site Tools


doc:appunti:linux:sa:qemu_kvm

Virtualizzazione QEMU-KVM su Debian Stretch

Verificare con cat /proc/cpuinfo che il processore supporti la virtualizzazione: deve essere presente il flag vmx (per i processori Intel) oppure svm (per i processori AMD). Potrebbe essere necessario abilitarla da BIOS (identificata da qualcosa tipo “CPU protezione esecuzione” o “virtualizzazione”).

A differenza del passato (Debian Lenny) non è più necessario installare il pacchetto kvm-source e procedere alla compilazione dei moduli kernel aggiuntivi.

Pacchetti installati:

  • qemu-kvm, per la virtualizzazione completa su hardware x86.
  • libvirt-daemon e libvirt-daemon-system, demone per la gestione delle macchine virtuali e file di configurazione.
  • libvirt-clients, programmi per la gestione delle macchine virtuali, ad esempio virsh.
  • bridge-utils, tool per la configurazione di interfaccia di rete in modo “bridge”, necessario per avere guest e host sulla stessa rete.
  • virtinst, non è indispensabile (installa oltre 200 Mb di pacchetti). Fornisce tool di supporto per la creazione di macchine virtuali, cioè dei file di configurazione, ecc.
  • libosinfo-bin, tool di supporto per scoprire le --os-variant supportate da virt-install.

Configurazione rete in modalità bridge

È la configurazione necessaria per mettere la macchina host e guest sulla stessa rete locale. In pratica si configura una interfaccia br0 che avrà l'indirizzo IP della macchina host. Tale interfaccia sarà messa in bridge con la porta fisica eth0 e con la porta virtuale tap0, che a sua volta corrisponde all'interfaccia eth0 della macchina guest.

Vediamo come si configura il file /etc/network/interfaces di una macchina Debian.

iface eth0 inet manual

auto br0
iface br0 inet static
        address 10.0.0.55
        netmask 255.255.255.0
        gateway 10.0.0.189
        bridge_ports eth0
        bridge_stp off
        bridge_maxwait 0
        bridge_fd 0

In questo secondo esempio la scheda di rete eth2 della macchina host non è configurata (non ha indirizzo IP). Il device br2 viene quindi usato come bridge virtuale dalle macchine guest, che potranno raggiungere gli altri host fisicamente connessi a eth2:

auto eth2
iface eth2 inet manual
        up   /sbin/ifconfig eth2 up   || true
        down /sbin/ifconfig eth2 down || true

auto br2
iface br2 inet manual
        bridge_ports eth2
        bridge_stp off
        bridge_maxwait 10
        up   /sbin/ifconfig br2 up || true
        down /sbin/ifconfig br2 up || true

Potrebbe tornare utile un bridge senza alcuna scheda Ethernet connessa, ad esempio per attivare una interfaccia di rete in una macchina virtuale, ma senza dover occupare per forza una porta Ethernet. Ecco come attivare br10 senza impegnare porte fisiche:

auto br10
iface br10 inet manual
        bridge_ports none
        bridge_stp off
        bridge_waitport 0
        bridge_maxwait 10
        up   /sbin/ifconfig br10 up   || true
        down /sbin/ifconfig br10 down || true

Ecco la sintassi da riga di comando per fare configurazioni analoghe:

brctl addbr br2
brctl addif br2 eth2
ifconfig br2 up

ifconfig br2 down
brctl delif br2 eth2
brctl delbr br2

Creazione di una macchina virtuale

Si può procedere in modalità manuale oppure preparando dei file di configurazione XML e lasciare il lavoro di basso livello al framework libvirt.

Modo manuale con network in modo bridge

La configurazione con rete in modalità bridge è la più complessa, perché richiede che la macchina ospitante sia predisposta opportunamente. In breve la macchina ospitante dovrà avere l'interfaccia br0 invece di eth0. Nel file /etc/network/interfaces si imposta:

auto br0
iface br0 inet static
        address 10.0.1.2
        netmask 255.255.255.0
        gateway 10.0.1.252
        bridge_ports eth0
        bridge_stp off
        bridge_maxwait 10

quindi l'utente root predispone l'interfaccia tap0:

tunctl -t tap0 -u root
ifconfig tap0 up
brctl addif br0 tap0

A questo punto è possibile avviare la macchina ospite con qualcosa del tipo:

qemu-system-x86_64 -m 1024 -machine accel=kvm \
        -netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no \
        -device e1000,netdev=mynet0,mac=52:55:00:00:00:01 \
        -cdrom ../../iso/debian-10.0.0-amd64-netinst.iso \
        -hda rootfs.img -boot c

Con libvirt

Una macchina virtuale è definita da due file: il file di configurazione e il file immagine del disco. Ad esempio una macchina di nome stretch-amd64 è definita da:

  • /etc/libvirt/qemu/stretch-amd64.xml
  • /var/lib/libvirt/images/stretch-amd64.qcow2

È possibile creare in maniera assistita tali file eseguento il tool virt-install. Ad esempio:

virt-install \
    --virt-type kvm --name stretch-amd64 \
    --network bridge=br0 \
    --cdrom /home/kvm/iso/grml64-full_2017.05.iso \
    --graphics vnc,password=MySecret,listen=0.0.0.0, \
    -v --os-variant debian9 \
    --disk size=40 --memory 512

dove i parametri sono il nome del guest (es. stretch-amd64), una immagine ISO da cui fare bootstrap, una password per connettersi via VNC alla console, la dimensione del disco (es. 40 GB) e la memoria da allocare (512 Mb). Il parametro --os-variant determina alcune ottimizzazioni alla configurazione, usare osinfo-query os per sapere le varianti supportate.

virt-install crea i file necessari e avvia la macchina virtuale, la console è raggiungibile tramite VNC sulla porta 5900 della macchina host. Nel file di configurazione il boot da CD-ROM e l'immagine relativa non viene messa. Ecco cosa cambiare per ripristinarlo quando serve:

<!-- <boot dev='hd'/> -->
<boot dev='cdrom'/>
<!-- <driver name='qemu' type='raw'/> -->
<source file='/home/kvm/iso/grml64-full_2017.05.iso'/>

In alternativa a virt-install è possibile creare manualmente il file .xml di configurazione e creare l'immagine disco con il tool:

qemu-img create -f qcow2 stretch-amd64.qcow2 40G

Quando si cambiano i file di configurazione delle macchine guest è necessario riavviare il servizio (le macchine virtuali in esecuzione non sono toccate):

systemctl restart libvirtd.service

quindi da virsh è possibile distruggere e far ripartire una macchina virtuale, nonché abilitiare l'avvio atuomatico della stessa:

destroy stretch-amd64
start stretch-amd64
autostart stretch-amd64

L'avvio automatico è determinato semplicmente dall'esistenza di un link simbolico:

/etc/libvirt/qemu/autostart/stretch-amd64.xml -> /etc/libvirt/qemu/stretch-amd64.xml

Immagine disco raw o qcow2

L'immagine di un disco virtuale si crea con qemu-img. È possibile utilizzare il formato raw (predefinito, facilmente portabile su altri emulatori) oppure il formato qcow2 (predefinito di QEMU, più versatile per crittografia, compressione, ecc.) utilizzando l'opzione -f qcow2 di qemu-img.

Per scoprire il formato di un file immagine dovrebbe essere sufficiente il comando file, a prescindere dall'estensione:

file disk_hda.img
disk_hda.img: QEMU QCOW Image (v2), 10737418240 bytes

file disk_hdb.img
disk_hdb.img: DOS/MBR boot sector; ...

Il file XML di configurazione differisce nei due casi:

<disk type='file' device='disk'>
  <driver name='qemu' type='qcow2'/>
  <source file='/var/lib/libvirt/images/rootfs.qcow2'/>
  <target dev='hda'/>
</disk>
<disk type='file' device='disk'>
  <source file='/var/lib/libvirt/images/rootfs.img'/>
  <target dev='hdb'/>
</disk>

Scheda di rete Virtio o RTL-8029(AS)

La scelta predefinita per l'emulazione di una scheda Ethernet è il modello Virtio. Tale modello potrebbe non essere supportato ad esempio dalle versioni più vecchie dei sistemi operativi (Linux 2.6.18 non la supporta). In questi casi è possibile scegliere l'emulazione di una Realtek RTL-8029(AS) configurando opportunamente il file XML. Ecco i due esempi:

<interface type='bridge'>
  <model type='virtio'/>
  <mac address='52:54:00:00:01:04'/>
  <source bridge='br0'/>
  <target dev='tap103'/>
</interface>

Il tipo virtio offre alla macchina guest un device Ethernet PCI con ID 1af4:1000.

<interface type='bridge'>
  <model type='ne2k_pci'/>
  <mac address='52:54:00:00:01:04'/>
  <source bridge='br0'/>
  <target dev='tap103'/>
</interface>

Il tipo ne2k_pci offre alla macchina guest una Ethernet PCI compatibile NE2000, per la precisione una Realtek RTL-8029(AS). L'ID PCI in realtà è 1af4:1100, sempre afferente al vendor QEMU.

Per avere due o più schede Ethernet è sufficiente aggiungere altre sezioni <interface>. Ovviamente si impostano mac address e device tap diversi. Anche il bridge connesso è bene che sia diverso (per evitare i bridge loop), eventualmente usando un bridge fittizio, senza alcuna interfaccia Ethernet connessa (vedi sopra).

Console VNC

Nella sezione <devices> del file di configurazione:

<graphics type='vnc' port='5908' passwd='MySecret' keymap='it'>
  <listen type='address' address='181.121.173.202'/>
</graphics>

Nella configurazione si imposta la porta TCP in ascolto, la password e la mappatura della tastiera. Con address uguale a 0.0.0.0 si fa il bind su tutte le interfacce, non è possibile specificare due o più indirizzi di bind. Ovviamente se si imposta la password in chiaro, è opportuno proteggere il file almeno con mode 0640.

Troubleshooting

ERROR unsupported configuration: CPU mode 'custom' for x86_64 kvm
    domain on x86_64 host is not supported by hypervisor

Errore durante il tentativo di avviare una macchina virtuale, risolto facendo reboot. Forse servizio non avviato? Moduli kernel non caircati?

ERROR Requested operation is not valid: network 'default' is not active

Errore durante il tentativo di avviare una macchina virtuale in modalità network NAT (modalità predefinita). Non era stata avviata la configurazione di rete default di libvirt. Dalla shell virsh si deve eseguire net-start default.

Web References

doc/appunti/linux/sa/qemu_kvm.txt · Last modified: 2022/11/09 09:14 by niccolo