KVM: Adding paravirtualized device on linux guest

Negli ultimi mesi il team di sviluppo di KVM ha lavorato per rendere disponibile driver paravirtualizzati per i guest virtualizzati, lo scopo è quello di eliminare l’ultimo layer di emulazione presente nella versione customizzata di qemu (principalmente disco e scheda di rete).

L’API scelta per supportare la virtualizzazione dell’IO è stata virtio, l’idea che sta dietro virtio è quella di avere un framework comune per diversi hypervisor per virtualizzare l’IO. Un interessante articolo di approfondimento su questo argomento si può leggere a questo indirizzo.

In questo post vedremo come configurare l’interfaccia di rete ed il controller dei dischi per utilizzare i driver paravirtualizzati per un guest linux-based, nei prossimi giorni con un post gemello vedremo come configurare i device paravirtualizzati in Microsoft Windows.

NOTA: se siete interessati ad un breve approfondimento su come è possibile installare i driver paravirtualizati per la rete all’interno di un guest Windows based potreste trovare interessante questo post.

Prerequisiti

Per poter utilizzare i driver paravirtualizzati è necessario avere una versione di KVM installata sull’host dalla 60 in poi ed avere sul guest una versione del kernel di linux dalla 2.6.25 in poi. Verificato di avere una versione del kernel compatibile è necessario assicurarsi che il kernel della distribuzione utilizzata sul guest sia stata compilata con i seguenti flag abilitati:

  • CONFIG_VIRTIO_PCI=y (Virtualization -> PCI driver for virtio devices)
  • CONFIG_VIRTIO_BALLOON=y (Virtualization -> Virtio balloon driver)
  • CONFIG_VIRTIO_BLK=y (Device Drivers -> Block -> Virtio block driver)
  • CONFIG_VIRTIO_NET=y (Device Drivers -> Network device support -> Virtio network driver)
  • CONFIG_VIRTIO=y (automatically selected)
  • CONFIG_VIRTIO_RING=y (automatically selected)

Notare che con y si ottengono i moduli compilati direttamente nel kernel di linux, nel caso in cui si scelga di optare per compilarli come moduli (m al posto di y) la cosa non crea generalmente problemi basta ricordarsi di di includerli nell’initrd.

E se la distribuzione che intendete utilizzare non ha un kernel uguale o superiore al 2.6.25? Sperate che il maintainer abbia compilato il kernel con la backward compatibility altrimenti vi toccherà a voi ricompilarvelo.

Ecco un esempio concreto di come sono settati i precedenti flag sulla distribuzione che andremo ad utilizzare, una Debian Lenny:

paolo@lennybox:~$ grep VIRTIO /boot/config-2.6.26-1-686
CONFIG_NET_9P_VIRTIO=m
CONFIG_VIRTIO_BLK=m
CONFIG_VIRTIO_NET=m
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_VIRTIO=y
CONFIG_VIRTIO_RING=y
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_BALLOON=m

Un’esempio concreto con Debian Lenny

Al momento in cui ho scritto questo post Debian Lenny include/includeva il kernel 2.6.26 quindi non è stato necessario effettuare paciocchi strani con kernel ricompilati, pacchetti presi dai repository unstable o simili.

Prima di iniziare una precisazione: la macchina virtuale utilizzata utilizzava l’emulazione ide, quindi il disco, l’unico disco presente, era /dev/hda. Nel caso in cui utilizziate l’emulazione scsi o in cui abbiate più dischi ricordatevi di questa piccola differenza quando leggete quanto segue.

Come abbiamo visto nel paragrafo riguardante i prerequisiti i moduli di nostro interesse non sono compilati built-in ma stand-alone, è quindi necessario andarli ad aggiungere all’initrd affinchè il tutto venga riconosciuto correttamente. Con Debian è sufficiente:

  • editare /etc/initramfs-tools/modules aggiungendo virtio, virtio_pci, virtio_ring, virtio_net, virtio_blk, aggiornare l’initrd digitando update-initramfs -u, ad esempio nella macchina di prova:
lennybox:~# cat /etc/initramfs-tools/modules
virtio
virtio_pci
virtio_ring
virtio_net
virtio_blk
lennybox:~# update-initramfs -u
  • editare /boot/grub/menu.lst modificando il valore di root in kopt in modo che /dev/[sh]d[a-z][1-9] diventi /dev/vd[a-z][1-9], aggiornare la configurazione di grub digitando update-grub, ad esempio nella macchina di prova:
lennybox:~# cat /boot/grub/menu.lst|grep kopt
# kopt=root=/dev/vda1 ro quiet
lennybox:~# update-grub
  • editare /etc/fstab in modo che le varie partizioni /dev/[sh]d[a-z][1-9] puntino alle nuove /dev/vd[a-z][1-9], ad esempio sulla macchina di prova:
lennybox:~# cat /etc/fstab
 ...
 /dev/vda1       /           ext3   defaults,errors=remount-ro 0       1
 /dev/vda2       none        swap   sw                         0       0
 ...
  • editare /boot/grub/device.map in modo che in disco da cui bootare diventi /dev/vd[a-z] anzichè /dev/[sh]d[a-z], ad esempio nella macchina virtuale di prova:
lennybox:~# cat /boot/grub/device.map
 (hd0)    /dev/vda

Una volta fatto quanto precedentemente detto riavviare la macchina virtuale impostando il modello della scheda di rete a virtio (model=virtio) ed il tipo di interfaccia del disco a virtio (if=virtio), di seguito un esempio concreto di come è stata avviata la macchina di prova:

sudo qemu-system-x86_64 -drive file=./lennybox.img,if=virtio,boot=on -net nic,model=virtio -net tap -k it -localtime -smp 2 -m 512

Dal guest verranno visti i seguenti nuovi device:

paolo@lennybox:~$ lspci -nn
...
00:03.0 Ethernet controller [0200]: Qumranet, Inc. Device [1af4:1000]
00:04.0 Mass storage controller [0180]: Qumranet, Inc. Device [1af4:1001]
00:05.0 RAM memory [0500]: Qumranet, Inc. Device [1af4:1002]

Il gioco è fatto!!! Gustatevi il nuovo boost prestazionale!!!

Related post:

Comments are closed.