Product SiteDocumentation Site

12.2. Virtualizzazione

La virtualizzazione è uno dei più grandi progressi dell'informatica negli ultimi anni. Il termine copre diverse astrazioni e tecniche per simulare macchine virtuali con grado variabile di indipendenza dall'effettivo hardware. Un server fisico può quindi ospitare diversi sistemi contemporaneamente in funzione e isolati fra loro. Le applicazioni sono molte e spesso derivano da questo isolamento; per esempio ambienti di prova con configurazioni variabili, oppure separazioni di servizi ospitati per ragioni di sicurezza su differenti macchine virtuali.
Ci sono numerose soluzioni di virtualizzazione, ciascuna coi suoi pro e contro. Questo libro si concentrerà su Xen, LXC e KVM, ma fra le altre implementazioni degne di nota vi sono le seguenti:

12.2.1. Xen

Xen è una situazione di "paravirtualizzazione". Introduce un sottile strato di astrazione, chiamato "hypervisor", fra l'hardware e i sistemi superiori; ciò agisce come un arbitro che controlla l'accesso all'hardware dalle macchine virtuali. Tuttavia, questo gestisce solo alcune delle istruzioni, mentre il resto è eseguito direttamente dall'hardware per conto dei sistemi. Il vantaggio principale è che non c'è degrado di prestazioni e i sistemi girano a una velocità prossima a quella nativa; il difetto è che i kernel dei sistemi operativi che si vogliono usare su un hypervisor Xen devono essere adattati per girare su Xen.
Dedichiamo un po' di tempo alla terminologia. L'hypervisor è lo strato inferiore che gira direttamente sull'hardware, addirittura sotto il kernel. Esso può suddividere il resto del software su più domini, che possono essere visti come altrettante macchine virtuali. Uno di questi domini (il primo che viene avviato) è conosciuto come dom0 e ha un ruolo speciale, in quanto solo questo dominio può controllare l'hypervisor e l'esecuzione di altri domini. Questi ultimi ssono conosciuti come domU. In altre parole, e dal punto di vista dell'utente, il dom0 coincide con lo "host" di altri sistemi di virtualizzazione, mentre un domU può essere visto come un "guest".
L'uso di Xen sotto Debian richiede tre componenti:
  • L'hypervisor stesso. A seconda dell'hardware disponibile, il pacchetto appropriato che fornisce xen-hypervisor sarà xen-hypervisor-4.14-amd64, xen-hypervisor-4.14-armhf o xen-hypervisor-4.14-arm64.
  • Un kernel che gira su tale hypervisor. Qualsiasi kernel più recente del 3.0 lo farà, inclusa la versione 5.10 presente in Bullseye.
  • L'architettura i386 richiede inoltre una libreria standard con le patch appropriate che si appoggino a Xen; questa si trova nel pacchetto libc6-xen.
L'hypervisor installa anche xen-utils-4.14, che contiene gli strumenti per controllare l'hypervisor dal dom0. Questo, a sua volta, installa l'appropriata libreria standard. Durante l'installazione di tutto ciò, gli script di configurazione creano anche una nuova voce nel menu del bootloader GRUB, in modo da poter avviare il kernel scelto in un dom0 Xen. Da notare, tuttavia, che questa voce non è solitamente impostata come la prima della lista, ma sarà selezionata per impostazione predefinita.
Una volta soddisfatti i prerequisiti, il passo successivo è collaudare il comportamento del dom0 da solo; questo richiede un riavvio per entrare nell'hypervisor e nel kernel Xen. Il sistema dovrebbe avviarsi nel modo consueto, mostrando nella console alcuni messaggi in più durante le prime fasi di inizializzazione.
Ora è il momento di installare veramente dei sistemi utili sui sistemi domU, usando gli strumenti di xen-tools. Questo pacchetto fornisce il comando xen-create-image, che automatizza gran parte del compito. L'unico parametro obbligatorio è --hostname, che dà un nome al domU; altre opzioni sono importanti, ma possono essere memorizzate nel file di configurazione /etc/xen-tools/xen-tools.conf e la loro mancanza dalla riga di comando non genera un errore. Perciò è importante controllare i contenuti di questo file prima di creare delle immagini oppure, in alternativa, usare parametri aggiuntivi nell'esecuzione di xen-create-image. I parametri importanti includono:
  • --memory, per specificare la quantità di RAM dedicata al sistema appena creato;
  • --size e --swap, per definire la dimensione dei "dischi virtuali" disponibili al domU;
  • --debootstrap-cmd, per specificare il comando debootstrap usato. Il predefinito è debootstrap se sono installati debootstrap e cdebootstrap; in questo caso, verrà usata spesso anche l'opzione --dist (con il nome di una distribuzione come bullseye).
  • --dhcp dichiara che la configurazione di rete del domU deve essere ottenuta tramite DHCP mentre --ip permette di definire un indirizzo IP statico.
  • Da ultimo, bisogna scegliere un metodo di memorizzazione per le immagini da creare (quelle che saranno viste come dischi fissi dal domU). Il metodo più semplice, che corrisponde all'opzione --dir, è di creare un file sul dom0 per ogni dispositivo da rendere disponibile al domU. Per i sistemi che usano LVM, l'alternativa è usare l'opzione --lvm, seguita dal nome di un gruppo di volume; quindi xen-create-image creerà un nuovo volume logico dentro quel gruppo e questo volume logico sarà reso disponibile al domU come disco fisso.
