Depuis sa version 10.0, FreeBSD inclut un hyperviseur nommé bhyve (prononcer « bee-hive »). C’est une plate-forme de virtualisation conçue exclusivement pour FreeBSD et qui permet, à l’instar de QEMU sous Linux, d’héberger des machines virtuelles.
J’ai moi-même été amené ces temps-ci à faire mumuse avec bhyve dans le cadre d’expérimentations à titre personnel : je voulais mettre en place une machine virtuelle sur mon serveur qui, à terme, devrait héberger mon installation d’Asterisk afin de mieux l’isoler du système hôte. Bhyve étant encore relativement jeune, je vous propose donc un petit compte-rendu des étapes nécessaires afin de faire fonctionner une VM sous FreeBSD avec bhyve.
Prérequis
Pour commencer, comme le précise le manuel de FreeBSD, votre machine doit disposer d’un processeur Intel® (resp. AMD®) récent et prenant en charge les fonctions « Extended Page Tables » (EPT) et « VMX unrestricted mode » (UG) (resp. « Rapid Virtualization Indexing » (RVI) ou « Nested Page Tables » (NPT) sur AMD®). Chez Intel, la majorité des Core i3/i5/i7 ou Xeon E3/E5/E7 récents feront l’affaire. Le manuel de FreeBSD décrit une procédure pour tester la compatibilité de votre matériel.
En outre, la plupart du temps, vous voudrez probablement démarrer des machines virtuelles à l’aide d’un gestionnaire de VM comme libvirt sous Linux. Bien qu’il soit possible d’utiliser libvirt sous FreeBSD avec bhyve, j’ai préféré opter pour une solution moins lourde et s’intégrant mieux avec les fonctions de ZFS en installant vm-bhyve.
Enfin, pour la mise en réseau, j’ai choisi de mettre les machines virtuelles « à plat » dans le même réseau que l’hôte, de sorte à ne pas être embêté par une quelconque forme de NAT. Pour cela, il faut reprendre une bonne partie de la configuration réseau et prendre garde aux interactions entre le trafic réseau destiné à la VM et le pare-feu pf de l’hôte.
Nous supposerons également que vous disposiez déjà d’un serveur DNS et d’un serveur DHCP sur votre réseau : la plupart du temps, il s’agit de votre routeur ou de votre box chez vous.
Le schéma ci-dessous reprend la configuration réseau que nous mettrons en place pour l’accès au réseau des machines virtuelles.
Installation et configuration de vm-bhyve
Pour installer vm-bhyve, il suffit de l’installer avec pkg(8) :
# pkg install vm-bhyve
Choisissez ensuite un emplacement dans lequel seront stockés tous les fichiers
de configuration et tous les espaces de stockage de vos VM. Pour ma part,
j’ai choisi d’utiliser /usr/home/vm
. Créez donc le dataset ZFS adéquat :
# zfs create -p zroot/usr/home/vm
Ajoutez ensuite les lignes ci-dessous dans /etc/rc.conf
pour activer
vm-bhyve au démarrage, de sorte à lancer automatiquement les machines
virtuelles souhaitées :
vm_enable="YES"
vm_dir="zfs:zroot/usr/home/vm"
Initialisez ensuite le répertoire utilisé par vm-bhyve et copiez les templates de VM par défaut (j’en parlerai plus tard) :
# vm init
# cp /usr/local/share/examples/vm-bhyve/* /usr/home//vm/.templates/
(Une petite précaution s’impose : vérifiez avec la commande which vm
qu’il
s’agisse bien de /usr/local/sbin/vm
; en particulier, si vous avez installé
le paquet mgetty
sur la même machine, il se pourrait que vous ayiez un
conflit avec l’outil vm
installé par ce dernier. Si c’est le cas, tapez le
chemin complet ou créez un alias dans votre shell.)
Configuration réseau
Cette partie est absolument nécessaire également. Sans cela, le réseau ne fonctionnera pas sur les VM, ou pire, cela ne fonctionnera que dans un sens. L’outil « vm » fournit des commandes de création de switches virtuels, mais cela fonctionne mal lorsque les VM doivent communiquer avec l’hôte. Heureusement, il y a une méthode plus fiable.
Supposons que vous ayiez dans votre /etc/rc.conf
la configuration réseau
suivante :
ifconfig_igb0="inet 192.168.10.21/24"
defaultrouter="192.168.10.254"
Il faudra donc modifier cela pour, à la place, créer un pont ayant comme
unique membre l’interface physique connectée au réseau. L’outil vm-bhyve
ajoute ensuite sur le même pont les interfaces virtuelles nécessaires pour les
VM au fur et à mesure qu’elles démarrent (nommées tap0
, tap1
, tap2
…).
En outre, l’adresse IP de l’hôte doit être affectée au pont et non à
l’interface membre.
On en profite également pour nommer le pont br-net
plutôt que d’utiliser
le nom par défaut bridge0
, ce qui a l’avantage de rendre plus
intelligible la sortie d’ifconfig.
Ainsi, vous devriez avoir la configuration suivante :
# interfaces
ifconfig_igb0="up"
cloned_interfaces="bridge0"
# réseau
ifconfig_bridge0_name="br-net"
ifconfig_br_net="addm igb0"
ifconfig_br_net_alias0="inet 192.168.10.21/24"
# routage
defaultrouter="192.168.10.254"
Si vous avez une machine avec plusieurs VLAN, je préconise de créer autant de ponts qu’il y a de VLAN. Cela vous permet d’isoler les machines virtuelles des VLAN dont elles n’ont pas besoin.
Une fois cette opération terminée, redémarrer le réseau avec les deux commandes :
# service netif restart
# service routing restart
N’oubliez pas ensuite de mettre à jour les fichiers de configuration faisant
référence aux noms de vos interfaces réseau, comme /etc/pf.conf
ou la
configuration de isc-dhcpd
si vous avez un serveur DHCP sur l’hôte.
Redémarrez ensuite les services concernés.
Enfin, pour chaque pont que vous avez créé, utilisez l’outil vm pour créer les switchs virtuels :
# vm switch import public br-net
Cette commande crée un switch virtuel nommé « public » à partir du pont « br-net » créé précédemment à la main.
Nous avons ainsi terminé les paramétrages nécessaires avant la création de la première machine virtuelle sur l’hôte.
Adapter le pare-feu de l’hôte
Les paquets réseau destinés à l’invité demeurent filtrés par le pare-feu pf de
l’hôte avant d’être acheminés vers l’invité. Comme je préfère configurer un
pare-feu sommaire par machine, il faut modifier le /etc/pf.conf
pour
autoriser tout le trafic réseau entre la machine virtuelle et l’extérieur.
Adaptez les noms des interfaces et les adresses IP et ajoutez cela vers le
début de vos règles pf :
pass in quick on igb0 from 192.168.10.22 no state
pass in quick on igb0 to 192.168.10.22 no state
Créer une première machine virtuelle
Afin de permettre de créer de nombreuses machines virtuelles avec des configurations matérielles semblables, vm-bhyve propose l’utilisation de templates. Un template décrit simplement la configuration matérielle par défaut d’une machine virtuelle créée à partir de celle-ci. Dans notre cas, si on souhaite faire tourner une VM sous FreeBSD, le template « default » conviendra, mais il est préférable d’utiliser « freebsd-zvol » si votre hôte utilise ZFS.
Pensez à modifier le template qui vous intéresse dans
/usr/home/vm/.templates
si jamais vous avez créé un switch dont le nom est
différent de « public » dans l’étape précédente. Vous pouvez aussi ajouter
une deuxième interface branchée sur un VLAN d’administration ou effectuer
toute autre modification que vous estimez nécessaire (il vaut mieux garder le
nombre de VCPU et la RAM à leurs valeurs d’origine ; au pire, ça peut se
régler par VM).
Une fois cela fait, il ne reste plus qu’à créer la VM (on crée au passage un disque dur virtuel de 20 Go) :
# vm create -s 20G -t freebsd-zvol ma_vm
On récupère ensuite une image d’installation de FreeBSD (nécessaire seulement la première fois) :
# vm iso \
ftp://ftp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/11.0/FreeBSD-11.0-RELEASE-amd64-bootonly.iso
Enfin, on démarre la VM sur le média d’installation qu’on vient de récupérer
(l’option -f
permet la connexion automatique à la console de l’invité) :
# vm install -f ma_vm FreeBSD-11.0-RELEASE-amd64-bootonly.iso
Il ne reste plus qu’à procéder à l’installation comme n’importe quelle autre machine physique.
Conclusion
La mise en œuvre de bhyve est comparable à celui d’une solution à base de QEMU/KVM sous Linux. Je n’ai pas encore testé la redirection de périphériques PCI, mais je sais que bhyve le permet, moyennant le paramétrage à la fois de l’hôte et de l’invité.
Je dirais donc que bhyve fait tout ce qu’on attend d’une plate-forme de virtualisation. Le seul inconvénient que j’ai relevé est que bhyve exige impérativement du matériel récent. En revanche, on obtient une solution élégante, rapide et qui s’intègre très bien avec ZFS : on peut alors faire des instantanés et des copies de sauvegardes comme avec n’importe quel autre zvol.
En somme, c’est une solution très intéressante lorsqu’on veut isoler des services les uns des autres et qu’une « jail » ne suffit pas.
Commentaires
Poster un commentaire
Poster un commentaire