Implementazione di un server di virtualizzazione con KVM

6

kvm

Nel precedente articolo “Introduzione alla virtualizzazione con KVM” sono stati introdotti gli aspetti base della virtualizzazione basata su KVM.
In questo articolo vedremo come implementare una completa soluzione di Virtualizzazione basata su KVM e Debian.

In particolare useremo Debian Squeeze, l’attuale release stable di Debian.

Prerequisiti

Per utilizzare KVM è necessario avere un processore dotato di estensioni per la virtualizzazione, per verificare che siano presenti è sufficiente lanciare il seguente comando:

# egrep -c '(vmx|svm)' /proc/cpuinfo
8

Se il comando (come nell’esempio) restituisce “1” o un numero maggiore le estensioni sono state rilevate, mentre se restituisce 0, significa che il vostro processore non dispone di tali estensioni, quindi dovrete usare una soluzione differente come ad esempio Xen o VirtualBox.

Nel caso in cui vogliate creare VirtualMachine con un quantitativo di RAM superiore ai 2 GB è necessario avere un processore con architettura X86-64. Anche in questo caso possiamo estrarre questa informazione dal file /proc/cpuinfo:

# egrep -c ' lm ' /proc/cpuinfo
8

Anche in questo caso, se il comando (come nell’esempio) restituisce un numero diverso da 0, il vostro processore potrà eseguire software a 64 bit.

L’ulteriore componente in gioco è il kernel del vostro sistema, che deve essere compilato con il supporto ai 64 bit, per controllare è sufficiente lanciare ‘uname’:

# uname -m
x86_64

che dovrà restituire appunto “x86_64”.
Nel caso il vostro processore sia a 64 bit ma sistema operativo installato a 32, non preoccupatevi, non è necessario effettuare una nuova installazione. Linux infatti è in grado di far girare uno userland a 32 bit su un kernel a 64 bit e nei repository Debian per l’architettura i386 è presente proprio il pacchetto che ci interessa, installabile con un colpo di Apt:

# apt-get install linux-image-2.6-amd64

Al contrario delle estensioni per la virtualizzazione, non avere un processore x86_64 non pregiudica la funzionalità di KVM, semplicemente si potranno creare macchine virtuali con al massimo 2 Gb di RAM, quantitativo più che sufficiente per macchine virtuali di test.

Come ultimo prerequisito è necessario procurarsi un client VNC da installare sulla propria workstation, in questo caso si può proprio dire che uno vale l’altro, l’uso che se ne farà è davvero semplice e non richiede alcuna caratteristica avanzata.

Installazione e configurazione

Il processo di installazione è davvero molto semplice:

# apt-get install qemu-kvm libvirt-bin

APT scaricherà tutti i pacchetti necessari per preparare il vostro sistema alla virtualizzazione.

È possibile fare in modo che un utente non privilegiato possa creare e gestire le VM semplicemente aggiungendo l’utente al gruppo ‘libvirt’:

# adduser fpedrini libvirt

ed effettuare nuovamente la login al sistema per acquisire il nuovo gruppo.

Per verificare che tutto sia funzionante è necessario utilizzare il comando virsh, parte del pacchetto libvirt-bin:

# virsh --connect qemu:///system list

che mostrerà un output simile al seguente:

 Id Name                 State
----------------------------------

#

virsh è una shell interattiva che permette di gestire il proprio ambiente di virtualizzazione indipendentemente dall’Hypervisor (vedi precedente articolo) utilizzato, di cui comunque parleremo in maniera approfondita più avanti.

Come ultimo passo, per fare in modo che le virtual machine possano connettersi alla stessa rete presso cui il server è collegato, sarà necessario creare un bridge. Viceversa è possibile sfruttare le reti interne gestite da virsh via libvirt, ma questo tipo di configurazione non è trattata in questo articolo.
Per creare un bridge è necessario installare il pacchetto bridge-utils:

# apt-get install bridge-utils

E’ quindi sufficiente modificare la configurazione delle interfacce di rete in /etc/network/interfaces, creando una nuova stanza all’interno del file e fare in modo che l’interfaccia primaria diventi il bridge (per esempio br0):

auto br0
iface br0 inet static
        address 192.168.0.100
        network 192.168.0.0
        netmask 255.255.255.0
        broadcast 192.168.0.255
        gateway 192.168.0.1
        bridge_ports eth0
        bridge_fd 9
        bridge_hello 2
        bridge_maxage 12
        bridge_stp off

Oltre alle normali opzioni (address/network/broadcast/netmask e gateway) sono presenti anche le opzioni usate per la creazione del bridge, e la più importante è bridge_ports, che indica al sistema quale interfaccia fisica deve essere usata per la costruzione del bridge.

Riavviando il servizio di networking:

# /etc/init.d/networking restart

il bridge verrà attivato.

Creazione della prima Macchina Virtuale

Una volta installati i vari pacchetti necessari per la virtualizzazione e configurata la rete è possibile installare la prima virtual machine, sfruttando il comando virt-install.