Una volta effettuate queste scelte, si può creare l'immagine per il futuro domU Xen:
# xen-create-image --hostname testxen --dhcp --dir /srv/testxen --size=2G --dist=bullseye --role=udev

General Information
--------------------
Hostname       :  testxen
Distribution   :  bullseye
Mirror         :  http://deb.debian.org/debian
Partitions     :  swap            512M  (swap)
                  /               2G    (ext4)
Image type     :  sparse
Memory size    :  256M
Bootloader     :  pygrub

[...]
Logfile produced at:
	 /var/log/xen-tools/testxen.log

Installation Summary
---------------------
Hostname        :  testxen
Distribution    :  bullseye
MAC Address     :  00:16:3E:C2:07:EE
IP Address(es)  :  dynamic
SSH Fingerprint :  SHA256:K+0QjpGzZOacLZ3jX4gBwp0mCESt5ceN5HCJZSKWS1A (DSA)
SSH Fingerprint :  SHA256:9PnovvGRuTw6dUcEVzzPKTITO0+3Ki1Gs7wu4ke+4co (ECDSA)
SSH Fingerprint :  SHA256:X5z84raKBajUkWBQA6MVuanV1OcV2YIeD0NoCLLo90k (ED25519)
SSH Fingerprint :  SHA256:VXu6l4tsrCoRsXOqAwvgt57sMRj2qArEbOzHeydvV34 (RSA)
Root Password   :  FS7CUxsY3xkusv7EkbT9yae
Adesso è stata creata una macchina virtuale, ma attualmente non è in esecuzione (e quindi occupa solo spazio sul disco fisso del dom0). Ovviamente si possono creare altre immagini, magari con parametri diversi.
Prima di accendere queste macchine virtuali, bisogna definirne le modalità di accesso. Ovviamente possono essere considerate come macchine isolate, a cui si accederà soltanto tramite la loro console di sistema, ma raramente vengono usate in questo modo. Nella maggior parte dei casi, un domU sarà considerato come un server remoto e vi si accederà solo via rete. Tuttavia sarebbe molto scomodo aggiungere una scheda di rete per ogni domU; per questo Xen permette di creare interfacce virtuali, che ogni dominio può vedere e usare in modo standard. Notare che queste schede, seppur siano virtuali, saranno utili solo una volta connesse a una rete, anche solo virtuale. Per questo scopo, Xen ha diversi modelli di rete:
  • Il modello più semplice è il modello bridge; tutte le schede di rete eth0 (sia nel dom0 che nei sistemi domU) si comportano come se fossero direttamente inserite in uno switch Ethernet.
  • C'è poi il modello routing, dove il dom0 si comporta come un router che sta fra i sistemi domU e la rete esterna (fisica).
  • Infine, nel modello NAT, il dom0 è di nuovo fra i sistemi domU e il resto della rete, ma i sistemi domU non sono direttamente accessibili dall'esterno e il traffico passa attraverso alcune traduzioni degli indirizzi di rete sul dom0.
