Outils pour utilisateurs

Outils du site


benevoles:technique:ganeti

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.

Source.

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.
Le temps de création de la première VM pourra être plutôt long : debootstrap doit télécharger les paquets sur un serveur Debian et faire sa tambouille. Le temps de création pourra être moindre pour les futures VMs car debootstrap conserve le rootfs créé dans un cache (stocké dans /var/cache/ganeti-instance-debootstrap/cache-$SUITE-amd64.tar par défaut). Ce cache est conservé 14 jours (configurable dans votre variante genre /etc/ganeti/instance-debootstrap/variants/jessie.conf). Les fichiers créés ou modifiés par les hooks d'install ne sont pas mis en cache.
Le script d'installation va démarrer une première fois la VM afin que le hook d'installation de GRUB s'exécute. Il est possible que la VM ne boot pas, qu'elle reste bloquée dans l'initrd en affichant « volume groups not found ».

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'

https://dsa.debian.org/howto/install-ganeti/

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 :

  • 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

benevoles/technique/ganeti.txt · Dernière modification : 2022/02/06 22:13 de ljf