====== Xen, Hyperviseur de machines virtuelles ====== [[wpfr>Xen|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 [[https://wiki.debian.org/Xen#Prioritise_Booting_Xen_Over_Native|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. --- //[[user:zatalyz|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 : [[http://xenbits.xen.org/docs/unstable/man/xl.1.html|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 [[http://wiki.xen.org/wiki/Xen_FAQ_Console#How_do_I_connect_to_or_detach_from_a_console.3F|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 à LVM((En tout cas, chez nous. Il y a d'autres systèmes qui permettent des snapshots.)), c'est donc dans la [[fr:lvm_snapshot#snapshot|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 [[fr:lvm_snapshot|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 [[fr:lvm_snapshot#lvs_liste_des_disques_qui_ont_disparus|LVS liste des disques qui ont disparus]]. ===== Sources et documentation ===== * https://wiki.xen.org/wiki/Xen_Man_Pages * [[http://xenbits.xen.org/docs/unstable/man/xl.1.html|man de xl]] {{tag>serveur web sysadmin}}