Queste tre modalità di rete comprendono alcune interfacce dai nomi insoliti, come vif*, veth*, peth* e xenbr0. L'hypervisor Xen le organizza in qualsiasi configurazione sia stata definita, sotto il controllo degli strumenti nello spazio utente. Poiché le modalità NAT e routing vengono utilizzate in casi particolari, ci occuperemo solo del modello di bridging.
La configurazione standard dei pacchetti Xen non cambia la configurazione di rete di sistema. Tuttavia, il demone xend è configurato per integrare le interfacce di rete virtuali in qualunque bridge di rete preesistente (con precedenza a xenbr0 se esiste più di un bridge). Bisogna quindi impostare un bridge in /etc/network/interfaces (il che richiede l'installazione del pacchetto bridge-utils, che è il motivo per cui xen-utils lo raccomanda) per sostituire la voce esistente relativa a eth0 (fare attenzione ad utilizzare il nome di dispositivo di rete corretto):
auto xenbr0
iface xenbr0 inet dhcp
    bridge_ports eth0
    bridge_maxwait 0
Dopo aver riavviato per assicurarsi che il bridge sia stato creato automaticamente, si può ora avviare il domU con gli strumenti di controllo di Xen, in particolare il comando xl. Questo comando permette diverse manipolazioni sui domini, fra cui elencarli, avviarli e fermarli. Si potrebbe dover incrementare la memoria predefinita mediante modifica della variabile memory nel file di configurazione (/etc/xen/testxen.cfg, in questo caso). Qui è stata impostata a 1024 (megabyte).
# xl list
Name                                        ID   Mem VCPUs	State	Time(s)
Domain-0                                     0  3918     2     r-----      35.1
# xl create /etc/xen/testxen.cfg
Parsing config from /etc/xen/testxen.cfg
# xl list
Name                                        ID   Mem VCPUs	State	Time(s)
Domain-0                                     0  2757     2     r-----      45.2
testxen                                      3  1024     1     r-----       1.3
Notare che il domU testxen usa memoria fisica presa dalla RAM che altrimenti sarebbe disponibile per il dom0, non memoria simulata. Pertanto bisogna fare attenzione, quando si assembla un server che deve ospitare istanze di Xen, a fornire RAM fisica secondo le necessità.
Voilà! La macchina virtuale è partita. Vi si può accedere in uno dei due modi. Il modo consueto è di connettersi ad essa "in remoto" tramite la rete, come ci si connetterebbe a una macchina reale; questo di solito richiederà di impostare un server DHCP o qualche configurazione di DNS. L'altro modo, che potrebbe essere l'unico se la configurazione di rete era errata, è di usare la console hvc0, con il comando xl console:
# xl console testxen
[...]

Debian GNU/Linux 11 testxen hvc0

testxen login: 
A questo punto si può aprire una sessione, proprio come si farebbe davanti alla tastiera della macchina virtuale. Lo scollegamento da questa console si ottiene con la combinazione di tasti Control+].
Una volta che il domU è attivo, può essere usato come qualunque altro server (visto che dopo tutto è un sistema GNU/Linux). Tuttavia, il suo stato di macchina virtuale permette di sfruttare alcune funzionalità aggiuntive. Ad esempio, un domU può essere temporaneamente messo in pausa e poi fatto uscire dalla pausa con i comandi xl pause e xl unpause. Notare che, sebbene un domU in pausa non usi affatto il processore, la memoria ad esso allocata è ancora in uso. Può essere interessante considerare i comandi xl save e xl restore: salvare un domU libera le risorse precedentemente usate da questo domU, compresa la RAM. Al ripristino (o all'uscita dalla pausa, se è per quello) un domU non si accorge di alcunché al di là del passare del tempo. Se un domU era in esecuzione quando il dom0 viene spento, gli script nel pacchetto salvano automaticamente il domU e lo ripristinano all'avvio successivo. Questo ovviamente comporterà i consueti inconvenienti che si riscontrano quando si iberna un computer portatile, per esempio; in particolare, se il domU viene sospeso per troppo tempo, le connessioni di rete possono scadere. Notare inoltre che a tutt'oggi Xen è incompatibile con gran parte della gestione energetica ACPI, il che impedisce di sospendere il sistema host (dom0).
Si può arrestare o riavviare un domU da dentro il domU (con il comando shutdown) o dal dom0, con xm shutdown o xl reboot.
La maggior parte dei sottocomandi di xl richiedono uno o più argomenti, spesso il nome di un domU. Questi argomenti sono ben descritti nella magina di manuale xl(1).

12.2.2. LXC

Anche se è usato per costruire "macchine virtuali", LXC non è, propriamente, un sistema di virtualizzazione, ma un sistema per isolare gruppi di processi l'uno dall'altro pur girando tutti sullo stesso host. Sfrutta alcune evoluzioni recenti nel kernel Linux, comunemente note come gruppi di controllo, con cui diversi insiemi di processi chiamati "gruppi" hanno visioni diverse di certi aspetti del sistema globale. Fra questi aspetti, i più importanti sono gli identificatori dei processi, la configurazione di rete e i punti di mount. Tale gruppo di processi isolati non avrà accesso agli altri processi nel sistema, ed i suoi accessi al file system possono essere ristretti a uno specifico sottoinsieme. Può anche avere la propria interfaccia di rete e la propria tabella di routing e può essere configurato per vedere solo un sottoinsieme dei dispositivi disponibili presenti sul sistema.
Queste funzionalità possono essere combinate per isolare un'intera famiglia di processi a partire dal processo init, e l'insieme che ne risulta è molto simile ad una macchina virtuale. Il nome ufficiale per una impostazione come questa è "contenitore" (da cui il nomignolo LXC: LinuX Containers), ma una differenza piuttosto importante rispetto alle "vere" macchine virtuali come quelle fornite da Xen o KVM è che non c'è un secondo kernel; il contenitore usa lo stesso kernel del sistema host. Questo ha sia dei pro che dei contro: fra i vantaggi ci sono prestazioni eccellenti data la totale assenza di carico aggiuntivo e il fatto che il kernel ha una visione globale di tutti i processi che girano sul sistema, quindi la schedulazione può essere più efficiente rispetto al caso in cui due kernel indipendenti dovessero schedulare diversi insiemi di attività. Il principale svantaggio è l'impossibilità di far girare un diverso kernel in un contenitore (sia una diversa versione di Linux sia un sistema operativo del tutto diverso).
Poiché si parla di isolamento e non di virtualizzazione vera e propria, impostare i contenitori LXC è più complesso che far girare debian-installer su una macchina virtuale. Verranno descritti alcuni prerequisiti, e poi si passerà alla configurazione di rete; a questo punto si potrà effettivamente creare il sistema da far girare nel contenitore.

12.2.2.1. Passi preliminari

Il pacchetto lxc contiene gli strumenti necessari per far girare LXC e quindi deve essere installato.
LXC richiede anche il sistema di configurazione dei gruppi di controllo, che è un file system virtuale da montare su /sys/fs/cgroup. Dal momento che Debian 8 è passata a systemd, che si basa anche su gruppi di controllo, questo ora è fatto automaticamente al boot senza ulteriori configurazioni.

12.2.2.2. Configurazione di rete

Lo scopo dell'installazione di LXC è di impostare delle macchine virtuali; pur potendo, ovviamente, tenerle isolate dalla rete e comunicare con loro solo tramite il file system, la maggior parte dei casi d'uso richiede di dare almeno un minimo accesso di rete ai contenitori. Nel caso tipico, ciascun contenitore avrà un'interfaccia di rete virtuale, connessa con la rete reale tramite un bridge. Questa interfaccia virtuale può essere inserita direttamente sull'interfaccia fisica di rete dell'host (nel qual caso il contenitore è direttamente in rete) o su un'altra interfaccia virtuale definita sull'host (e l'host può allora filtrare o ridirigere il traffico). In entrambi i casi, sarà necessario il pacchetto bridge-utils.
Nel caso più semplice richiede solo di modificare /etc/network/interfaces, spostando la configurazione dell'interfaccia fisica (per esempio eth0 o enp1s0) su un'interfaccia bridge (di solito br0) e configurare il collegamento fra di loro. Per esempio, se il file di configurazione dell'interfaccia di rete contiene inizialmente voci come le seguenti:
auto eth0
iface eth0 inet dhcp
Devono essere disabilitate e sostituite con le seguenti:
auto br0
iface br0 inet dhcp
    bridge-ports eth0
