Xen, Hyperviseur de machines virtuelles
Xen est un logiciel libre de virtualisation permettant de gérer plusieurs VM sur un même serveur physique.
Installation
Tout ce qui suit se fait avec l'utilisateur root.
Système de base
Si vous installez sur un serveur d'OVH, choisissez une distribution Debian (ou autre qui vous plaît et compatible Xen). Ne sélectionnez pas Citrix Xen Server : Citrix n'est pas libre et demandera l'activation d'une licence.
Dans ce genre de cas, faites aussi une installation personnalisée, en veillant à avoir les 3 partitions la racine /
, /home
et la swap
.
Avec une installation basique de Debian, vous avez peut-être déjà 3 partitions : la racine /
, /home
et la swap
.
Démontez /home
dans ce cas, puis éditer /etc/fstab
pour enlever l'entrée lui correspondant. Notez sur quel partition /home
était montée (ici, dans l'exemple, c'est sur /dev/sda3
).
umount /home nano /etc/fstab
Activez LVM (qui permet de gérer les partitions puis créez la partition virtuelle avec pvcreate :
service lvm2-monitor enable service lvm2-monitor restart pvcreate /dev/sda3
Dans le cas où service lvm2 enable
retourne l'erreur lvm2: unrecognized service
, installez lvm2 :
apt install lvm2
Lors du pvcreate, si vous avez un message tel que WARNING: ext4 signature detected on /dev/sda3 at offset 1080. Wipe it? [y/n]:
, vous pouvez dire yes. Cela écrase le précédent volume.
Nous allons ensuite utiliser /dev/sda3
pour créer un “groupe de volumes” : toutes nos VM seront contenues là, dans des volumes logiques. Notre système hôte, dans l'exemple, s'appelle groska : nous allons aussi donner ce nom au groupe de volume.
vgcreate groska /dev/sda3
Installer les divers outils dont on va avoir besoin :
apt update apt install xen-tools qemu-system-x86 xen-system-amd64 avant buster : xen-linux-system-amd64
Booter sur le bon noyau : configuration de GRUB
Avec Stretch sur online.net, je n'ai pas eu besoin de changer manuellement le noyau
reboot
Sinon il faut ensuite changer le noyau puis redémarrer, pour utiliser celui de Xen.
dpkg-divert --divert /etc/grub.d/08_linux_xen --rename /etc/grub.d/20_linux_xen # La ligne ci-dessous ne concerne que les machines chez OVH. dpkg-divert --divert /etc/grub.d/09_OVHkernel --rename /etc/grub.d/06_OVHkernel update-grub reboot
S'il est activé, la commande xl list
devrait lister les domaines, d'une façon similaire à celle ci-dessous :
# xl list
Name ID Mem VCPUs State Time(s)
Domain-0 0 14779 8 r----- 1881.8
Si ça fonctionne passez au 1.3 .
Si ça ne marche pas
Si ce n'est pas le cas et que vous obtenez ERROR: Can't find hypervisor information in sysfs!
alors on va chercher le bon noyau.
- vérifier dans
/etc/grub.d/
qu'il y ait bien 06_linux_xen juste après 05_debian_theme - vérifier que
update-grub
a bien été lancé avant de redémarrer.
Si ça ne suffit toujours pas :
grep -Eoe "(menuentry|submenu) '[^']*'" /boot/grub/grub.cfg | nl -v0
Repérez la première entrée menuentry
avec “xen” dedans, par exemple :
menuentry 'Debian GNU/Linux, with Linux 3.2.0-4-amd64 and XEN 4.1-amd64'
Pour vérifier que tout va bien, utilisez grub-reboot, qui va tester l'entrée en question au prochain démarrage (et uniquement au prochain démarrage : cela permet de rapidement revenir à quelque chose de fonctionnel en cas d'erreur)
grub-reboot 'Debian GNU/Linux, with Linux 3.2.0-4-amd64 and XEN 4.1-amd64' reboot
Si xl list
donne un résultat, c'était la bonne entrée.
Il faut alors mettre grub à jour en éditant /etc/default/grub
. Changez le numéro du menuentry GRUB_DEFAULT=0
, sachant qu'on compte à partir de 0 ; Xen est probablement le 3e dans la liste (en général il y a le système de base, puis le système en mode rescue, et ensuite Xen), ce qui donne GRUB_DEFAULT=2
.
Ensuite :
update-grub reboot
Attention, si Xen est bien installé, il va créer un /boot/grub/grub.cfg
avec des sous-menu et il faut adapter la syntaxe (voir man grub-reboot
), par exemple :
grub-reboot '0>0>2'
Xen override grub
Vérifiez dans le fichier /etc/default/grub.d/xen.cfg
que la variable XEN_OVERRIDE_GRUB_DEFAULT
soit à 1, et dans le bloc suivant il doit y avoir la bonne entrée (GRUB_DEFAULT
doit correspondre à la bonne entrée) :
if [ "$XEN_OVERRIDE_GRUB_DEFAULT" = "1" ]; then GRUB_DEFAULT="Debian GNU/Linux, with Xen hypervisor" fi
Exécutez update-grub
, ça devrait être bon maintenant.
Forcer le boot d'un noyau
Il se peut aussi que l'hyperviseur Xen n'ait pas été configuré pour être le “noyau” démarré par défaut. Pour vérifier cela, on peut lister les différentes possibilités que nous offre grub lors du boot :
awk -F\' '/(menuentry|submenu)\ / {print $2}' /boot/grub/grub.cfg | nl -v0
Remarquez les numéros en début de ligne : c'est le numéro qui nous permettra de dire à grub quel noyau démarrer par défaut. Pour voir lequel est actuellement configuré :
grep -Eoe "(menuentry|submenu) '[^']*'" /boot/grub/grub.cfg | nl -v0
0 menuentry 'Debian GNU/Linux, with Xen hypervisor' 1 submenu 'Advanced options for Debian GNU/Linux (with Xen hypervisor)' 2 submenu 'Xen hypervisor, version 4.8-amd64' 3 menuentry 'Debian GNU/Linux, with Xen 4.8-amd64 and Linux 4.9.0-7-amd64' 4 menuentry 'Debian GNU/Linux, with Xen 4.8-amd64 and Linux 4.9.0-7-amd64 (recovery mode)' 5 menuentry 'Debian GNU/Linux, with Xen 4.8-amd64 and Linux 4.9.0-6-amd64' 6 menuentry 'Debian GNU/Linux, with Xen 4.8-amd64 and Linux 4.9.0-6-amd64 (recovery mode)' 7 submenu 'Xen hypervisor, version 4.8-amd64.efi' 8 menuentry 'Debian GNU/Linux, with Xen 4.8-amd64.efi and Linux 4.9.0-7-amd64' 9 menuentry 'Debian GNU/Linux, with Xen 4.8-amd64.efi and Linux 4.9.0-7-amd64 (recovery mode)' 10 menuentry 'Debian GNU/Linux, with Xen 4.8-amd64.efi and Linux 4.9.0-6-amd64' 11 menuentry 'Debian GNU/Linux, with Xen 4.8-amd64.efi and Linux 4.9.0-6-amd64 (recovery mode)' 12 menuentry 'Debian GNU/Linux' 13 submenu 'Advanced options for Debian GNU/Linux' 14 menuentry 'Debian GNU/Linux, with Linux 4.9.0-7-amd64' 15 menuentry 'Debian GNU/Linux, with Linux 4.9.0-7-amd64 (recovery mode)' 16 menuentry 'Debian GNU/Linux, with Linux 4.9.0-6-amd64' 17 menuentry 'Debian GNU/Linux, with Linux 4.9.0-6-amd64 (recovery mode)'
On peut obliger grub à démarrer un noyau spécifique au prochain redémarrage avec la commande xen-set-default
en lui donnant l'entrée à démarrer, soit par son nom, soit par son numéro ; par contre étant donné que c'est un menu avec sous-menus et éventuellement sous-sous-menus, il faut donner à la commande le chemin complet de l'entrée à démarrer, par exemple :
grub-set-default '1>2>3'
Alors c'est comme un chemin, sauf que c'est séparé par des >
.
Ou avec le nom exact, selon l'exemple ci-dessus :
grub-set-default 'Advanced options for Debian GNU/Linux (with Xen hypervisor)>Xen hypervisor, version 4.8-amd64>Debian GNU/Linux, with Xen 4.8-amd64 and Linux 4.9.0-7-amd64'
locales
Grub a besoin que la locale par défaut soit anglaise. Suite à un problème de boot on a mis la locale en_US.UTF-8
et re-généré le fichier /boot/grub/grub.cfg avec update-grub
.
Bug et impossibilité de redémarrer
Nous avons rencontré un bug lors de la dernière mise à jour de Xen. La machine refusait de redémarrer. La source du problème était la langue (“locale”) qui était en français, et les scripts de grub n'aiment pas ça (en tout cas pas à l'heure actuelle – août 2018). Voir ci-dessus pour la résolution du problème.
Configuration du réseau
Le serveur Xen fait aussi office de routeur pour les VM. Les machines virtuelles ont leur propre réseau, elles ont accès au réseau mais ne peuvent être joignables sans ajout de règle sur le pare-feu.
Modifiez /etc/sysctl.conf
et décommentez/ajoutez la ligne suivante :
net.ipv4.ip_forward=1
Pour une prise en charge immédiate des modification du fichier /etc/sysctl.conf
taper la commande :
sysctl -p /etc/sysctl.conf
Trouvez quelle est votre interface ethernet (probablement quelque chose comme enp1s0, ou eth0) :
ip a
Ensuite, modifiez iptables. Si c'est enp1s0
:
iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
Sauvegardez les règles iptables uniquement après s'être assuré de leur fonctionnement ! Pour cette règle là, ça ne devrait pas poser trop de problème.
Sauvegarde des règles :
apt install iptables-persistent iptables-save > /etc/iptables/rules.v4
Pour exécuter les règles au démarrage du serveur, éditez le fichier /etc/network/interfaces
:
auto enp1s0 iface enp1s0 inet static address 91.121.136.163 netmask 255.255.255.0 network 91.121.136.0 broadcast 91.121.136.255 gateway 91.121.136.254 # Ajoutez la ligne suivante post-up iptables-restore /etc/iptables/iptables.rules
On configure Xen pour utiliser le NAT. Dans /etc/xen/xl.conf
, ajoutez ou décommentez :
# default vif script to use if none is specified in the guest config vif.default.script="vif-nat"
On redémarre le service de xen :
systemctl restart xen
Pour vérifier à quoi ressemble le réseau :
ip route ls
Configuration des machines virtuelle et accès réseaux
Configuration des outils Xen
Afin de réduire le nombre d'options à taper lors d'utilisation des commande xen.
Par défaut ne veut pas dire définitive, la commande xen-create-image (voir plus bas) prend toujours le dessus sur ces paramètres.
Nous commencerons par modifier le fichier /etc/xen-tools/xen-tools.conf
:
# Paramètres par défaut des VM
###
# Groupe de volumes où le script va créer des volumes logiques
# (=partitions) nécessaires à la VM,
# dans notre exemple précédent il s’agissait de groska donc :
lvm = groska
# Les tailles sont définie en octet comme suit : G=Giga, M=Mega, k=Kilo
# Taille de la partition root où seront stockées les données
size = 20G
# RAM allouée à la machine
memory = 1G
# Taille de la partition swap
swap = 1G
# Système de fichiers
fs = ext4
# Distribution installée
# `xt-guess-suite-and-mirror --suite` : même distribution que le Dom0
dist = `xt-guess-suite-and-mirror --suite`
# Les paramètres réseau
gateway = 192.168.20.254
netmask = 255.255.255.0
broadcast = 192.168.20.255
# Vous pouvez changer le DNS par défaut de vos VM :
# nameserver = 5.9.49.12
# On lance les VM via pygrub
pygrub = 1
# Exécuter immédiatement après création.
boot = 1
Les paramètres réseau de ce fichier peuvent différer de ceux de /etc/network/interfaces, ça n'est pas un souci.
Pour plus d'informations taper man xen-create-image
dans un terminal.
Pour rendre vos VM accessibles sans mot de passe, il est possible d'intégrer directement votre clef publique aux nouvelles VM.
Attention, les clefs seront installées sur toutes les Machine nouvellement créées. N'y placez pas les clefs publiques de n'importe qui !
Sur le serveur Hôte (Dom0) :
mkdir -p /etc/xen-tools/skel/root/.ssh chmod -R 700 /etc/xen-tools/skel/root
Depuis votre machine :
cat ~/.ssh/VOTRE_clef_public_ssh #par defaut id_rsa.pub
Copiez le contenu de la commande précédente et tapez dans la console de votre machine Xen :
echo "Coller_Ici_Le_Contenu_de_la_clef" >> /etc/xen-tools/skel/root/.ssh/authorized_keys
Création d'une VM
Pour créer une VM :
xen-create-image --hostname=myvm --ip=192.168.20.35 --vifname=vif_myvm
xen-create-image
pour créer une image–hostname=myvm
: remplacez “myvm” par le nom que vous souhaitez donner à votre VM !–ip=192.168.20.35
: ce sera l'ip par laquelle on accèdera à nos VM, après être passé par une salade interne ; commencez par “192.168.20.” puis mettez ce que vous voulez, tant que 2 VM ne partagent pas la même.–vifname=vif_myvm
Permet de choisir le nom de l'interface réseau de la VM côté hôte. Ceci facilite la lecture d'information avecifconfig
et/ouip add
Si vous souhaitez outrepasser les paramètres par défaut définis dans /etc/xen-tools/xen-tools.conf
, les paramètres donnés à la commande xen-create-image
sont prioritaires. Par exemple :
xen-create-image --dist=jessie --pygrub --hostname=myvm --size=50G --lvm=groska --ip=192.168.20.35 --mem=1024Mb --netmask=255.255.255.0
–dist=jessie
pour dire quelle distribution utiliser–pygrub
: démarre les VM avec un “grub”–size=50G
: taille que la VM va prendre sur le disque dur–lvm=groska
: VG (groupe de volumes) sur lequel le script va créer des volumes logiques (=partitions) nécessaires à la VM, ici on l'a défini plus haut et appelé groska. Il va créer un LV (volume logique) myvm-disk pour la VM, et un LV myvm-swap pour le swap.–mem=1G
: RAM alloué à la VM, comme pour le fichier de config, vous pouvez utiliser le Gb, Mb et le Kb.–netmask=255.255.255.0
: masque de sous-réseau
La création de la VM prend un peu de temps. Notez bien le mot de passe qui est donné à la fin.
Choix de l'ip interne : il faut que le dernier chiffre soit inférieur à 128.
Il y a un lien pair qui est créé et l'adresse ip ne peut pas dépasser certains chiffres.
Donc l'ip 192.168.20.35
est correcte, mais pas 192.168.20.135
.
Pour tout dire, j'ai rien compris à ce qui se passe… M'enfin en principe en appliquant bêtement ça doit marcher ; par contre une adresse ip supérieure à 192.168.x.128
va créer des erreurs à la création.
Si vous avez les éléments pour expliquer la théorie, complétez l'article. — zatalyz 2018/04/20 08:57
NB : pour savoir ce qui reste comme espace de libre :
pvscan
Lancer/se connecter aux VM
La commande suivante liste les VM lancées :
xl list
Il y a toujours Domain-0 : c'est l'hôte.
Les “states” correspondent à :
- r - running : le domaine fonctionne actuellement.
- b - blocked : le domaine est “bloqué”. Peut-être est-ce juste qu'il attend un truc à faire.
- p - paused : le domaine est en pause (commandé par un admin).
- s - shutdown : la commande “shutdown” a été appelée sur ce domaine (en-train de s'éteindre, quoi).
- c - crashed : ça s'est terminé brutalement.
- d - dying : le système meurt, sans être crashé ni en-train de s'éteindre.
Source : Man xl
Pour démarrer une VM, si elle n'est pas lancée (remplacez myvm par son nom dans les exemples suivants), et s'y connecter (sans le -c
, on se contente de la lancer) :
xl create -c /etc/xen/myvm.cfg
Un terminal s'ouvre; pour en sortir proprement (le détacher), le raccourci est ctrl
+]
(peut-être ctrl
+[
sur gnome-terminal; voir la documentation officielle).
Pour rentrer dans une VM lancée, depuis l'hôte :
xl console myvm
Puis retour à la ligne pour entrer dans le terminal (sinon, la commande reste affichée sans rien d'autre)
Pour sortir de la VM, depuis l’hôte :
crlt + ( ou 5
Pour éteindre une VM, depuis l'hôte :
xl shutdown myvm
Forcer violemment une VM à s'éteindre (à éviter) :
xl destroy myvm
Supprimer définitivement une VM
xen-delete-image --lvm=groupe_de_volumes vm
- groupe_de_volumes est le nom du VG où est stocké le volume de la VM qu'on va virer
- vm est à remplacer par le nom de la VM.
Par exemple
xen-delete-image --lvm=groska branaz
Va enlever tous les éléments étiquetés branaz (branaz-disk, branaz-swap) dans le groupe de volumes groska.
Accès distant aux VM
Nous avons une machine virtuelle fonctionnelle, elle a accès à internet mais personne ne peut y accéder depuis l’extérieur.
Sur l'hôte, il faut donc modifier les règles iptables.
Ouverture de l’accès SSH avec une redirection du port externe 3535 vers le port 22 de la machine virtuelle :
iptables -t nat -I PREROUTING -p tcp --destination-port 3535 -j DNAT --to 192.168.20.35:22
Cette manipulation est à refaire pour chaque VM directement accessible via SSH; ici, on pourra accéder à la VM via la commande ssh user@mon.ip -p 3535
.
Une des VM va servir de reverse proxy aux autres. Sur cette VM, on va configurer Apache, ou Haproxy, ou autre, afin de rediriger le trafic web vers les bonnes VM.
Pour des raisons de sécurité, il faut que l'hyperviseur (la partie qui gère les VM) ait le minimum de choses à gérer : les VM, les lvm, et rediriger le réseau vers le pare-feu. Et, si possible, c'est tout.
Si on a configuré myvm
comme VM de reverse proxy (accès via “http” et “https”), ajouter les règles suivantes depuis l'hyperviseur :
iptables -A FORWARD -d 192.168.20.35 -p tcp --sport 80 --dport 80 -j ACCEPT iptables -A FORWARD -d 192.168.20.35 -p udp --sport 80 --dport 80 -j ACCEPT iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.20.35:80 iptables -t nat -A PREROUTING -i eth0 -p udp --dport 80 -j DNAT --to-destination 192.168.20.35:80 iptables -A FORWARD -d 192.168.20.35 -p tcp --sport 443 --dport 443 -j ACCEPT iptables -A FORWARD -d 192.168.20.35 -p udp --sport 443 --dport 443 -j ACCEPT iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 192.168.20.35:443 iptables -t nat -A PREROUTING -i eth0 -p udp --dport 443 -j DNAT --to-destination 192.168.20.35:443
Le port 443 pour https, 80 pour le http.
Penser à sauvegarder les règles pour le redémarrage !
iptables-save > /etc/iptables/rules.v4
Pensez aussi, si ce n'est pas déjà fait, à bien configurer fail2ban sur l'hyperviseur.
Je mets ici un exemple de config iptable
#!/bin/bash #acepter les connexions ssh iptables -t nat -I PREROUTING -i eno1 -p tcp --destination-port ssh -j ACCEPT #rediriger tous les ports sur une VM proxy iptables -t nat -A PREROUTING -i eno1 -j DNAT --to-destination 192.168.**.10 #ouvrir un port ssh pour chaque VM iptables -t nat -I PREROUTING -p tcp --destination-port 3510 -j DNAT --to 192.168.**.10:22 iptables -t nat -I PREROUTING -p tcp --destination-port 3511 -j DNAT --to 192.168.**.11:22 iptables -t nat -I PREROUTING -p tcp --destination-port 3512 -j DNAT --to 192.168.**.12:22 iptables -t nat -I PREROUTING -p tcp --destination-port 3513 -j DNAT --to 192.168.**.13:22 iptables -t nat -I PREROUTING -p tcp --destination-port 3514 -j DNAT --to 192.168.**.14:22 #exemple pour diriger un port sur une VM iptables -t nat -I PREROUTING -i eno1 -p tcp --destination-port **** -j DNAT --to 192.168.**.**:**** #exemple pour prosody iptables -t nat -I PREROUTING -i eno1 -p tcp --destination-port 5222 -j DNAT --to 192.168.**.13:5222 iptables -t nat -I PREROUTING -i eno1 -p tcp --destination-port 5269 -j DNAT --to 192.168.**.13:5269 iptables -t nat -I PREROUTING -i eno1 -p tcp --destination-port 5280 -j DNAT --to 192.168.**.13:5280 iptables -t nat -I PREROUTING -i eno1 -p tcp --destination-port 5281 -j DNAT --to 192.168.**.13:5281
Réinitialiser le mot de passe root d'une VM
Ouais, bon, ça arrive. Si on a accès à l'hôte (Dom), tout va bien.
Commencer par repérer sur quel disque la VM se monte :
nano /etc/xen/myvm.conf
Chercher quelque-chose comme disk = [“phy:/dev/domus/myvm_disk,sda1,w”]
Monter le disque, y accéder en chroot, remettre le mot de passe à zéro :
mount -o loop /dev/domus/myvm_disk /mnt chroot /mnt mount -o remount,rw / passwd mount -o remount,ro / exit
Démonter le disque et relancer la VM :
umount /mnt xl create /etc/xen/myvm.conf
Faire des snapshots, cloner une VM
Il s'agit de manipulations propres à LVM1), c'est donc dans la documentation sur LVM, ici.
Upgrade de Stretch à Buster
Mettre à jour la distribution puis :
apt autoremove
Changer dans /etc/xen/maVM.conf
bootloader = '/usr/lib/xen-4.11/bin/pygrub'
Vérifier que /etc/sysctl.conf
net.ipv4.ip_forward = 1
Dans /etc/xen/scripts/vif-nat (à la fin)
echo handle_iptable
Bugs récurrents
Il y en a quelques uns déjà listé sur cette page, mais consultez aussi la page de LVM, car les deux logiciels sont très liés…
Si lors du lancement d'un VM, vous avez ceci en erreur :
# xl create /etc/xen/etherpad2.cfg Parsing config from /etc/xen/etherpad2.cfg libxl: error: libxl_device.c:381:libxl__device_disk_set_backend: Disk vdev=xvda2 failed to stat: /dev/nuxru/etherpad2-disk: No such file or directory libxl: error: libxl_create.c:946:initiate_domain_create: Unable to set disk defaults for disk 0 libxl: error: libxl.c:1575:libxl__destroy_domid: non-existant domain 2 libxl: error: libxl.c:1534:domain_destroy_callback: unable to destroy guest with domid 2 libxl: error: libxl.c:1463:domain_destroy_cb: destruction of domain 2 failed
Allez voir LVS liste des disques qui ont disparus.
Horloge
Les VM peuvent avoir une heure aberrante par rapport à Dom0. Ce qui est lié à la timezone mal déclarée.
Ça se règle en exécutant en root
dpkg-reconfigure tzdata
Une liste de choix permet alors de cibler le bon fuseau.