FreeBSD : Bhyve

Update 27/01/22 : Rajout d'exemples de commandes et de détails si ZFS n'est pas utilisé.

Bonjour à tous,

Aujourd'hui un nouveau billet qui porte sur Bhyve.

Pour faire court: Bhyve (BSD Hypervisor) est l'outil de virtualisation sous FreeBSD à l'instar de KVM pour Linux.
L'équipe de Bhyve a fait comme choix technique d'utiliser l'extension EPT au niveau CPU. Ce choix restreint donc les architectures possibles (surtout en lien avec l'âge du/des CPU).
Si l'extension EPT n'est pas présente, Bhyve se retrouve très fortement limité: il ne sera possible que de lancer des VM sous FreeBSD et avec uniquement 1 vCPU.

Attention! Dans mon cas j'utilisais un cpu de la génération Nehalem (Xeon L5520) qui a cette extension mais avec une fonctionnalité en moins qui n'arrive qu'à partir de la génération suivante: Westmere. Afin de pouvoir profiter pleinement de Bhyve j'ai dû les remplacer par des Xeon L5640.

Voici la différente, d'abord avec les L5520:

root@bhyve:~ # grep CPU: /var/run/dmesg.boot -A 7
CPU: Intel(R) Xeon(R) CPU           L5520  @ 2.27GHz (1866.77-MHz K8-class CPU)
  Origin="GenuineIntel"  Id=0x106a5  Family=0x6  Model=0x1a  Stepping=5
  Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
  Features2=0x9ce3bd<SSE3,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,DCA,SSE4.1,SSE4.2,POPCNT>
  AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
  AMD Features2=0x1<LAHF>
  VT-x: PAT,HLT,MTF,PAUSE,EPT,VPID
  TSC: P-state invariant, performance statistics