L'effetto di questa configurazione sarà simile a ciò che si otterrebbe se i contenitori fossero macchine collegate alla stessa rete fisica dell'host. La configurazione "bridge" gestisce il transito dei frame Ethernet fra tutte le interfacce in bridge, il che include la eth0 fisica oltre alle interfacce definite per i contenitori.
Nei casi in cui questa configurazione non si può usare (per esempio, se non si possono assegnare IP pubblici ai contenitori), un'interfaccia virtuale tap verrà creata e connessa al bridge. A quel punto la topologia di rete equivalente diventa quella di un host con una seconda scheda di rete inserita in uno switch separato, con i contenitori anch'essi inseriti in quello switch. L'host allora deve agire da gateway per i contenitori se questi devono comunicare con il mondo esterno.
Oltre a bridge-utils, questa configurazione "ricca" richiede il pacchetto vde2; il file /etc/network/interfaces allora diventa:
# l'interfaccia eth0 è invariata
auto eth0
iface eth0 inet dhcp

# interfaccia virtuale
auto tap0
iface tap0 inet manual
    vde2-switch -t tap0

# Bridge per i contenitori
auto br0
iface br0 inet static
    bridge-ports tap0
    address 10.0.0.1
    netmask 255.255.255.0
La rete allora può essere impostata staticamente nei contenitori o dinamicamente con un server DHCP che gira sull'host. Tale server DHCP dovrà essere configurato per rispondere alle richieste sull'interfaccia br0.

