Table des matières
Ganeti pour ARN
Ganeti est un outil de gestion de cluster de machines virtuelles développé par Google. l'empilage de solutions utilise Xen ou KVM comme plate-forme de virtualisation, LVM pour la gestion de disques, et éventuellement DRBD pour la réplication de disque sur des hôtes physiques.
Ganeti permet la migration à chaud de machines virtuelles ce qui permet une disponibilité du service de virtualisation en cas de panne ou de maintenance. Ganeti simplifie grandement la gestion de machines virtuelles.
Les scripts/hooks présentés ci-dessous sont publiquement disponibles dans notre dépôt git.
Installation et création du cluster
On suit grosses mailles la doc' officielle : http://docs.ganeti.org/ganeti/2.12/html/install.html
Nommage des hyperviseurs
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
- Il faut que le nom complet (FQDN) de chaque hyperviseur membre du cluster, tel qu'il apparaît dans /etc/hostname (ou commande hostname –fqdn), puisse être résolu, par le DNS ou /etc/hosts ou autre. Il faut que la résolution IPv4 aboutisse à une IPv4 pas locale (pas 127.0.0.1, quoi).
- Attention donc à Debian qui ajoute la ligne incorrecte suivante dans /etc/hosts :
# Cette ligne est incorrecte ! 127.0.1.1 hwhost-1.arn-fai.net # Cette ligne est également incorrecte ::1 hwhost-1.arn-fai.net
- Le cluster doit aussi avoir son propre couple hostname / IPv4. L'IP sera assignée sur une interface de loopback sur l'hyperviseur qui sera le master Ganeti.
- Là aussi, ce nom doit être résolvable en IPv4 via DNS ou /etc/hosts.
- Exemple de loopback définie dans le fichier /etc/network/interfaces de chaque hyperviseur :
# Ganeti and routing loopback auto loopback1 iface loopback1 inet manual pre-up ip link add $IFACE type dummy post-up ip l s up dev $IFACE post-up ip a a 89.234.141.131/32 scope global dev $IFACE post-up ip r a 89.234.141.131/32 dev $IFACE pre-down ip r d 89.234.141.131/32 dev $IFACE iface loopback1 inet6 manual post-up ip -6 a a 2a00:5881:8100::131/128 scope global dev $IFACE post-up ip -6 r a 2a00:5881:8100::131/128 dev $IFACE pre-down ip -6 r d 2a00:5881:8100::131/128 dev $IFACE post-down ip l d $IFACE
Installation de l'hyperviseur
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
- On installe le logiciel hyperviseur que l'on souhaite utiliser. KVM dans notre cas.
sudo apt-get install qemu-kvm
Installation et configuration de DRBD
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
- On installe les outils userland DRBD (le noyau Linux packagé dans Debian contient déjà le module drbd) :
sudo apt-get install drbd8-utils
- On configure les options avec lesquelles le module drbd sera chargé dans le noyau.
- « minor_count » autorise l'existence de N périphériques de type DRBD en simultané donc 64 machines virtuelles (il y a 2 DRBD par machine virtuelle : un de metadatas, l'autre contenant les données, le disque de la VM).
echo "options drbd minor_count=128 usermode_helper=/bin/true" | sudo tee /etc/modprobe.d/drbd.conf
- Le module DRBD doit être chargé au boot :
echo "drbd" | sudo tee -a /etc/modules
- On gère les dépendances entre modules et on charge le module DRBD dans le noyau pour commencer à l'utiliser directement :
sudo depmod -a && sudo modprobe drbd
LVM
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
- On indique à vgscan (qui est exécuté au boot, entre autres) de ne pas chercher de VG sur les DRBD.
sudo sed -i -e 's@#\? \?filter = \[ "a\/\.\*\/" \]@filter = ["r|/dev/cdrom|", "r|/dev/drbd[0-9]+|", "r|/dev/vg_vpsstockage/.*|" ]@' /etc/lvm/lvm.conf
Le fichier change avec Debian Stretch donc la commande devient :
sudo sed -i -e 's@#\? \?filter = \[ "a|\.\*\/|" \]@filter = ["r|/dev/cdrom|", "r|/dev/drbd[0-9]+|" , "r|/dev/vg_vpsstockage/.*|"]@' /etc/lvm/lvm.conf
- Si ce n'est pas fait, il faut créer un PV puis un VG avec le nom que vous voulez. Ganeti peut très bien utiliser le même VG que celui qui contient les volumes dédiés au système de l'hyperviseur même si ça semble plus clean de loger toutes les VM dans un VG distinct.
sudo pvcreate /dev/sdX sudo vgcreate <NOM> /dev/sdX
Installation de Ganeti
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
sudo apt-get install ganeti
Création du cluster Ganeti
Cette section est à exécuter uniquement sur l'hyperviseur qui sera l'hyperviseur master du cluster.
- Initialisation du cluster
sudo gnt-cluster init --enabled-hypervisors=kvm -H kvm:migration_bandwidth=100 --nic-parameters mode=routed --master-netdev=loopback1 \ --vg-name=vg0 --prealloc-wipe-disks yes --node-parameters ssh_port=2222 -B maxmem=1024M,minmem=1024M --enabled-disk-templates drbd,plain,diskless <NOM_CLUSTER>
Explications (dans l'ordre) :
- « –enabled-hypervisors=kvm » : nous utilisons KVM (Ganeti peut aussi prendre en charge Xen) ;
- « -H kvm:migration_bandwidth=100 » : débit maximal utilisable durant une live migration, en mo/s. Ici nous limitons à 100 mo/s soit 800 mbps, ce qui laisse environ 200 mbps pour nos autres usages sur notre lien inter-hyperviseurs à 1 Gbps ;
- « –nic-parameters mode=routed » : nous voulons un réseau routé. Chaque VM aura sa propre interface tap et l'IP de la VM sera routée dessus. Contrairement au mode bridge dans lequel ces interfaces seraient toutes dans un bridge, toutes sur un même segment réseau, un même réseau local L2 ;
- « –master-netdev=loopback1 » : nous assignons l'IP du master à l'interface loopback1 crée au tout début. Une interface portant ce nom-là doit exister sur tous les hyperviseurs. C'est utile en cas de déplacement du master après une panne ;
- « –vg-name=vg0 » : le nom du VG LVM à utiliser pour stocker les VM. Ici vg0 ;
- « –prealloc-wipe-disks yes » : effacer les données avant d'attribuer de l'espace à une VM. Utile pour éviter (en tout cas essayer ;) ) que les abonné-e-s à notre service VPS ne retrouve des données d'ancien-ne-s abonné-e-s sur leur VM avec un programme genre photorec ;
- « –node-parameters ssh_port=2222 » : le démon SSH de nos hyperviseurs écoute sur le port 2222
- « -B maxmem=1024M,minmem=1024M » : une VM peut avoir entre 1G et 1G de RAM par défaut (ça peut être contourne par VM, au cas par cas). Ici, nous mettons des valeurs min et max identiques donc ça désactive le balloning qui peut parfois réserver de mauvaises surprises niveau performances.
- Le nom du cluster, tel que nous l'avons défini à la première étape.
Si vous avez peur d'oublier des paramètres ou n'êtes pas sûr de la valeur à mettre, pas de panique, tout cela peut être changé par la suite avec la commande suivante :
sudo gnt-cluster modify <liste des params à changer>
- Maintenant, il faut ajouter chaque hyperviseur au cluster. Ganeti va configurer automatiquement les nouveaux arrivants notamment en uniformisant la paire de clés SSH utilisée par chaque hyperviseur pour que les admins puissent l'identifier ! Cette configuration se fait en root, avec le mot de passe. Depuis Jessie, l'authentification par mot de passe pour root est désactivée dans sshd. Il faut donc penser à l'activer sur chaque hyperviseur qui sera ajouté. Quand tout est prêt, depuis le master, et pour chaque hyperviseur à ajouter :
sudo gnt-node add hwhost-2.arn-fai.net
Une fois que c'est fait, penser à désactiver à nouveau l'authentification par mot de passe pour root dans la config SSH de chaque hyperviseur : Ganeti a installé sa clé publique dans l'authorized_keys de root sur chaque hyperviseur.
Configurer le debootstrap
- Copier un modèle :
sudo cp /etc/default/ganeti-instance-debootstrap /etc/ganeti/instance-debootstrap/variants/jessie.conf
On peut ensuite modifier cette copie. Exemples :
- « ARCH=“amd64”» au lieu de « ARCH=“i386” » pour avoir un système x86 64 bits au lieu de 32 bits
- Changer le miroir Debian depuis lequel sera tiré le debootstrap
- « SUITE=“jessie” » au lieu de « SUITE=“wheezy” » afin d'installer la dernière version stable de Debian (au moment de l'écriture de cette doc').
- Utiliser « EXTRA_PKGS » pour installer des packages en plus dans chaque VM. Exemple : « EXTRA_PKGS=“acpi-support-base,kbd,udev,linux-image-amd64,openssh-server” ». L'installation de linux-image est nécessaire à la poursuite de cette doc' : nous allons faire en sorte que chaque VM ait son noyau + son GRUB au lieu du noyau et initrd de l'hôte.
- On rajoute le nom de notre variante de debootstrap à la liste des variantes disponibles :
echo "jessie" | sudo tee -a /etc/ganeti/instance-debootstrap/variants.list
- On copie les 2 fichiers décrivant notre variante de debootstrap sur tous les hyperviseurs membres du cluster :
sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/variants/jessie.conf sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/variants.list
- On vérifie. La commande suivante doit afficher, entre autres, « debootstrap+jessie » :
sudo gnt-os list
Variables de scripts
Ci-dessous, nous allons présenter les scripts et les hooks que nous utilisons pour automatiser un maximum le cycle de vie d'une machine virtuelle sur notre cluster Ganeti.
Tous ces scripts inclus un fichier global commun nommé common-arn-vars (récupérable sur notre git). Il doit être stocké en /etc/ganeti/common-arn-vars .
Actuellement, il sert à :
- Définir la variable « CONFDIR » c'est-à-dire le dossier dans lequel est stockée la conf' (réseau, clé publique SSH, mdp VNC, etc.) de chaque VM. Cette variable est utilisée par la plupart de nos scripts & hooks ;
- Définir la variable « APTSOURCES_DIR » c'est-à-dire le dossier dans lequel sont stockés les templates de fichiers sources.list utilisés par le hook d'install « aptsources ».
Script de création de VMs
Notre script de création automatique de VMs est dispo sur notre git. On peut le stocker n'importe où dans l'arborescence du master Ganeti (genre dans /usr/local/sbin). Il n'est pas nécessaire de le copier sur l'ensemble des hyperviseurs.
Ce script permet de :
- Créer une machine virtuelle soit pré-installée avec un Debian GNU/Linux Jessie minimaliste (debootstrap) soit qui boote sur une iso pour installer un système au choix de l'utilisateur-rice de la machine virtuelle ;
- Stocker la config' IPv4 et IPv6 de la machine (dans $CONFDIR ;)) pour qu'elle puisse être chargée au lancement de la VM ;
- S'il s'agit d'un VPS (et pas d'une VM dédiée à l'infra du FAI), on le reconnaît grâce à son nom qui commence par « vps- », on génère et on stocke un mot de passe VNC. À l'inverse, on ne wipe pas le disque si c'est une VM d'infra pour préserver nos SSD.
- D'afficher les principales infos (IPv4, IPv6, empreintes SSH, etc.) concernant la machine virtuelle à la fin de la création. S'il s'agit d'un VPS, on le reconnaît grâce à son nom qui commence par « vps- » et on affiche l'ensemble des informations disponibles dans un format lisible et facilement communicable à l'abonné-e.
Pour que ce script fonctionne, il faut faire un peu de configuration supplémentaire :
- Avec ce script, soit la VM a son propre noyau Linux interne (donc dédié) soit on passe les paramètres qu'il faut pour booter sur une ISO. Donc KVM n'a pas besoin de connaître le noyau à utiliser :
sudo gnt-cluster modify -H 'kvm:kernel_path='
Hooks d'installation
Ces hooks, récupérables sur notre git, sont exécutés à la fin du debootstrap.
- aptsources : copier, dans le rootfs de la VM, un fichier template de sources.list apt situé dans l'arborescence de l'hyperviseur (voir $APTSOURCES_DIR dans le fichier de variables globales.
- grub : prépare l'installation de GRUB sur la VM. Il ajoute d'une ligne dans rc.local qui installe GRUB puis halt la VM lors du premier boot de celle-ci. Ce script prépare aussi les réponses pour les questions posées par GRUB lors de son installation (genre « où dois-je m'installer ? ») et télécharge le paquet dans l'arborescence de la VM sans l'installer.
- hosts : génère, dans le rootfs de la VM, un fichier /etc/hosts minimaliste. Sans cela, c'est le fichier hosts de l'hyperviseur qui est utilisé par debootstrap. Or, ce dernier contient le nom des hyperviseurs, le nom du cluster Ganeti et d'autres associations noms↔IP qui n'ont rien à faire dans une VM.
- login : si une clé publique SSH a été fournie au script de création de VMs, alors on installe cette clé dans l'authorized_keys de root dans la VM et on verrouille le mot de passe de root pour lutter contre les bruteforce SSH (c'est surtout utile avant Jessie puisqu'à partir de Jessie, le rootlogin est désactivé dans SSHd). Si aucune clé n'a été fournie, on configure un mot de passe par défaut standardisé pour root.
- net-interfaces : génère, dans le rootfs de la VM, un fichier /etc/network/interfaces qui implémente notre topologie réseau . Les infos (adresse IPv4 et/ou IPv6) sont récupérées dans $CONFDIR, là où le script de création de VMs les dépose.
- resolvconf : génère, dans le rootfs de la VM, un fichier /etc/resolv.conf pour préciser les récursifs DNS que la VM peut utiliser. Sans cela, c'est le fichier hosts de l'hyperviseur qui est utilisé par debootstrap. Le nôtre est géré par Puppet, qui lui ajoute une mention explicité « MANAGZED BY PUPPET » qui peut faire croire à l'abonné-e qu'ARN entre en douce dans sa VM.
- timezone : configure le fuseau horaire dans la VM .
Il faut stocker ces scripts dans /etc/ganeti/instance-debootstrap/hooks/ avec les bonnes permissions (c'est mieux). Leur présence sur tous les hyperviseurs est nécessaire.
sudo mv scripts/* /etc/ganeti/instance-debootstrap/hooks/ sudo chown root:root /etc/ganeti/instance-debootstrap/hooks/* sudo chmod 744 /etc/ganeti/instance-debootstrap/hooks/*
sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/hooks/aptsources sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/hooks/grub sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/hooks/hosts sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/hooks/login sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/hooks/net-interfaces sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/hooks/resolvconf sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/hooks/timezone
Création de la première VM
On peut désormais créer une VM en utilisant le script de création de VMs. \o/
sudo ./create-ganeti-vm-full -n vm-name [-d disk] [-r ram] [-4 ipv4] [-6 ipv6] [-s suite] [-k sshkey ] [ -i iso ]
Explication des options :
- vm-name : nom de la machine à créer. S'il commence par « vps- », on fait des traitements en plus (voir la section « Script de création de VMs » ci-dessus) ;
- disk : taille du disque à allouer en Go (défaut : 50) ;
- ram : quantité de RAM à allouer en Mo (défaut : 1024) ;
- ipv4 : liste des adresses IPv4 attribuées à la future machine avec leur masque et séparés par des espaces s'il y en a plusieurs (ex. “192.0.2.1/32 192.0.2.2/32”) ;
- ipv6 : idem que le paramètre précédent mais avec des adresses IPv6 (ex. “a:b:c::1/56 a:b:d::1/56”), et le masque de la première adresse doit obligatoirement être un multiple de 4 (et les autres aussi parce que sinon c'est drôlement crade) ;
- suite : quelle suite de debian ? (pour l'instant : wheezy, jessie ; par défaut : jessie).
- sshkey : clé SSH publique à injecter pour root (à défaut un mot de passe prédéfini est configuré).
- iso image : chemin absolu d'une iso à utiliser pour lancer la VM. Si cette option est mise, aucun système ne sera installé sur la VM. ATTENTION : à la fin de l'installation, l'abonné-e doit halt/poweroff sa VM, pas rebooter, sinon la VM rebootera sur l'iso.
Cela se produit si la partition système de l'hyperviseur est chiffrée. Dans un tel cas, lors de la génération de l'initrd de l'hyperviseur (qui est utilisé pour booter la VM la première fois, pour rappel), /usr/share/initramfs-tools/hooks/cryptroot parse /etc/crypttab pour créer un fichier cryptroot qui est stocké dans l'initrd et permet à celui-ci de savoir qu'il doit ouvrir un conteneur chiffré pour y trouver la partition de boot. Ce fichier contient le device source, le nom du device “ouvert” puis ce qu'il convient d'y trouver à l'intérieur genre « lvm=racine » indique que l'on ouvre cette partition chiffrée dans le but d'y trouver un volume LVM nommé « racine ».
L'ouverture de la partitions racine chiffrée est l'une des premières actions réalisées par l'initrd : /init → /scripts/init-top (chargement des modules nécessaires) → /scripts/local:mount_top() → local_top() → /scripts/local-top/cryptroot → parsage de cryptroot qui indique de chercher un volume LVM.
La partition de la VM n'est pas chiffrée. Donc, lors de son démarrage, les scripts dans l'initrd échouent à ouvrir un quelconque conteneur chiffré mais ils continuent à chercher le volume LVM résultant d'une bonne ouverture du conteneur. Forcément, cette recherche échoue, d'où le message en boucle « volume groups not found ».
La seule solution est de générer un initrd sans cryptroot qui sera utilisé en remplacement de l'initrd de l'hôte. Pour ce faire, sur l'hyperviseur master :
sudo mv /etc/crypttab /root/ sudo mkinitramfs -o /var/lib/ganeti/custom-initrd sudo mv /root/crypttab /etc/ sudo gnt-cluster copyfile /var/lib/ganeti/custom-initrd
Et dans le script de création de VMs, il faut remplacer :
gnt-instance start --paused -H kernel_path=/vmlinuz,initrd_path=/initrd.img "$name"
par
gnt-instance start --paused -H kernel_path=/vmlinuz,initrd_path=/var/lib/ganeti/custom-initrd "$name"
Non, il n'y a pas de manière plus douce de faire que de déplacer /etc/crypttab : à partir du moment où ce fichier existe, /usr/share/initramfs-tools/hooks/cryptroot va générer un fichier cryptroot.
Hooks d'exécution
Ganeti permet d'exécuter des scripts sur l'hyperviseur à plusieurs stade du cycle de vie d'une machine virtuelle.
Nos hooks sont disponibles sur notre dépôt git.
Hook au démarrage d'une VM
Nom du script (dispo sur notre git) : kvm-vif-bridge
À mettre dans : /etc/ganeti/kvm-vif-bridge
Exécuté par : l'hyperviseur sur lequel une VM va booter.
Nécessite : l'ajout des lignes suivantes dans /etc/iproute2/rt_protos (signification) :
# Used by ARN team 245 ganeti
Objectifs : globalement, ce script fait la configuration réseau côté hyperviseur pour que la VM devienne accessible, puisque si l'on utilise KVM et le mode routé, Ganeti ne gère pas cet aspect-là (voir la section ci-dessous pour plus d'infos).
- On ajoute un alias (le nom de la VM) à l'interface réseau tap côté hyperviseur. L'idée est de pouvoir repérer facilement l'interface réseau d'une VM en cas de besoin ;
- On désactive la réception d'infos d'autoconfiguration IPv6 depuis l'interface d'une VM : ce n'est pas à une VM d'autoconfigurer nos hyperviseurs-routeurs :D ;
- On ajoute l'IPv4 locale et l'IPv6 locale qu'a notre hyperviseur sur la tap. Ces IPs servent de routeur de sortie pour la VM. Voir routage
- On ajoute les routes IPv4 et IPv6 de la VM
- « $MYV4 » et « $MYV6 » sont les adresses globales avec lesquelles nos routeurs causent à une VM. Voir routage.
- Pour la signification de « proto Ganeti », voir routage.
- Par défaut, les IPs (v4 et v6) sont routées directement sur la VM, sans next-hop. Cela signifie que nos hyperviseurs envoient directement des demandes ARP/NDP sur la tap et que la VM doit y répondre avant de recevoir du trafic. Ce fonctionnement simpliste ne permet pas (sans bidouille type ARP/NDP proxy) le subnetting IPv6 ou l'utilisation de la VM comme un endpoint VPN, par exemple, car alors, la VM ne sera pas en mesure de répondre aux demandes ARP/NDP de nos hyperviseurs. Pour permettre cela, il est possible d'ajouter « VIA=“true” » dans la configuration réseau de la VM côté hyperviseur. L'IPv4 et le bloc IPv6 seront alors routés via l'adresse locale au lien de la VM et les usages sus-cités deviendront possibles.
- Si la VM est celle d'un-e abonné-e, on met à jour un enregistrement DNS pointant sur l'hyperviseur sur lequel la VM est présentement exécutée afin que l'abonné-e puisse utiliser l'interface VNC (qui nécessite de connaître sur quel hyperviseur la VM est exécuté à un instant T).
Hook à la migration d'une VM
Nom du script (dispo sur notre git) : no-ghost-route-with-zebra
À mettre dans : /etc/ganeti/hooks/instance-migrate-pre.d/
Exécuté par : tous les hyperviseurs, avant la live migration d'une VM.
Objectif : voir routage. En gros : si l'on route des IPs/subnet via l'IP (link-locale ou non) d'une VM, alors zebra (module de Quagga qui cause avec Linux) conserve cette route même lorsque l'interface est détruite puisque la VM est migrée.
Hook à la suppression d'une VM
Nom du script (dispo sur notre git) : remove-vm-conf
À mettre dans : /etc/ganeti/hooks/instance-remove-post.d/
Exécuté par : tous les hyperviseurs, après la suppression d'une VM.
Objectif : on supprime la conf' (réseau, VNC) d'une VM lors de sa suppression.
Optimisation
Si les CPU sont homogènes
D'après cette doc, si les cpu sont identiques on peut optimiser la façon dont kvm gère le cpu via :
gnt-cluster modify -H kvm:cpu_type='host'
Commandes utiles
Lister les machines
gnt-instance list
Démarrer une VM
gnt-instance start <vm-name>
Se connecter à une VM via une console
gnt-instance console <vm-name>
Redémarrer une VM
gnt-instance reboot <vm-name>
Éteindre une VM (mode gentil, on laisse une chance à la VM de s'éteindre)
gnt-instance stop <vm-name>
Éteindre "définitivement" une VM depuis l'intérieur
Par défaut, une VM éteinte depuis l'intérieur est présentée avec un status « ERROR_down » donc le watchdog Ganeti la démarrera automatiquement après quelques minutes. Mais si l'utilisateur veut éteindre sa VM ?
Il faut activer les options (historiquement désactivées) :
gnt-cluster modify --user-shutdown=true gnt-cluster modify -H kvm:user_shutdown=true
Ici, les paramètres sont définis pour tout le cluster mais on peut les positionner par instance si nécessaire.
Lorsque l'utilisateur éteint sa VM, un status USER_down est visible dans gnt-instance list au lieu de ERROR_down ou ADMIN_down.
Booter sur une ISO
sudo gnt-instance start -H boot_order=cdrom,cdrom_image_path=/root/mini.iso,serial_console=false <vm-name>
Attention : l'image ISO doit exister sur l'hyperviseur sur lequel la VM sera lancée. Voir la section « Copier un fichier sur tous les membres du cluster ».
Cette configuration est non-persistante : l'image ISO sera virée au redémarrage de la VM côté hyperviseur (mais pas au reboot à l'intérieur du guest).
L'abonné-e peut aussi la virer en exécutant « poweroff » ou « halt -p » depuis sa VM. Le watchdog Ganeti (qui checke toutes les 5 minutes que toutes les VM configurées pour être up sont bien up) relancera la VM dans une nouvelle instance KVM donc la modification sera appliquée.
Non, KVM ne permet pas d'avoir un boot_order=disk,cdrom qui permettrait de ne pas avoir à reboot la VM depuis l'hyperviseur. :-
Gestion des disques des VMs
Intervertir 2 disques
On a besoin typiquement de faire ça sur d'ancien VPS STO:
On récupère l'UUID du premier disque
gnt-instance info vpsto-XXXX
On détache le premier disque et on le rattache en position 1
gnt-instance stop vpsto-XXXX gnt-instance modify --disk UUID:detach vpsto-XXXX gnt-instance modify --disk 1:attach,uuid=UUID vpsto-XXXX gnt-instance start vpsto-XXXX
Monter un disque sur l'hyperviseur
Activer le disques ; noter la sortie, il faudra travailler sur cette machine et ce device ensuite :
gnt-instance activate-disks nom_machine
Lire la table des partitions :
kpartx -av /dev/drbdNN
Faire apparaitre tous les LV du VG précédent, si LVM il y a :
vgchange -t -a y (mode test, pour trouver le nom du VG qu'on veut utiliser) vgchange -a y nomvg
Monter la partition :
mount /dev/mapper/drbdNNp1 /mnt/ OU LVM mount /dev/nomlvkvm/nomlvlxc /mnt
Démonter le lv
umount /mnt (vgchange -a n nomlvkvm) kpartx -dv /dev/drbdNN gnt-instance deactivate-disks nom_machine
Changer le nombre de cœurs CPU virtuels d'une VM
sudo gnt-instance modify -B vcpus=<nombre_CPU> <vm-name>
Pour que l'ajout soit effectif, il faut reboot la VM côté hyperviseur. On peut aussi laisser les adhérents exécuter un « poweroff » ou « halt -p » depuis leur VM. Le watchdog Ganeti (qui checke que toutes les VM configurées pour être up sont bien up) relancera la VM dans une nouvelle instance KVM donc la modification sera appliquée.
Changer la quantité de RAM allouée à une VM
Positionner les bornes :
gnt-instance modify -B maxmem=1024,minmem=128 <vm-name>
Ce sont les limites, le minimum doit être garanti, mais l'instance peut utiliser jusqu'au max s'il y a de la place.
Positionner une valeur dans l'intervalle :
gnt-instance modify -m 256 <vm-name>
La modification est immédiate (en live) si l'on est dans l'intervalle défini au démarrage (ou moins que l'intervalle, si défini en fonctionnement), sinon il faut reboot côté hyperviseur. On peut aussi laisser les adhérents exécuter un « poweroff » ou « halt -p » depuis leur VM. Le watchdog Ganeti (qui checke que toutes les VM configurées pour être up sont bien up) relancera la VM dans une nouvelle instance KVM donc la modification sera appliquée.
Augmenter le disque d'une VM
Ganeti ne sait pas agrandir un disque et notifier la VM (avec qemu). https://code.google.com/p/ganeti/issues/detail?id=258 Mais on peut agrandir dans ganeti (qui s'occupe de DRBD etc.) et après annoncer la taille dans qemu à la main via le monitor… ou juste reboot.
Pour aller taper directement sur le monitor qemu il faut se connecter sur la machine où l'instance tourne et :
socat - UNIX-CLIENT:/var/run/ganeti/kvm-hypervisor/ctrl/<vm-name>.monitor
Commandes (monitor qemu ou reboot depuis l'hyperviseur pour activer la nouvelle taille) :
(master ganeti) gnt-instance grow-disk <vm-name> 0 1g << agrandir d'1G le disque 0 (noter éventuellement la taille totale obtenue pour le block_resize) (monitor qemu) info block << pour trouver le nom interne qemu du disque (monitor qemu) block_resize hotdisk-XXXXXXXXX-pci-4 12G << nom affiché par la commande info et taille absolue du disque
On peut alors voir avec dmesg que la VM a bien remarqué la nouvelle taille.
Il faut ensuite bien sûr redimensionner le système de fichier à l'intérieur, idéalement, à l'aide de parted & resize2fs.
Un exemple type pour un passage de 5Go à 6Go:
root@vps:~# parted /dev/vda GNU Parted 3.2 Using /dev/vda Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print << affiche la table de partition avec diverses informations Model: Virtio Block Device (virtblk) Disk /dev/vda: 6442MB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 1049kB 5369MB 5368MB primary ext4 boot (parted) resizepart Partition number? 1 << le numéro de la partition qu'on souhaite redimensionner Warning: Partition /dev/vda1 is being used. Are you sure you want to continue? Yes/No? Yes End? [5369MB]? 100% << 100% signifie qu'on souhaite utiliser la totalité de l'espace disque (parted) print << on vérifie que le changement a bien été pris en compte Model: Virtio Block Device (virtblk) Disk /dev/vda: 6442MB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 1049kB 6442MB 6441MB primary ext4 boot (parted) q Information: You may need to update /etc/fstab. root@vps:~# resize2fs /dev/vda1 << on agrandit le système de fichier à la taille de la partition. resize2fs 1.43.4 (31-Jan-2017) Filesystem at /dev/vda1 is mounted on /; on-line resizing required old_desc_blocks = 1, new_desc_blocks = 1 The filesystem on /dev/vda1 is now 1572608 (4k) blocks long.
Ajouter un disque HDD à une VM
Cette opération peut se faire à chaud.
gnt-instance modify --disk 1:add,size=200G,vg=vg_vpsstockage --hotplug <VPS_NAME>
Live migration de VMs
Déplacer la machine du primaire au secondaire ou du secondaire au primaire (selon l'endroit où elle se trouve)
gnt-instance migrate <nomdevm>
Migrer toutes les VM en cours d'exécution dont un hyperviseur est leur primaire :
gnt-node migrate <NOM_HYPERVISEUR>
Pour répartir / re-balancer automatiquement les machines virtuelles sur les hyperviseurs (voir http://shaarli.guiguishow.info/?KVf3JA ) :
hbal -L -C -p --no-disk-moves --exclude-instances=XXX,YYY,etc
Réinstallation / changement de système
Éventuellement changer de variante de debootstrap à utiliser :
gnt-instance modify -o debootstrap+<suite> <nomdevm>
Faire la réinstallation :
gnt-instance reinstall <nomdevm>
Attendre le retour au prompt (qui correspond au temps que debootstrap s'exécute) puis lancer la VM avec le noyau externe (afin que GRUB soit installé) :
gnt-instance start --paused -H kernel_path=/vmlinuz,kernel_args="ro root=/dev/vda1",initrd_path=/initrd.img <nomdevm> gnt-instance console <nomdevm>
Démarrer enfin la VM pour de bon :
gnt-instance start <nomdevm>
IL peut être nécessaire de remettre les IPs:
gnt-instance modify --os-parameters ipv4=<ipv4>/32,ipv6=<ipv6>/128 <nomdevm>
Exécuter une commande sur tous les membres du cluster
gnt-cluster command <COMMANDE>
Pas de commande interactive, bien entendu.
Copier un fichier sur tous les membres du cluster
gnt-cluster copyfile </chemin/vers/fichier>
Connaître l'état des DRBD des VMs en cours d'exécution
cat /proc/drbd
Supprimer une VM
gnt-instance remove <NOM>
Divers
Cette section explique certains de nos choix et reformule de manière synthétique des choses déjà évoquées ci-dessus.
Network
gnt-network (voir http://docs.ganeti.org/ganeti/2.12/html/design-network.html ) aurait pu être pratique mais est un peu limité en pratique :
- On ne veut pas un même /64 IPv6 pour toutes nos VMs mais un /56 par VM
- On n'a pas besoin d'une assignation dynamique des IPs
- Notre routage est un peu complexe, voir routage
Sans gnt-network :
- /etc/ganeti/kvm-ifup-os ne sert qu'aux “communication channels”, voir http://docs.ganeti.org/ganeti/2.12/html/design-os.html#communication-mechanism
- Ganeti ne s'occupe pas du réseau (routage et autres) mais un hook est disponible (pour tous les modes, routé ou bridgé) : /etc/ganeti/kvm-vif-bridge . Voir la section « Hooks d'exécution ».
Instances full (la VM ne dépend pas du host)
Le template debootstrap est fait pour utiliser un linux/initrd externe, or nous on veut que les VM soient indépendantes : chacune doit avoir son noyau et son initrd. Cela offre plus de liberté à l'utilisateur de la VM.
Pour le noyau il suffit de l'installer avec le reste en l'ajoutant aux paquets à installer de notre variante.
Pour GRUB c'est plus difficile, quasi impossible au moment du debootstrap (car on n'a pas de disque virtuel propre). On a donc des hook qui 1) préparent le terrain au moment du debootstrap (config, téléchargement des paquets) et 2) au premier boot (qui doit donc utiliser un linux/initrd externe) on installe vraiment GRUB.
Ajout VM déjà existante (réutiliser un disque)
Faire une image du disque de la VM, la copier dans un nouveau LV de la bonne taille. Il suffit ensuite de créer une nouvelle VM ganeti normalement, avec “adopt=LV” comme disque.
Exemple :
lvcreate -L 5368709120b vg0 dd if=/home/jmichalon/arn-web.img of=/dev/vg0/lvol0 bs=64k gnt-instance add -t plain --disk 0:adopt=lvol0 -B memory=512MB -o debootstrap+jessie \ -O ipv4=89.234.141.68/32,ipv6=2a00:5881:8100:1000::5/64 --no-name-check --no-ip-check --net 0:ip=10.0.0.42 -n hwhost-1 web
L'instance boot alors. On peut ensuite passer en DRBD :
gnt-instance modify -t drbd -n hwhost-2 web
Ne pas oublier de faire les config du script de création s'il y a lieu (config IP entre autres).
Changer les IP du cluster
https://groups.google.com/forum/#!topic/ganeti/-kdir3wKzfg
Changer l'IP master :
- changer l'IP dans le résolveur du nom (DNS, hosts, …)
- rename avec le même nom (ie. gnt-cluster rename ganeti-cluster.arn-fai.net)
Change les IP des nodes (théorie) :
- changer l'IP dans le résolveur du nom (DNS, hosts, …)
- gnt-node add –readd hwhost-1
Attention, il y a des fois des erreurs entre ip secondaires et primaires (multi-homed ou non), et des opérations qu'on ne peut faire que sur un master. En jouant entre la résolution, les secondaires et en basculant le master ça finit par passer. À savoir : pour déterminer si un cluster/nœud est multi-homed il compare juste les adresses primaires/secondaires du nœud.
Wipe des disques avant attribution à une VM
Au cas où on réallouerait une portion de disque ayant appartenu à une autre machine virtuelle auparavant, il semble utile d'écraser ces données. Ganeti peut le faire automatiquement = l'allocation d'un nouveau disque ou à l'agrandissement.
Pour activer la fonctionnalité dans le cluster :
gnt-cluster modify --prealloc-wipe-disks yes
Par contre c'est passablement lent en DRBD puisqu'il faut écrire et synchroniser le tout immédiatement à la création (alors que sinon on peut reconstruire le DRBD en background).
Démarrer une instance et avoir tout le log
Pour démarrer une instance et avoir tout le log (avec pause, la VM est mise en pause puis relancée quand on se connecte à la console) :
gnt-instance start --paused tinst1 gnt-instance console tinst1
Donner un kernel/initramfs pour les instances debootstrap :
gnt-instance modify -H kernel_path=/boot/vmlinuz-3.5.0-17-generic,initrd_path=/boot/initrd.img-3.5.0-17-generic tinst1
Pour accéder à la console, ils utilisent socat :
/usr/bin/socat STDIO,raw,echo=0,escape=0x1d UNIX-CONNECT:/var/run/ganeti/kvm-hypervisor/ctrl/tinst1.serial
Split Brain (divergence entre deux disques DRBD)
Cas numéro 1 : difficulté facile
gnt-instance migrate --cleanup tinst1
Cela ne fera pas une nouvelle migration, si l'instance est déjà sur son nœud primaire. Mais une resynchronisation des disques est effectuée.
Cas numéro 2 : difficulté moyenne
Néanmoins, c'est parfois plus compliqué.
Identifier où se trouve le disque dur le plus à jour
gnt-instance info <NOM_VM> | grep drbd Disk template: drbd - disk/2: drbd, size 50.0G on primary: /dev/drbd2 (147:2) in sync, status *DEGRADED* on secondary: /dev/drbd2 (147:2) in sync, status *DEGRADED* *UNCERTAIN
“*DEGRADED*” : explicite. “*UNCERTAIN STATE*” : à priori celui qui n'est pas à jour…
- Si c'est le “primary” qui est le plus à jour, utiliser l'option “-s” (secondary) dans la commande suivante (-p sinon), qui renvoi tout le disque sur le réseau :
gnt-instance replace-disks -s <NOM_VM>
- Une fois réparé, on vérifie :
gnt-instance info <NOM_VM> | grep drbd
Disk template: drbd - disk/2: drbd, size 50.0G on primary: /dev/drbd2 (147:2) in sync, status ok on secondary: /dev/drbd2 (147:2) in sync, status ok
Cas numéro 3 : difficulté difficile
Parfois, c'est encore plus compliqué.
Dans /proc/drbd, on lit :
24: cs:WFBitMapS ro:Primary/Secondary ds:UpToDate/Consistent C r-----
gnt-instance info <NOM_VM> | grep drbd :
Disk template: drbd - disk/24: drbd, size 50.0G on primary: /dev/drbd24 (147:24) *RECOVERING* 0.00%, ETA unknown, status *DEGRADED* on secondary: /dev/drbd24 (147:24) *RECOVERING* 0.00%, ETA unknown, status *DEGRADED* *UNCERTAIN STATE*
Avec ces indications (et la connaissance du déroulé de l'incident), on se doute fortement que le disque le plus à jour est celui du primaire.
On tente de resynchroniser le secondaire avec « gnt-instance replace-disks -s <NOM_VM> » mais ça ne fonctionne pas : Ganeti nous indique que le disque source est aussi considéré comme non sain donc pas question de resynchroniser quoi que ce soit.
« gnt-instance –cleanup <NOM_VM> » reste bloqué sur « progress: 0.0% » pendant plusieurs dizaines de minutes. Ce n'est pas normal et il faut annuler le job. Pour cela, « gnt-job list » + « gnt-job cancel <ID_job> » (en remplaçant <ID_job> par l'ID du job « INSTANCE_MIGRATE(<NOM_VM>) » ne suffit pas car le job est en cours d'exécution donc intouchable. Il faut stopper les démons Ganeti avec « systemctl stop ganeti » puis supprimer le fichier « /var/lib/ganeti/queue/job-<ID_JOB> » puis relancer les démons Ganeti. Voir : https://groups.google.com/forum/#!topic/ganeti/7dCemwUajaY . À la suite de cela, le disque fût resynchronisé automatiquement sans pertes de données…
Notons qu'un « echo “migrate_cancel” | sudo /usr/bin/socat STDIO UNIX-CONNECT:/var/run/ganeti/kvm-hypervisor/ctrl/<NOM_VM>.monitor » n'a été d'aucun secours.
Réinstaller un hyperviseur suite à une panne matérielle
Soit un cluster Ganeti avec deux machines, hwhost-1 et hwhost-2. Le master est hwhost-1. hwhost-2 a dû être réinstallé à partir de zéro (panne disques dur).
Installation
Installer le paquet « ganeti », qui installera les dépendances dans la version demandée (ici 2.12). Après l'installation, un « gnt-node list » sur hwhost-1 ne trouve toujours pas la machine (« ? » partout), car ganeti n'est pas lancé immédiatement après l'installation : « Incomplete configuration, will not run ».
SSH
Le cluster ganeti configure lui-même des clés SSH pour root lorsqu'on ajoute un nœud la première fois. Ici, il faut donc redéployer.
Avant sa version 2.15, Ganeti utilisait uniquement des clefs DSA, qui sont maintenant considérées obsolètes : leur prise en charge est désactivée par défaut dans OpenSSH 7.0+, version de SSH packagée dans Debian Stretch. Erreur correspondante dans /var/log/auth.log : « key type ssh-dss not in PubkeyAcceptedKeyTypes » Rapport de bug correspondant pour Debian Stretch.
Néanmoins, on peut déployer les clés SSH à la main pour avoir du RSA. Ici on en profite pour faire table rase de l'ancienne configuration client SSH de root sur hwhost-1 (authorized_keys, etc.).
# mkdir /root/.ssh/old # mv /root/.ssh/* /root/.ssh/old # ssh-keygen -t rsa
On ajoute ensuite la clé publique dans l'authorized_keys du compte root sur hwhost-2 et on la connexion fonctionne.
On vérifiera, par la suite, que la reconfiguration de hwhost-2 en nœud ganeti a bien copié la clef privée aussi, au cas où on voudrait faire un failover du master sur cette machine (et c'est bien le cas).
Reconfiguration
Le nœud réinstallé est toujours configuré et connu par le master. On peut donc simplement le “readd”, ce qui garde les mêmes configurations (adresses IP, secondaire des VMs, …). « In case you're readding a node after hardware failure, you can use the --readd parameter ». Pour ce faire :
# gnt-node add --readd hwhost-2.arn-fai.net
Il demande de confirmer l'empreinte de la clé SSH pour se connecter en SSH, ce qui parait étonnant car à la main la connexion était immédiate (known_hosts cohérent) mais, en fait, la commande ssh de ganeti utilise l'option SSH « -o GlobalKnownHostsFile=/var/lib/ganeti/known_hosts -o UserKnownHostsFile=/dev/null ».
À partir de là, « gnt-node list » trouve bien ce deuxième hyperviseur.
Dans le tuto workshop sus-cité, on lit « It could take a while to re-sync the DRBD data if a lot of disk activity (writing) has taken place » sauf que dans notre cas, il ne se passe rien… On lance donc un « gnt-cluster verify », qui râle sur beaucoup de choses dont les paramètres de config', l'absence des hooks, etc. qui ne sont pas encore remis en place. Il nous rappelle aussi que le module drbd n'est pas chargé sur hwhost-2. On copie la configuration, les hooks, etc. depuis hwhost-1 (on ne peut pas utiliser simplement scp à cause des liens symboliques qui ne sont pas préservés par scp) :
rsync -av -e 'ssh -p 2222' /etc/ganeti hwhost-2:/etc/
Ne pas oublier de satisfaire aux exigences des hooks (comme de “créer” le protocole ganeti pour le script kvm-vif-bridge). Pour ce qui est de DRBD et de LVM, refaire la configuration officielle pour le helper et le filtrage des volumes utilisés par vgchange (voir le début de la présente page) .
commande cool : gnt-node list-drbd hwhost-1
Problèmes de re-création des parties secondaires des disques DRBD
Maintenant, on peut tenter de remonter un disque DRBD :
# gnt-instance activate-disks <instance> WARNING: Could not prepare block device disk/0 on node hwhost-2.arn-fai.net (is_primary=False, pass=1): Error while assembling disk: drbd8: can't set the synchronization parameters: Can't change syncer rate: exited with exit code 10 - 8: Failure: (127) Device minor not allocated\nadditional info from kernel:\nunknown minor\n
En lisant la documentation, il apparaît que « replace-disks » serait plus adéquat, on tente :
# gnt-instance replace-disks -a mutu INFO: Checking disk/0 on hwhost-1.arn-fai.net INFO: Checking disk/0 on hwhost-2.arn-fai.net Failure: prerequisites not met for this operation: error type: wrong_state, error details: Please run activate-disks on instance <instance> first
Selon d'autres utilisateurs, ce souci est gênant principalement lorsqu'on n'a que deux nœuds en tout (sinon on peut reconstruire les réplications de disques sur une autre machine). On apprend ici que l'on pourrait éventuellement supprimer une vérification (qui intervient car ganeti essaye de configurer des paramètres DRBD trop tôt ?), mais ça ne fonctionne pas. On voit aussi qu'on pourrait tenter de recréer les volumes LVM sous-jacents à la main. Tentative :
# lvcreate -L 50G vg0 -n ab257c8c-6aa5-499b-8648-70d367b368dd.disk0_data # lvcreate -L 128M vg0 -n ab257c8c-6aa5-499b-8648-70d367b368dd.disk0_meta # drbdmeta /dev/drbd11 v08 /dev/vg0/ab257c8c-6aa5-499b-8648-70d367b368dd.disk0_meta 0 create-md
La commande drbdmeta et ses paramètres sont trouvées dans /var/log/ganeti/node-daemon.log .
A priori le numéro du /dev/drbd n'est pas important (c'est assez logique), car se tromper ici ne porte pas à conséquence…
Après ces trois commandes, « activate-disks » de l'instance correspondante fonctionne, et la synchronisation DRBD démarre. On peut donc partir là dessus !
Pour automatiser la création des LV, on crée donc une liste de nom / taille des LV à partir de la commande :
# lvs -o lv_size,lv_name,vg_name
On s'en sert pour créer un “script” enchaînant des lvcreate -L -n et des drbdmeta et des activate-disks avec son éditeur préféré pour retrouver la forme des trois commandes sus-testées et approuvées.
Notes sur Debian Stretch
Suite au crash matériel de notre deuxième hyperviseur, qui utilisait Debian Jessie, nous l'avons réinstallé en Debian Stretch, qui est sorti y'a quelques semaines, afin d'éviter de repartir sur une version “oldstable”. Quelques notes à propos du mélange Jessie/Stretch au sein d'un même cluster Ganeti.
idée : sur hwhost-2 (Stretch), installer la version de ganeti packagée dans Debian Jessie (2.12) et faire l'upgrade sur hwhost-1 via les backports de Jessie (2.15, comme dans Stretch)dans un deuxième temps.
Ajouter les dépôts Jessie dans la configuration d'apt puis un classique :
# apt-get -t jessie install ganeti Les paquets suivants seront ENLEVÉS : initramfs-tools linux-image-4.9.0-3-amd64 linux-image-amd64
Ha, euh non, en fait, mauvaise idée. :/ On préfère utiliser aptitude et forcer aussi la version de ganeti-instance-debootstrap.
Notons que DRBD supporte bien un écart mineur de version entre 2 hyperviseurs. Exemple :
WARNING: node 5822be58-990e-4d5b-90ab-a73602d3ee75: DRBD version mismatch: 8.4.7 (api:1/proto:86-101) WARNING: node 9ad036d5-df21-4dd1-973f-0b6a8121a9b4: DRBD version mismatch: 8.4.3 (api:1/proto:86-101)
Toutefois, attention : une machine virtuelle lancée (ou migrée) sur l'hyperviseur Stretch ne peut pas être migrée à chaud sur l'hyperviseur Jessie à cause d'un problème de compatibilité minimale des fonctionnalités KVM. La migration d'une machine virtuelle depuis l'hyperviseur sous Jessie fonctionne mais la machine virtuelle arrive freezée sur l'hyperviseur Stretch (console affichée mais plus rien d'actif, ni réseau, ni VNC).
Mettre à jour Ganeti
Contexte : nous avons un hyperviseur qui fonctionne avec Debian Stretch et un autre avec Debian Jessie (voir la section précédente pour plus d'infos). Nous avons la version 2.12 de Ganeti. Stretch et Jessie-backports proposent la 2.15. Comment mettre à jour ?
Sur l'hyperviseur Stretch, on installe Ganeti depuis les dépôts Jessie comme expliqué dans la section précédente.
Sur l'hyperviseur Jessie, on active les backports et on installe ganeti-2.15 ganeti-haskell-2.15 ganeti-htools-2.15 avec aptitude afin de ne pas désinstaller ganeti-2.12 tout de suite.
Sur chaque hyperviseur, tour à tour, on lance la commande de mise à jour :
# gnt-cluster upgrade --to 2.15
Si port SSH différent de 22
Si l'erreur « Ganeti version 2.15 not installed on nodes » se produit, c'est peut-être car le serveur SSH des hyperviseurs est configuré pour écouter un autre port que le port 22 standard et que Ganeti ne gère pas cela lors d'une mise à jour… Solution : corriger la ligne 1769 du fichier /usr/share/ganeti/2.12/ganeti/client/gnt_cluster.py .
Avant :
result = srun.Run(name, constants.SSH_LOGIN_USER, command)
Après :
result = srun.Run(name, constants.SSH_LOGIN_USER, command, port=2222)
Si les clés SSH du cluster sont de type RSA
La dernière action lancée par la commande de mise à jour est la commande « gnt-cluster verify ». Les erreurs suivantes peuvent se produire :
ERROR: node hwhost-1.arn-fai.net: Could not verify the SSH setup of this node. ERROR: node hwhost-1.arn-fai.net: Node did not return file checksum data […] ERROR: instance ext: instance not running on its primary node hwhost-1.arn-fai.net ERROR: node hwhost-1.arn-fai.net: instance ext, connection to primary node failed
Cela se produit quand l'administrateur a remplacé l'antique clé SSH DSA par une clé RSA (voir section précédente). Le support de RSA n'est pas complet avant Ganeti 2.15-8 alors que seule la version 2.15-7 est présente dans Debian Stretch et Jessie-backports. De plus, la version 2.15 introduit une paire de clés pour chaque hyperviseur susceptible d'être candidat au rôle de master. La mise à jour tente donc de créer le fichier qui rassemble ces clés, /var/lib/ganeti/ganeti_pub_keys . Mais comme on a supprimé la clé DSA puisqu'on a migré avec succès à RSA, l'outil de mise à jour n'est pas en mesure de créer ce fichier d'où les erreurs.
Il faut donc créer ce fichier /var/lib/ganeti/ganeti_pub_keys . Sa syntaxe est une ligne par hyperviseur susceptible d'être candidat au rôle de master. Chaque ligne a la forme « <ID_du nœud> <clé publique SSH> ». Les ID des nœuds sont donnés par dans les erreurs de la commande « gnt-cluster verify ». Exemple :
ERROR: node: The following node UUIDs of potential master candidates are missing in the public key file on node hwhost-1.arn-fai.net: 5822be58-990e-4d5b-90ab-a73602d3ee75.
Enfin, il faut combler l'absence de la clé publique DSA :
# cd /root/.ssh # ln -s id_rsa.pub id_dsa.pub
Un « gnt-cluster verify » devrait désormais fonctionner.
Si la migration à chaud échoue
Il se peut qu'il ne soit plus possible de migrer à chaud une machine virtuelle :
Unhandled Ganeti error: Cannot change directory permissions on '/var/run/ganeti/kvm-hypervisor': [Errno 1] Operation not permitted: '/var/run/ganeti/kvm-hypervisor'
Visiblement, ce bug se produit uniquement lorsqu'il y a un mix de versions / de systèmes d'exploitation. Ganeti essaye de créer le dossier /var/run/ganeti/kvm-hypervisor puis de mettre un mode égal à 775. Sauf que si le dossier existe, il appartient à root donc le processus « ganeti-luxid » lancé avec le compte utilisateur « gnt-masterd » ne peut pas changer le mode. D'autant plus qu'il est correct…
Il existe deux solutions : soit patcher ganeti, soit « chown -R gnt-masterd:root /var/run/ganeti/kvm-hypervisor ». La solution la plus propre consiste à patcher Ganeti compte-tenu que le mode est correct et que ce bug ne se produit que lors d'un mix entre deux systèmes (dont l'un en Debian Jessie) et ne se produit pas sur Debian Stretch…
Raccrocher un nœud non reconnu
Lors de la migration vers buster, nous avons eu de multiples problèmes. Interface qui ne se montent pas, règles iptables disparues, bug avec quagga…
Un de sbugs était que le noeud hw1 n'était plus joignable d'après ganeti. Pourtant le ssh fonctionnait.
Après plusieurs tentative nous avons pu réajouter le noeud ainsi: Autorisation de RPC sur les 2 noeuds
iptables -A INPUT -i INTERFACE8LIEN_LOCAL-p tcp -m tcp --dport 1811 -m comment --comment "Ganeti RPC" -j ACCEPT
Réajout du noeud:
gnt-node add --debug --readd hwhost-1.arn-fai.net
Lors de cette opération les VM n'ont pas été redémarré.
Master failover
En cas de panne du master (hwhost-1 chez ARN), lors du transfert du rôle de master du cluster d'un hyperviseur à un autre (gnt-cluster master-failover –no-voting –yes-do-it), il est nécessaire de modifier les lignes suivantes dans /etc/default/ganeti :
WCONFD_ARGS="--no-voting --yes-do-it" LUXID_ARGS="--no-voting --yes-do-it"
Cela permet aux démons ganeti-luxid (l'API qui est derrière les commandes comme gnt-instance) et ganeti-wconfd d'accepter de se lancer sur un hyperviseur qui n'est pas reconnu comme master, le temps de propager la configuration sur tout le cluster (gnt-cluster redist-conf)… ce qui nécessite d'être master. Sans cela, ces démons ne se lancent pas puisque il y a deux hyperviseurs dans le cluster dont l'un ne peut voter puisqu'il est en panne donc l'élection est un échec, donc il faut faire un coup d'état.
Supprimer une VM récalcitrante
Avec drbd il arrive qu'une VM ne se supprime pas car le drbd est utilisé. Concretement ganeti essaie de faire l'équivalent d'un `drbdsetup down RESOURCE_DRBD` qui lui même fait l'équivalent de `dmsetup remove /dev/mapper/DRBD`.
Sauf que ça ne marche pas car le kernel renvoie:
failed to demote
Et drbd conclue que la ressource est utilisé. Pouratnt on a pas trouvé de processus en dehors des [drbd_submit].
Potentiellement la commande ganeti dit quelques chose d'autres.
La solution a consisté à détacher le disque des vm concerné, il est alors possible de les supprimer. MAIS il faut supprimer le drbd si on veut pouvoir créer d'autres VM sinon on aura:
Can't create block device <DRBD8(hosts=5822be58-990e-4d5b-90ab-a73602d3ee75/26-9ad036d5-df21-4dd1-973f-0b6a8121a9b4/26, port=11112, backend=<LogicalVolume(/dev/vg0/31add426-ae5f-414b-bf22-343821e69310.disk0_data, not visible, size=10240m)>, metadev=<LogicalVolume(/dev/vg0/31add426-ae5f-414b-bf22-343821e69310.disk0_meta, not visible, size=128m)>, visible as /dev/disk/0, size=10240m)> on node hwhost-1.arn-fai.net for instance vps-reflexlibre3: Can't create block device: drbd26: minor is already in use at Create() time
Du coup, la solution a été d'identifier le block device associé au drbd et de forcer sa suppression.
dmsetup remove -f /dev/mapper/XXXX
Puis de supprimer la ressource DRBD
drbdsetup down resourceXX
Potentiellement il peut être nécessaie de détacher avant le disque du drbd:
drbdsetup detach /dev/drbdXX
Agrandir une grappe raid
Pour commencer il faut identifier les disques dans la grappe:
cat /proc/mdstat
Le S signifie que c'est un disque de spare.
Puis il faut identifier le disque à ajouter:
fdisk -l | grep "Disk /dev/sd"
Puis on copie la table de partition ici de /dev/sda qui est dans la grappe vers /dev/sdf notre disque à ajouter
sgdisk /dev/sda -R /dev/sdf
On change l'UUID
sgdisk -G /dev/sdf
On vérifie la table de partition
gdisk -l /dev/sdf
On ajoute le disque à la grappe (ici à chaud), par défaut il sera considéré comme 2ème spare
mdadm --manage /dev/md0 --add /dev/sdf1 cat /proc/mdstat
Une fois l'opération finie, on va grossir le raid en changeant le nombre de disque utilisé pour répartir les données, il faut donc compter le nombre de disque initial (sans compter les spares) avec :
cat /proc/mdstat
Puis on augmente de 1:
mdadm --grow --raid-devices=5 /dev/md0
Arrivé ici l'opération peut durer quelques heure spour un raid > 1To (dans notre cas, 9h pour passer de 1,4T à 1,9T). Il y a une barre de progression dans:
cat /proc/mdstat
Une fois que c'est finis, on vérifie que md0 est bien augmenté:
fdisk -l /dev/md0
On fait un partprobe pour rescan les disques au cas où:
partprobe
Et on redimensionne le volume physique du lvm
pvresize /dev/md0
A ce stade le volume group devrait suivre et on devrait avoir dans ganeti la nouvelle taille de stockage:
vgdisplay gnt-node list-storage
Error while assembling disk: drbd : can't attach local disk
Il peut y avoir des problèmes de conflits entre LVM et drbd.
Si un hôte à installer des LVM, ces derniers peuvent être détecté par l'hôte. Ceci peut empécher le boot de la VM avec des messages de ce types:
Error while assembling disk: drbdXX : can't attach local disk
On constate alors que ces drbd seront marqué cs:Unconfigured
cat /proc/drbd
De la même façon si ls vg sur le guest s'appelle de la même façon que l'un des vg de l'hôte ceci peut empécher de créer de nouvelles VM.
La solution à chaud consiste à désactiver les vg sur les noeuds du cluster:
vgdisplay vgchange --activate n /dev/vg-113
Attention de ne pas désactiver les vg de l'hôte.
Dés lors il est en général possible de relancer un start de la VM (ou une création):
gnt-instance start VMNAME
Pour que le redémarrage ce passe bien, il faut a priori filtrer correctement les VG dans /etc/lvm/lvm.conf (propriété filter).
Docs intéressantes
- http://www.policyrouting.org/iproute2.doc.html (pour le mode routed, utilisation de tables de routage séparées)