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.
On suit grosses mailles la doc' officielle : http://docs.ganeti.org/ganeti/2.12/html/install.html
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
# Cette ligne est incorrecte ! 127.0.1.1 hwhost-1.arn-fai.net # Cette ligne est également incorrecte ::1 hwhost-1.arn-fai.net
# 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
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
sudo apt-get install qemu-kvm
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
sudo apt-get install drbd8-utils
echo "options drbd minor_count=128 usermode_helper=/bin/true" | sudo tee /etc/modprobe.d/drbd.conf
echo "drbd" | sudo tee -a /etc/modules
sudo depmod -a && sudo modprobe drbd
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
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
sudo pvcreate /dev/sdX sudo vgcreate <NOM> /dev/sdX
Toute cette section est à réaliser sur chaque hyperviseur membre du cluster.
sudo apt-get install ganeti
Cette section est à exécuter uniquement sur l'hyperviseur qui sera l'hyperviseur master 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) :
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>
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.
sudo cp /etc/default/ganeti-instance-debootstrap /etc/ganeti/instance-debootstrap/variants/jessie.conf
On peut ensuite modifier cette copie. Exemples :
echo "jessie" | sudo tee -a /etc/ganeti/instance-debootstrap/variants.list
sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/variants/jessie.conf sudo gnt-cluster copyfile /etc/ganeti/instance-debootstrap/variants.list
sudo gnt-os list
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 à :
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 :
Pour que ce script fonctionne, il faut faire un peu de configuration supplémentaire :
sudo gnt-cluster modify -H 'kvm:kernel_path='
Ces hooks, récupérables sur notre git, sont exécutés à la fin du debootstrap.
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
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 :
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.
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.
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).
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.
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.
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'
gnt-instance list
gnt-instance start <vm-name>
gnt-instance console <vm-name>
gnt-instance reboot <vm-name>
gnt-instance stop <vm-name>
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.
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. :-
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
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
umount /mnt (vgchange -a n nomlvkvm) kpartx -dv /dev/drbdNN gnt-instance deactivate-disks nom_machine
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.
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.
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.
Cette opération peut se faire à chaud.
gnt-instance modify --disk 1:add,size=200G,vg=vg_vpsstockage --hotplug <VPS_NAME>
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
É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>
gnt-cluster command <COMMANDE>
Pas de commande interactive, bien entendu.
gnt-cluster copyfile </chemin/vers/fichier>
cat /proc/drbd
gnt-instance remove <NOM>
Cette section explique certains de nos choix et reformule de manière synthétique des choses déjà évoquées ci-dessus.
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 :
Sans gnt-network :
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.
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).
https://groups.google.com/forum/#!topic/ganeti/-kdir3wKzfg
Changer l'IP master :
Change les IP des nodes (théorie) :
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.
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).
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
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.
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…
gnt-instance replace-disks -s <NOM_VM>
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
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.
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).
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 ».
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).
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
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.
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).
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 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)
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.
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…
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é.
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.
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
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
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).