12.2.2.3. Impostazione del sistema

Ora si imposta il file system che il contenitore dovrà usare. Poiché questa "macchina virtuale" non girerà direttamente sull'hardware, servono alcuni accorgimenti rispetto a un file system standard, in particolare riguardo al kernel, i dispositivi e le console. Per fortuna, il pacchetto lxc include degli script che automatizzano gran parte di questa configurazione. Per esempio, i seguenti comandi (che richiedono i pacchetti debootstrap e rsync) installeranno un contenitore Debian:
# lxc-create -n testlxc -t debian
debootstrap is /usr/sbin/debootstrap
Checking cache download in /var/cache/lxc/debian/rootfs-stable-amd64 ... 
Downloading debian minimal ...
I: Retrieving Release 
I: Retrieving Release.gpg 
[...]
Download complete.
Copying rootfs to /var/lib/lxc/testlxc/rootfs...
[...]
# 
Notare che il file system è creato all'inizio in /var/cache/lxc e poi spostato nella sua directory di destinazione. Ciò permette di creare contenitori identici molto più rapidamente, visto che a questo punto basta copiarli.
Da notare che lo script per la creazione dei modelli Debian accetta l'opzione --arch per specificare l'architettura del sistema da installare ed un'opzione --release se si vuole installare qualcos'altro rispetto all'attuale versione stabile di Debian. È anche possibile impostare la variabile d'ambiente MIRROR per puntare ad un mirror locale di Debian.
Il pacchetto lxc crea inoltre un'interfaccia bridge lxcbr0, che viene usata, in modo predefinito, da tutti i nuovi contenitori creati tramite /etc/lxc/default.conf e il servizio lxc-net:
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
Queste voci vogliono dire, rispettivamente, che verrà creata un'interfaccia virtuale in ogni nuovo contenitore; che verrà automaticamente attivata quando il suddetto contenitore verrà avviato; e che verrà automaticamente connessa al bridge lxcbr0 sull'host. Queste impostazioni sono presenti nella configurazione del contenitore creato (/var/lib/lxc/testlxc/config), anche l'indirizzo MAC del dispositivo sarà contenuto in lxc.net.0.hwaddr. Se quest'ultima voce fosse assente o disabilitata, verrà generato un indirizzo MAC casuale.
Un'altra voce di utile in quel file è l'impostazione del nome host:
lxc.uts.name = testlxc
Il nuovo file system creato ora contiene un sistema Debian minimale e un'interfaccia di rete.

12.2.2.4. Avvio del contenitore

Ora che l'immagine della macchina virtuale è pronta, si avvia il contenitore con lxc-start --name=testlxc.
Nelle versioni di LXC successive alla 2.0.8 non vi è un'impostazione predefinita della password di root. Se si vuole è possibile impostarla eseguendo lxc-attach -n testlxc passwd. È possibile accedere con:
# lxc-console -n testlxc
Connected to tty 1
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