Virt-install e’ un tool della suite di libvirt che permette di automatizzare i passaggi di base necessari alla creazione della VM, come ad esempio la creazione del file che fungerà da disco virtuale o la configurazione del file XML che contiene la definizione della Virtual Machine.

Se ad esempio volessimo installare una VM che faccia girare una nuova istanza di Debian Squeeze, il comando da lanciare sarà simile al seguente:

# virt-install --connect qemu:///system -n squeeze-vm -r 512 --vcpus=2 --disk path=/virtuals/squeeze-vm10.img,size=10 -c /dev/cdrom --vnc --noautoconsole --os-type linux --os-variant debiansqueeze --accelerate  --hvm --network=bridge:br0

Quello che all’inizio può sembrare un comando difficile e complesso, si rivela in realtà una lista di opzioni abbastanza facile da ricordare quando se ne conosce il significato:

  • –connect qemu:///system indica a virt-install quale deve essere l’hypervisor target
  • -n indica il nome della Virtual Machine, in questo caso squeeze-vm
  • -r indica il quantitativo della ram virtuale in megabytes
  • –vcpus=2 indica il quantitativo di cpu virtuali da assegnare alla VM. Test prestazionali indicano che su processori multicore come quelli odierni, assegnare più di due vcpu ad un sistema guest non porta ad alcun aumento di performance. Il numero di processori dedicati infatti serve semplicemente a far capire al sistema guest che sta girando in un ambiente SMP. Ci penserà l’hypervisor a dividere il carico sui core del sistema host
  • –disk-path=/virtuals/squeeze-vm,size=10 indica a virt-install dove creare l’immagine per il disco virtuale e la sua dimensione. Può anche essere usato un dispositivo a blocchi (come ad esempio /dev/sdb1, la prima partizione del secondo disco del sistema host o un volume LVM), in questo caso l’opzione size non avrà alcun effetto.
  • -c /dev/cdrom indica a virt-install il path dell’immagine di installazione del sistema guest. È possibile utilizzare anche un normale file .iso
  • –vnc indica a virt-install di abilitare la console VNC non appena la macchina virtuale è stata creata.
  • –os-type linux –os-variant debiansqueeze indicano a virt-install che tipo di sistema operativo verrà installato sul guest
  • –accelerate –hvm indica a virt-install che il guest dovrà sfruttare l’accelerazione fornita da KVM. Ricordiamo che in realtà Qemu e KVM sono legati a doppio filo e il secondo può essere visto come un acceleratore per Qemu. inoltre la seconda opzione specifica che il guest dovrà essere un sistema completamente virtualizzato (e non paravirtualizzato come succederebbe con Xen)
  • –network=bridge:br0 indica a virt-install quale sarà il bridge da usare per connettere questa virtual machine alla rete

Una volta premuto invio, l’output si presenterà in maniera simile alla seguente:

Starting install...
Creating domain...                                                                                                                                                      |    0 B     00:00     
Domain installation still in progress. Waiting for installation to complete.

a questo punto collegandosi mediante un client VNC (ad esempio vncviewer) al server è possibile completare l’installazione via console, come se si trattasse di una normale installazione Debian.

Dal momento che VNC non è un protocollo cifrato, è preferibile utilizzare un tunnel SSH (come spiegato in questo articolo) dalla propria workstation al server di virtualizzazione, puntando quindi il proprio client VNC alla porta aperta dal tunnel su localhost.

Gestione delle Virtual Machine

Gestire le virtual machine è possibile sempre mediante la comoda shell interattiva virsh di cui è stato fatto cenno poco sopra.

Virsh è il tool principe per la gestione delle macchine virtuali in quanto permette di eseguire con semplicità anche i compiti più complessi tramite una comoda interfaccia testuale.

Per lanciare virsh sarà necessario lanciare il comando:

# virsh --connect qemu:///system

Si presenterà quindi una vera e propria shell interattiva:

Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh #

Per ottenere la lista dei comandi disponibili è sufficiente scrivere help:

virsh # help
Commands:

    help            print help
    attach-device   attach device from an XML file
    attach-disk     attach disk device
    attach-interface attach network interface
    autostart       autostart a domain
    capabilities    capabilities
    cd              change the current directory
    connect         (re)connect to hypervisor
    ....
    version         show version
    vncdisplay      vnc display
    snapshot-create Create a snapshot
    snapshot-current Get the current snapshot
    snapshot-delete Delete a domain snapshot
    snapshot-dumpxml Dump XML for a domain snapshot
    snapshot-list   List snapshots for a domain
    snapshot-revert Revert a domain to a snapshot

I comandi disponibili per virsh sono moltissimi e permettono di gestire qualsiasi aspetto di una macchina virtuale, dal suo stato, alla gestione dei dischi virtuali, fino alla gestione delle reti interne.

I comandi sicuramente più utilizzati sono quelli relativi all’esecuzione di un guest, cioè list,start, shutdown e reboot, destroy, suspend e resume.

