KVM in KVM

Objectif

Il s'agit de pouvoir exécuter une machine virtuelle de type KVM, à l'intérieur d'une première machine virtuelle (KVM, elle aussi).

Un des avantages de cette idée est de pouvoir développer et tester des hyperviseurs comme des machines virtuelles classiques.

Problème

Pas vraiment de difficulté, il suffit d'avoir du matériel et un noyau relativement récent.

Environnement de départ

  • une machine physique alpha (avec processeur Intel) - noyau 4.6 (jessie-backports) - libvirt (jessie-backports)

Environnement cible

  • une VM hostkvm (créée depuis l'hyperviseur), avec un environnement libvirt / qemu
  • une VM guestkvm (créée depuis hostkvm)

Étapes

Afin de pouvoir créer une VM KVM depuis une première VM, il suffit simplement de s'assurer que la bonne configuration du paramètre:

  • /sys/module/kvm_intel/parameters/nested
  • /sys/module/kvm_amd/parameters/nested

Donc première chose à faire (à adapter au type de processeur utilisé):

$ cat /sys/modules/kvm_intel/parameters/nested
Y

Si la réponse est N (ou 0), il faudra recharger le module en définissant cette option à 1 (ou Y). Cela peut être fait:

  • soit en paramètre de démarrage du noyau: kvm-intel.nested=1 (suivit d'un redémarrage de la machine)

  • soit en option pour modprobe:

    # rmmod kvm-intel
    # echo "options kvm-intel nested=y" > /etc/modprobe.d/kvm.conf
    # modprobe kvm-intel
    

Si la réponse au test est toujours négative c'est que votre noyau / distribution / plateforme matérielle est trop ancien(ne).

Lorsque l'option est activée, il suffit de créer sa première VM (hostkvm) avec l'option:

<cpu mode="host-passthrough"></cpu>

Ainsi, en employant l'outil de création de VM virt-install et le paramètre --cpu host-passthrough, cela donne:

# hostname
alpha
# virt-install --name hostkvm --cpu host-passthrough --ram 4096 --location http://ftp.fr.debian.org/debian/dists/jessie/main/installer-amd64/ --disk size=5 --os-variant debianwheezy --console "pty,target_type=serial" --extra-args="console=ttyS0,115200n8 serial" --network bridge=virbr0

L'option existe de manière similaire au travers de l'interface graphique virt-manager.

On se connecte à la VM par ssh ou directement sur la console, on configure rapidement un environnement libvirt, et on crée la VM guestkvm:

# hostname
hostkvm
# apt-get install ebtables libvirt-bin virtinst
# virsh net-start default
# virt-install --name guestkvm --ram 512 --location http://ftp.fr.debian.org/debian/dists/jessie/main/installer-amd64/ --disk size=1 --os-variant debianwheezy --console "pty,target_type=serial" --extra-args="console=ttyS0,115200n8 serial" --network bridge=virbr0

La seconde installation se réalise, et l'on peut vérifier à partir des diverses machines qui est contenue par qui:

# hostname
alpha
# virsh list
 Id    Name                           State
----------------------------------------------------
 4     hostkvm                        running
# ps aux | grep kvm
libvirt+ 20564  9.7  1.7 3209864 569788 ?      Sl   22:39   1:29 qemu-system-x86_64 -enable-kvm -name hostkvm -S -machine pc-i440fx-2.1,accel=kvm,usb=off -cpu host -m 4096 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid 43642e0a-1022-4136-b8cd-d3b33747ded8 -nographic -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/hostkvm.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=discard -no-hpet -no-shutdown -boot strict=on -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x3.0x7 -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x3 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x3.0x1 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x3.0x2 -drive file=/var/lib/libvirt/images/hostkvm-1.qcow2,if=none,id=drive-virtio-disk0,format=qcow2 -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -netdev tap,fd=24,id=hostnet0,vhost=on,vhostfd=25 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:d2:62:90,bus=pci.0,addr=0x2 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -device usb-tablet,id=input0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 -msg timestamp=on

Sur la machine alpha, libvirt contrôle une VM d'identifiant 4 et nommée hostkvm. Une recherche parmi les processus d'alpha ne montre la présence que d'un seul processus 20564, nommé hostkvm (avec kvm et 4096Mo de RAM).

# hostname
hostkvm
# virsh list
 Id    Name                           State
----------------------------------------------------
 3     guestkvm                       running
# ps aux | grep kvm
libvirt+  8693 59.0 15.0 951028 76064 ?        Sl   23:08   3:08 qemu-system-x86_64 -enable-kvm -name guestkvm -S -machine pc-i440fx-2.1,accel=kvm,usb=off -cpu Broadwell -m 512 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid 7e5df8a8-7764-4dbb-a854-536fe4d6cce6 -nographic -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/guestkvm.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=discard -no-hpet -no-shutdown -boot strict=on -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x3.0x7 -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x3 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x3.0x1 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x3.0x2 -drive file=/var/lib/libvirt/images/guestkvm.qcow2,if=none,id=drive-virtio-disk0,format=qcow2 -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -netdev tap,fd=24,id=hostnet0,vhost=on,vhostfd=25 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:ed:c3:19,bus=pci.0,addr=0x2 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -device usb-tablet,id=input0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 -msg timestamp=on

Sur la machine hostkvm, libvirt contrôle une VM d'identifiant 3 et nommée guestkvm. Une recherche parmi les processus d'hostkvm ne montre la présence que d'un seul processus 8693, nommé guestkvm (avec kvm et 512Mo de RAM).