Debian GNU/Linux 11 testlxc tty1

testlxc login: root
Password: 
Linux testlxc 5.10.0-11-amd64 #1 SMP Debian 5.10.92-1 (2022-01-18) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Mar  9 01:45:21 UTC 2022 on console
root@testlxc:~# ps auxwf
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.2  18964 11464 ?        Ss   01:36   0:00 /sbin/init
root          45  0.0  0.2  31940 10396 ?        Ss   01:37   0:00 /lib/systemd/systemd-journald
root          71  0.0  0.1  99800  5724 ?        Ssl  01:37   0:00 /sbin/dhclient -4 -v -i -pf /run/dhclient.eth0.pid [..]
root          97  0.0  0.1  13276  6980 ?        Ss   01:37   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
root         160  0.0  0.0   6276  3928 pts/0    Ss   01:46   0:00 /bin/login -p --
root         169  0.0  0.0   7100  3824 pts/0    S    01:51   0:00  \_ -bash
root         172  0.0  0.0   9672  3348 pts/0    R+   01:51   0:00      \_ ps auxwf
root         164  0.0  0.0   5416  2128 pts/1    Ss+  01:49   0:00 /sbin/agetty -o -p -- \u --noclear [...]
root@testlxc:~# 
Ora ci si trova nel contenitore; l'accesso ai processi è ristretto solo a quelli avviati dal contenitore stesso e l'accesso al file system è analogamente ristretto al sottoinsieme dedicato del file system completo (/var/lib/lxc/testlxc/rootfs). Si può uscire dalla console con Control+a q.
Da notare che il contenitore è stato eseguito come processo in background, grazie all'avvio di lxc-start che usa in modo predefinito l'opzione --daemon. Si può interrompere l'esecuzione del contenitore con un comando del tipo lxc-stop --name=testlxc.
Il pacchetto lxc contiene uno script di inizializzazione che può avviare automaticamente uno o più contenitori quando si avvia l'host (si basa su lxc-autostart che avvia i contenitori che hanno l'opzione lxc.start.auto impostata a 1). Un controllo più dettagliato dell'ordine di avvio è possibile con lxc.start.order e lxc.group: per impostazione predefinita, lo script di inizializzazione avvia prima i contenitori che fanno parte del gruppo onboot e poi i contenitori che non fanno parte di alcun gruppo. In entrambi i casi, l'ordine all'interno di un gruppo è definito dall'opzione lxc.start.order.

12.2.3. KVM

KVM, che sta per Kernel-based Virtual Machine (Macchina Virtuale basata su Kernel), è prima di tutto un modulo del kernel che fornisce la maggior parte dell'infrastruttura che può essere usata da un virtualizzatore, ma di per sé non è un virtualizzatore. Il controllo effettivo della virtualizzazione è gestito da un'applicazione basata su QEMU. Non c'è da preoccuparsi se questa sezione menziona comandi qemu-*: si parla comunque di KVM.
Contrariamente ad altri sistemi di virtualizzazione, KVM è stato incluso nel kernel Linux fin dall'inizio.I suoi sviluppatori hanno scelto di sfruttare le istruzioni dei processori dedicate alla virtualizzazione (Intel-VT e AMD-V), cosa che mantiene KVM leggero, elegante e parco di risorse. Il rovescio della medaglia, ovviamente, è che KVM non funziona su tutti i computer ma solo su quelli con procesori adatti. Per i computer x86-based, è possibile verificare di avere un tale processore cercando vmx” o “svm” tra i flag della CPU elencati in /proc/cpuinfo.
Con il supporto attivo al suo sviluppo da parte di Red Hat, KVM sembra destinato a diventare il punto di riferimento per la virtualizzazione in Linux.

12.2.3.1. Passi preliminari