Tutti questi comandi risultano abbastanza autoesplicativi e, ad eccezione di list tutti necessitano del nome del sistema guest su cui dovranno agire. Il comando list invece accetta due parametri: –all e –inactive, che agiranno come filtri per visualizzare rispettivamente tutte le virtual machine o i soli guest inattivi, se invocato senza alcun parametro, verrà visualizzato l’elenco delle macchine virtuali avviate.

Come detto sopra, i comandi risultano abbastanza chiari, ma è bene fare attenzione ad un paio di dettagli, vediamo con ordine:

  • start è sicuramente il più semplice, permette di avviare la virtual machine. In aggiunta, è utile citare il comando autostart che permette di comunicare a libvirt di avviare automaticamente le virtual machine all’avvio del sistema.
  • shutdown permette di inviare al sistema guest un segnale di shutdown, simulando ciò che accade sulle macchine fisiche quando viene premuto il tasto di accensione
  • reboot invia alla macchina virtuale il segnale di reboot che avvierà un processo di riavvio pulito del sistema.
  • destroy fa in modo che il processo della virtual machine venga ucciso. Dal punto di vista della virtual machine questo è l’equivalente di un blackout, la corrente viene interrotta bruscamente. Ovviamente come succede per le macchine reali, questo comando potrebbe creare inconsistenze sul filesystem del guest anche se ovviamente non causerà alcun danno reale all’hardware
  • suspend fa in modo che l’esecuzione della virtual machine venga interrotta. La ram rimarrà comunque occupata, ma la macchina virtuale non occuperà più alcuna risorsa relativa a CPU, HD e rete fino al resume.
  • resume permette di far uscire la virtual machine dallo stato di ibernazione attivato con suspend

Menzione particolare meritano anche i comandi save e restore.
Save richiede, oltre al nome della virtual machine anche un parametro aggiuntivo, cioè il filename dove salvare lo stato del sistema guest. Al contrario di suspend, questo comando permette di salvare tutto ciò che concerne la virtual machine (ram, registri del processore, interrupts, eccetera, eccetera…) in un file, e terminare il processo del sistema guest. Questo fa si che una Virtual Machine possa essere spostata completamente da un host all’altro senza che il sistema e le applicazioni al suo interno ne risentano minimamente.
Restore, come la sua controparte richiede come parametro aggiuntivo il file da cui leggere lo stato della virtual machine da ripristinare.

Conclusioni

Questo articolo, per quanto lungo, rimane sempre e comunque una rapida introduzione al vasto argomento della virtualizzazione, tematica che grazie ai recenti miglioramenti di libvirt e dei tool a corredo sta diventando sempre più vasta e interessante.

Ciò nonostante credo che usando come base le informazioni qui contenute si possano creare ambienti di virtualizzazione in grado di competere (e in parecchi casi persino surclassare) le soluzioni di virtualizzazione proprietarie più blasonate.

Basti pensare che i grandi player del mondo della virtualizzazione (Amazon, RackSpace e Google, giusto per citare i più grandi) utilizzano soluzioni basate proprio sui software descritti in questo articolo.

6 risposte a “Implementazione di un server di virtualizzazione con KVM”

  1. Avatar Cicciolippo
    Cicciolippo

    manca l’installazione di virtinst…

  2. Avatar Raoul Scarazzini

    Giustissimo.

    # apt-get install virtinst
    

    Senza questo pacchetto il comando virt-install non sarà disponibile.

  3. Avatar Cicciolippo
    Cicciolippo

    Come faccio a tirar su la macchiona virtuale una volta finita l’installazione?
    E se voglio raggiungere un servizio, diciamo apache, sulla porta 80 della macchian virtuale come si fa?

  4. Avatar Raoul Scarazzini

    E’ tutto spiegato nell’articolo: mediante l’utilizzo del comando virsh con l’opzione start avvii la macchina. Ad esempio, per avviare la macchina creata nell’articolo:

    # virsh start squeeze-vm
    

    Per quanto riguarda i servizi come Apache, essendo la macchina attestata sulla medesima rete del server reale, e possedendo quindi un IP relativo, sarà sufficiente installare il servizio apache e questo sarà raggiungibile dalla rete.

  5. Avatar Luca
    Luca

    Ciao,
    seguendo la tua guida, quando provo ad installare la macchina virtuale con “virt-install” e tutto il blablabla che segue mi da il seguente errore:

    “libvirtError: internal error Process exited while reading console log output: libvir: error : cannot open /sys/devices/system/cpu/cpu0/topology/physical_package_id: no such file or directory”

    In effetti, il percorso corrisponde sul mio OS fino a cpu0… la cartella topology non c’è proprio!!
    Qualche dritta?? Come posso risolvere??

  6. Avatar Francesco Pedrini

    Ciao Luca,

    perdonami ma questo commento mi e’ proprio sfuggito.

    Nel caso ne avessi ancora bisogno, pare ci sia un bug in libvirt, tracciato per Debian qui: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=579801

    Non e’ ancora presente una patch ufficiale ma la soluzione proposta e’ quella di usare un kernel -686 invece che un kernel -486 (che comunque non e’ consigliato con i processori moderni).

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *