Logo Khaganat
Traductions de cette page?:

Ceci est une ancienne révision du document !


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 avec ifconfig et/ou ip 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.

Lister quels genre d'horloge on peut avoir :

sudo cat /sys/devices/system/clocksource/clocksource0/available_clocksource

Dans mon cas, tsc et xen sont listés. Mais lequel est actif ?

sudo cat /sys/devices/system/clocksource/clocksource0/current_clocksource

Si ce n'est pas xen, ça explique peut-être un souci ? Et ajouter aussi la ligne suivante dans les /etc/xen/vm.cfg :

extra = 'xencons=tty clocksource=xen'

Solution trouvé et adaptée d'un vieux site.

Ceci dit, même après un reboot, ça ne résous rien…

Sources et documentation

1)
En tout cas, chez nous. Il y a d'autres systèmes qui permettent des snapshots.
CC Attribution-Share Alike 4.0 International Driven by DokuWiki
fr/xen.1721815040.txt.gz · Dernière modification : 2024/07/24 09:57 de zatalyz

Licences Mentions légales Accueil du site Contact