Contrariamente a strumenti come VirtualBox, KVM di per sé non include nessuna interfaccia utente per creare e gestire macchine virtuali. Il pacchetto virtuale qemu-kvm fornisce solo un eseguibile in grado di avviare una macchina virtuale, oltre a uno script di inizializzazione che carica i moduli appropriati del kernel.
Per fortuna, Red Hat fornisce anche un altro insieme di strumenti per affrontare questo problema, sviluppando la libreria libvirt e gli strumenti virtual machine manager associati. libvirt permette di gestire macchine virtuali in modo uniforme, indipendentemente dal sistema di virtualizzazione dietro le quinte (attualmente supporta QEMU, KVM, Xen, LXC, OpenVZ, VirtualBox, VMWare e UML). virt-manager è un'interfaccia grafica che usa libvirt per creare e gestire macchine virtuali.
Prima di tutto si installano i pacchetti richiesti, con apt-get install libvirt-clients libvirt-daemon-system qemu-kvm virtinst virt-manager virt-viewer. libvirt-daemon-system fornisce il demone libvirtd, che permette di gestire (potenzialmente da remoto) le macchine virtuali che girano sull'host e fa partire le VM richieste all'avvio dell'host. libvirt-clients fornisce lo strumento a riga di comando virsh, che permette di controllare le macchine gestite da libvirtd.
Il pacchetto virtinst fornisce virt-install, che permette di creare macchine virtuali da riga di comando. Infine, virt-viewer permette di accedere alla console grafica di una VM.

12.2.3.2. Configurazione di rete

Proprio come in Xen e LXC, la configurazione di rete più frequente richiede un bridge che raggruppa le interfacce di rete delle macchine virtuali (vedere Sezione 12.2.2.2, «Configurazione di rete»).
In alternativa e nella configurazione predefinita fornita da KVM, alla macchina virtuale è assegnato un indirizzo privato (nell'intervallo 192.168.122.0/24) e viene impostato il NAT cosicché la VM possa accedere alla rete esterna.
Il resto di questa sezione assume che l'host abbia un'interfaccia fisica eth0 e un bridge br0 e che la prima sia connessa al secondo.

12.2.3.3. Installazione con virt-install

Creare una macchina virtuale è molto simile a installare un sistema normale, tranne che le caratteristiche della macchina virtuale sono descritte da una riga di comando che sembra infinita.
In pratica, questo vuol dire che si userà l'installer Debian, avviando la macchina virtuale su un lettore DVD-ROM virtuale che viene mappato su un'immagine DVD di Debian memorizzata sul sistema host. La VM esporterà la sua console grafica sul protocollo VNC (vedere Sezione 9.2.2, «Utilizzo di desktop remoti grafici» per i dettagli), il che consentirà di controllare il processo di installazione.
Innanzitutto bisogna indicare a libvirtd dove memorizzare le immagini dei dischi, se non va bene la posizione predefinita (/var/lib/libvirt/images/).
# mkdir /srv/kvm
# virsh pool-create-as srv-kvm dir --target /srv/kvm
Pool srv-kvm created

# 
Si avvia il processo di installazione per la macchina virtuale e si guardano più da vicino le opzioni più importanti di virt-install. Questo comando registra la macchina virtuale e i suoi parametri in libvirtd, quindi la avvia cosicché la sua installazione può procedere.
# virt-install --connect qemu:///system  1
               --virt-type kvm           2
               --name testkvm            3
               --memory 2048             4
               --disk /srv/kvm/testkvm.qcow,format=qcow2,size=10  5
               --cdrom /srv/isos/debian-11.2.0-amd64-netinst.iso  6
               --network bridge=virbr0   7
               --graphics vnc            8
               --os-type linux           9
               --os-variant debiantesting


Starting install...
Allocating 'testkvm.qcow'

1

L'opzione --connect specifica quale "hypervisor" usare. La sua forma è quella di un URL contenente un sistema di virtualizzazione (xen://, qemu://, lxc://, openvz://, vbox:// e così via) e la macchina che deve ospitare la VM (questo può essere lasciato vuoto nel caso dell'host locale). Inoltre e nel caso di QEMU/KVM ciascun utente può gestire macchine virtuali che funzionano con permessi ristretti e il percorso nell'URL permette di differenziare le macchine "di sistema" (/system) dalle altre (/session).

2

Poiché KVM è gestito allo stesso modo di QEMU, --virt-type kvm permette di specificare l'uso di KVM anche se l'URL sembra quello di QEMU.

3

L'opzione --name definisce un nome (unico) per la macchina virtuale.

4

L'opzione --memory permette di specificare la quantità di RAM (in MB) da allocare per la macchina virtuale.

5