root@bhyve:~ # cpuflags 
/usr/local/bin/cpuflags: gcc: not found
[: -gt: unexpected operator
/usr/local/bin/cpuflags: gcc: not found
Unknown machine - please send cpuflags details to abs@absd.org
OS    : 'FreeBSD'
hw.model  : 'Intel Xeon CPU           L5520  @ 2.27GHz'
hw.machine  : 'amd64'
hw.machine_arch : 'amd64'
cpu details :
CPU: Intel(R) Xeon(R) CPU           L5520  @ 2.27GHz (1866.77-MHz K8-class CPU)
  Origin="GenuineIntel"  Id=0x106a5  Family=0x6  Model=0x1a  Stepping=5
  Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
  Features2=0x9ce3bd<SSE3,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,DCA,SSE4.1,SSE4.2,POPCNT>
  AMD Features=0x28100800<SYSCALL,NX,RDTSCP,LM>
  AMD Features2=0x1<LAHF>
  VT-x: PAT,HLT,MTF,PAUSE,EPT,VPID
  TSC: P-state invariant, performance statistics

Cette génération de CPU possède bien l'extension EPT mais n'est pas compatible avec Bhyve.

Maintenant avec les L5640:

root@bhyve:~ # grep CPU: /var/run/dmesg.boot -A 7
CPU: Intel(R) Xeon(R) CPU           L5640  @ 2.27GHz (2266.79-MHz K8-class CPU)
  Origin="GenuineIntel"  Id=0x206c2  Family=0x6  Model=0x2c  Stepping=2
  Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
  Features2=0x9ee3fd<SSE3,DTES64,MON,DS_CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,DCA,SSE4.1,SSE4.2,POPCNT>
  AMD Features=0x2c100800<SYSCALL,NX,Page1GB,RDTSCP,LM>
  AMD Features2=0x1<LAHF>
  VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
  TSC: P-state invariant, performance statistics

root@bhyve:~ # cpuflags 
/usr/local/bin/cpuflags: gcc: not found
[: -gt: unexpected operator
/usr/local/bin/cpuflags: gcc: not found
Unknown machine - please send cpuflags details to abs@absd.org
OS    : 'FreeBSD'
hw.model  : 'Intel Xeon CPU           L5640  @ 2.27GHz'
hw.machine  : 'amd64'
hw.machine_arch : 'amd64'
cpu details :
CPU: Intel(R) Xeon(R) CPU           L5640  @ 2.27GHz (2266.79-MHz K8-class CPU)
  Origin="GenuineIntel"  Id=0x206c2  Family=0x6  Model=0x2c  Stepping=2
  Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
  Features2=0x9ee3fd<SSE3,DTES64,MON,DS_CPL,VMX,SMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,DCA,SSE4.1,SSE4.2,POPCNT>
  AMD Features=0x2c100800<SYSCALL,NX,Page1GB,RDTSCP,LM>
  AMD Features2=0x1<LAHF>
  VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
  TSC: P-state invariant, performance statistics

La différence est subtile: le L5520 a bien l'extension EPT tout comme le L5640 cependant, ce dernier a en plus le flag UG (Unrestricted Guest) pour le VT-x qui fait toute la différence.

La plateforme utilisée:

  • 2*L5640
  • Supermicro X8DAL-I
  • 3*16Go DDR3 ECC REG
  • Raid 0 de 4*146Go sas 10K

Commencons maintenant par l'ajout des modules nécessaires à Bhyve:

root@bhyve:~ # nano /boot/loader.conf
if_bridge_load="YES"
if_tap_load="YES"
vmm_load="YES"
nmdm_load="YES"
  • if_bridge_load : Charge le driver pour avoir un montage automatique des interfaces Bridge
  • if_tap_load : Charge le driver pour avoir un montage automatique des interfaces tap des VM
  • vmm_load : Module nécessaire à la gestion de machines virtuelles
  • nmdm_load : Charge le driver pour avoir accès à une console série

Pour effectuer leur chargement sans devoir redémarrer:

root@bhyve:~ # kldload if_bridge
root@bhyve:~ # kldload if_tap
root@bhyve:~ # kldload vmm
root@bhyve:~ # kldload nmdm

Afin de se faciliter les opérations, il existe un outil qui s'appelle vm-bhyve qui permet de manipuler Bhyve plus facilement:

root@bhyve:~ # pkg install vm-bhyve grub2-bhyve

La préparation du dataset qui servira à accueillir les VM (si vous utilisez ZFS ce qui est mon cas):

root@bhyve:~ # zfs create tank/vms
root@bhyve:~ # zfs set mountpoint=/vms tank/vms

Si vous n'utilisez pas ZFS, il faut uniquement créer le dossier qui recevras les VMs :

root@bhyve:~ # mkdir /vms

Il faut maitenant rajouter les informations concernant vm-bhyve dans le rc.conf afin qu'il soit lancé automatiquement au boot:

root@bhyve:~ # nano /etc/rc.conf
# Bhyve
vm_enable="YES"
vm_dir="zfs:tank/vms"
vm_list=""
vm_delay="5"
  • vm_enable : permet d'activer ou désactiver vm-bhyve
  • vm_dir : spécifie le dossier ou le dataset où seront stockées les VM
  • vm_list : liste des VM avec un démarrage auto (l'ordre dans la liste régie l'ordre de lancement des VM)
  • vm_delay : délais entre le démarrage de chaque VM

On initialise l'installation:

root@bhyve:~ # vm init

Cette commande crée les répertoires cachés nécessaire au bon fonctionnement de vm-bhyve.

Afin d'automatiser une partie de l'installation (dans le cas de Windows) ainsi que de fournir des paramètres génériques lors de la création des VM, il existe des fichiers de templates:

cp /usr/local/share/examples/vm-bhyve/* /vms/.templates/

Pour utiliser pleinement ZFS, il faut modifier les fichiers de templates. Vous devez rajouter la ligne suivante au niveau de la partie de gestion des disques pour chaque template que vous allez utiliser :

disk0_dev="sparse-zvol"

Et modifier les lignes:

disk0_name="disk0.img"
disk0_type="ahci-hd"

En:

disk0_name="disk0"
disk0_type="virtio-blk"

Ces modifications permettront de créer le disque dur de la vm au sein de ZFS par le biais d'un volume ZFS (zvol) et non d'un fichier .img.

Pour que nos VM puissent avoir accès à des ressources réseaux (internet ou un LAN quelconque), il est nécessaire de créer un virtual switch (vswtich):

root@bhyve:~ # vm switch create public
root@bhyve:~ # vm switch list
NAME    TYPE      IFACE      ADDRESS  PRIVATE  MTU  VLAN  PORTS
public  standard  vm-public  -        no       -    -     -

Le vswitch étant créé, il faut maintenant lui attacher une interface physique pour pouvoir avoir accès à internet/LAN (étape qu'il est possible de sauter si vous souhaitez uniquement créer un vswitch):

root@bhyve:~ # vm switch add public em1
root@bhyve:~ # vm switch list
NAME    TYPE      IFACE      ADDRESS  PRIVATE  MTU  VLAN  PORTS
public  standard  vm-public  -        no       -    -     em1

Attention! L'interface que l'on ajoute au virtualswitch doit avoir une adresse IP sinon le traffic ne sort pas.

Nous pouvons maintenant créer la VM et lancer son installation:

root@bhyve:~ # vm create -t freebsd-zvol -s 16G testvm
root@bhyve:~ # vm install testvm FreeBSD-11-boot-only.iso

Attention! Au boot de l'installeur de FreeBSD, il vous sera demandé le type de console, il faut bien choisir VT100 (normalement le choix par défaut).

Une fois l'installation terminée, il faut choisir l'option pour avoir accès à un shell et faire poweroff afin de pouvoir récupérer la main sur votre terminal de départ.
Vous pouvez maintenant démarrer la VM et y accéder via SSH.

Une petite liste des commandes de base:

  • Lister toutes les VM, qu'elles soient démarrées ou non:
root@bhyve:~ # vm list
NAME        DATASTORE  LOADER     CPU  MEMORY  VNC  AUTOSTART  STATE
testvm      default    bhyveload  1    1024M   -    No         Stopped
  • Démarrer une VM:
root@bhyve:~ # vm start testvm
  • Arrêter une VM (via ACPI):
root@bhyve:~ # vm stop testvm
  • Stopper une VM en restant appuyer sur le bouton power:
root@bhyve:~ # vm poweroff testvm
  • Appuyer sur le bouton reset de la VM:
root@bhyve:~ # vm reset testvm
  • Se connecter à la console de la VM (pour sortir de la console il faut utiliser: ~.):
root@bhyve:~ # vm console testvm
  • Supprimer une VM (doit être arrêtée):
root@bhyve:~ # vm destroy testvm
  • Permet de changer ou rajouter des options à la VM (lance vi en éditeur):
root@bhyve:~ # vm configure testvm
  • Pour augmenter la taille du disque de la VM:
root@bhyve:~ # zfs set volsize=32G zroot/vms/testvm/disk0
  • Pour ajouter un disque non zfs :
root@bhyve:~ # vm add -d disk -t file -s 50G testvm

Vous avez maintenant une installation de Bhyve fonctionnelle!

Have a nice day.