Virtualisation sous FreeBSD

J’utilise cet article comme un mémo des actions réalisées.
Celles-ci sont donc adaptées à mon environnement et mon matériel, et ne peuvent pas convenir au votre sans adaptation.

Je suis connecté sur la machine hôte en ssh.
Les commandes commençant par # sont lancées en root.
La machine hote est animée par FreeBSD 14.2-RELEASE.

Bhyve

Bhyve est une solution robuste et efficace pour faire de la virtualisation sous FreeBSD, et élégante avec vm-bhyve.

Installation des packages

# pkg install vm-bhyve-devel bhyve-firmware edk2-bhyve grub2-bhyve

Configuration du système

Création du volume ZFS qui accueillera les VMs

# zfs create -o mountpoint=/vm zroot/vm

Activation du service et configuration

Éditer le fichier /etc/rc.conf et ajouter les lignes suivantes :

vm_enable=YES
vm_dir="zfs:zroot/vm"
vm_list=""
vm_delay=3

Pour activer le service vm, vous pouvez aussi utiliser la commande :

# sysrc vm_enable=YESvm_enable: NO -> YES

Copie des modèles

# cp -a /usr/local/share/examples/vm-bhyve/ /vm/.templates

(Re)démarrage du service vm et check

# service vm restart
# vm list
NAME  DATASTORE  LOADER  CPU  MEMORY  VNC  AUTO  STATE

Il n’y a pas (encore) de VM

Configuration réseau

Pour mon environnement, les VMs seront connectées sur mon réseau, sans NAT ni réseau privé, et pourront donc profiter du DHCP et de la connexion Internet en place.
Cette configuration est donc ultra simple.

# sysrc gateway_enable=YES
# sysctl net.inet.ip.forwarding=1
# sysctl net.link.tap.up_on_open=1
# echo net.link.tap.up_on_open=1 >> /etc/sysctl.conf

La première commande configure la machine pour qu’elle agisse comme un routeur IP, par exemple pour transférer des paquets entre les interfaces.

La deuxième fait la même chose de manière différente. Vous pouvez vous reportez à ce thread pour comprendre la différence entre les deux manières de faire.

La troisième ligne assure que l’interface tap sur laquelle s’appuie bhyve pour créer les interfaces réseaux des VMs sera toujours présente en cas de reboot.

La quatrième ligne prérénise cette option pour chaque démarrage.

Création d’un virtual switch

Comme les VMs seront dans le même réseau que la machine hôte, nous allons créer un switch en lui attribuant un IP libre de notre réseau.

# vm switch create -a 192.168.0.201/24 public

Et maintenant si on ping cette IP :

# ping -c 2 192.168.0.201
PING 192.168.0.201 (192.168.0.201): 56 data bytes
64 bytes from 192.168.0.201: icmp_seq=0 ttl=64 time=0.122 ms
64 bytes from 192.168.0.201: icmp_seq=1 ttl=64 time=0.208 ms

--- 192.168.0.201 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.122/0.165/0.208/0.043 ms

Maintent on branche l’interface réseau de la machine à ce switch:

# vm switch add public re0

Et pour afficher les infos du switch :

# vm switch list
NAME    TYPE      IFACE      ADDRESS           PRIVATE  MTU  VLAN  PORTS
public  standard  vm-public  192.168.0.201/24  no       -    -     re0

Vous retrouverez ces infos dans le fichier /vm/.config/system.conf.

# cat /vm/.config/system.conf
switch_list="public"
type_public="standard"
addr_public="192.168.0.201/24"
ports_public="re0"

Le Datastore

Il contient les VMs. Nous l’avons configurer avec l’option vm_dir dans /etc/rc.conf.
Pour vérifier :

# vm datastore list
NAME            TYPE        PATH                      ZFS DATASET
default         zfs         /vm                       zroot/vm

Les images ISOs

Les VMs seront installées à partir d’ISO (à l’ancienne 😉 ).
Nous allons donc ajouter notre première ISOs à partir de sont emplacement sur le serveur FTP de Free.

# vm iso http://ftp.free.fr/mirrors/cdimage.debian.org/debian-cd/12.9.0/amd64/iso-cd/debian-12.9.0-amd64-netinst.iso
/vm/.iso/debian-12.9.0-amd64-netinst.iso        3% of  632 MB  519 kBps 25m46s

Pour lister les ISOs disponibles :

# vm iso
DATASTORE           FILENAME
default             debian-12.9.0-amd64-netinst.iso

Modification du modèle

Les outils vm-bhyve s’appuie sur des modèle pour créer les VMs. Ceux que nous avons copié plus haut.
Nous allons copier le modèle debian.conf et le modifier pour notre usage.

# cp /vm/.templates/debian.conf /vm/.templates/debian_uefi.conf
# vim /vm/.templates/debian_uefi.conf

Modifier le contenu du fichier comme ci-dessous :

loader="uefi"
cpu=1
memory=1024M
network0_type="virtio-net"
network0_switch="public"
uefi_vars="/usr/local/share/uefi-firmware/BHYVE_UEFI_VARS.fd"
disk0_type="nvme"
disk0_name="disk0.img"
grub_run_partition="1"
grub_run_dir="/boot/grub"
graphics="yes"
graphics_port="5900"
graphics_res="800x600"

Les différences concernent :

  • loader : nous choisissons uefi
  • memory : la quantité de mémoire passe à 1Gb
  • disk0_type : le type de disque, on passe en nvme
  • graphics, graphics_port et graphics_res : nous permettrons de nous connecter en VNC sur la VM. Nécessite que loader=uefi.
    • uefi_vars : cette option est indispensable avec UEFI et une install UEFI de la VM.

Création de la VM à partir du template

# vm create -t debian_uefi debian12

Démarrage de la VM en mode install sur l’ISO deabin12.9

# vm install debian12 debian-12.9.0-amd64-netinst.iso

Connexion VNC distante

On récupère le port VNC avec la commande vm list:

# vm list
NAME      DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO  STATE
debian12  default    uefi    1    1024M   0.0.0.0:5900  No    Running (7489)

Et depuis ma machine client je lance une connexion vnc sur l’IP de la machine hôte et le port 5900.

Et c’est partie pour l’installation de la Debian12 dans une VM.

Stopper la VM

Depuis la machine hote :

# vm stop debian12

Démarrer la VM

Depuis la machine hôte une fois installée

# vm start debian12

Supprimer la VM

# vm stop debian12
# vm destroy debian12
Are you sure you want to completely remove this virtual machine (y/n)? y

Et voilà.

Références