--disk specifica la posizione del file immagine che deve rappresentare il disco fisso della macchina virtuale; quel file è creato, se non presente, con una dimensione (in GB) specificata dal parametro size. Il parametro format permette di scegliere fra vari modi di memorizzare il file immagine. Il formato predefinito (qcow2) permette di iniziare con un file piccolo che cresce solo quando la macchina virtuale comincia effettivamente ad usare spazio.

6

L'opzione --cdrom è usata per indicare dove trovare il disco ottico da usare per l'installazione. Il percorso può essere un percorso locale di un file ISO, un URL dove reperire il file o il device di un lettore CD-ROM fisico (es. /dev/cdrom).

7

--network specifica come la scheda di rete virtuale si integra nella configurazione di rete dell'host. Il comportamento predefinito (che in questo esempio è esplicitamente forzato) è di integrarla in un qualunque bridge di rete preesistente. Se non esiste un tale bridge, la macchina virtuale raggiungerà la rete fisica solo tramite NAT, quindi riceve un indirizzo in un intervallo di una sottorete privata (192.168.122.0/24).
La configurazione di rete predefinita, che contiene la definizione per un'interfaccia bridge virbr0, può essere modificata con virsh net-edit default e avviata con virsh net-start default se non è già stata eseguita automaticamente durante l'avvio del sistema.

8

--graphics vnc indica che la console grafica deve essere resa disponibile tramite VNC. Il comportamento predefinito per il server VNC associato è di soltanto restare in ascolto sull'interfaccia locale; se il client VNC deve girare su un host diverso, si dovrà impostare un tunnel SSH per stabilire la connessione (vedere Sezione 9.2.1.4, «Creazione di tunnel cifrati con il port forwarding»). In alternativa, si può usare --graphics vnc,listen=0.0.0.0 in modo che il server VNC sia accessibile da tutte le interfacce; notare che in questo caso, sarebbe veramente necessario configurare un firewall di conseguenza.

9

Le opzioni --os-type e --os-variant permettono di ottimizzare alcuni parametri della macchina virtuale, basandosi su alcune delle funzionalità note del sistema operativo lì menzionato.
L'elenco completo dei tipi di sistema operativo (OS - Operative System) può essere visualizzato usando il comando osinfo-query os presente nel pacchetto libosinfo-bin.
A questo punto la macchina virtuale è in esecuzione e bisogna connettersi alla console grafica per procedere con il processo di installazione. Se la precedente operazione è stata lanciata da un ambiente desktop grafico, questa connessione dovrebbe essere avviata automaticamente. In caso contrario, o in caso si operi da remoto, si può eseguire virt-viewer da qualunque ambiente grafico per aprire la console grafica (notare che la password di root dell'host remoto viene chiesta due volte perché l'operazione richiede 2 connessioni SSH):
$ virt-viewer --connect qemu+ssh://root@server/system testkvm
root@server's password: 
root@server's password: 
Connessione alla sessione di installazione mediante virt-viewer

Figura 12.1. Connessione alla sessione di installazione mediante virt-viewer

Al termine del processo di installazione, la macchina virtuale viene riavviata ed è ora pronta all'uso.

12.2.3.4. Gestire macchine con virsh

Ora che l'installazione è terminata, si passa a come gestire le macchine virtuali disponibili. La prima cosa da provare è chiedere a libvirtd la lista delle macchine virtuali che gestisce:
# virsh -c qemu:///system list --all
 Id Name                 State
----------------------------------
  8 testkvm              shut off
Si avvia la macchina virtuale di prova:
# virsh -c qemu:///system start testkvm
Domain testkvm started
Si possono ora ottenere le istruzioni per connettersi alla console grafica (il display VNC restituito può essere passato come parametro a vncviewer):
# virsh -c qemu:///system vncdisplay testkvm
127.0.0.1:0
Altri sottocomandi disponibili di virsh includono:
  • reboot per riavviare una macchina virtuale;
  • shutdown per provocare uno spegnimento pulito;
  • destroy per fermarla brutalmente;
  • suspend per metterla in pausa;
  • resume per farla uscire dalla pausa;
  • autostart per abilitare (o disabilitare, con l'opzione --disable) l'avvio automatico della macchina virtuale all'avvio dell'host;
  • undefine per rimuovere ogni traccia della macchina virtuale da libvirtd.
Tutti questi sottocomandi accettano un identificatore di macchina virtuale come parametro.