Grenode utilise maintenant Ganeti pour gérer certains de ses hyperviseurs, notamment ?tillac.

Le backend de virtualisation utilisé est KVM, et on ne fait pas de DRDB pour le moment.

Documentation

La documentation officielle est assez complète : http://docs.ganeti.org/ganeti/2.15/html/

Quand on sait quoi chercher, les pages de manuel des différentes commandes (gnt-node, gnt-cluster, gnt-instance) sont la référence.

Installation et configuration de ganeti

Installation

On installe Ganeti, les scripts de gestion d'installation via debootstrap, la définition d'OS "noop" qui sert pour les installations manuelles via ISO, ainsi que KVM :

sudo apt-get install --no-install-recommends ganeti ganeti-instance-debootstrap
sudo apt-get install --no-install-recommends ganeti-os-noop
sudo apt-get install --no-install-recommends qemu-kvm

On n'installe pas les paquets recommandés parce que ça tire la moitié du support d'interface graphique de Debian...

Configuration du cluster

Il faut déjà créer un Volume Group LVM pour stocker les disques des VM.

Ensuite, Ganeti a besoin d'une IP "virtuelle" avec un nom DNS associé. C'est une IP qui va toujours pointer sur le serveur "master" lorsqu'on a plusieurs serveurs dans un cluster. Cette IP va être ajoutée par Ganeti sur l'interface qui sert à communiquer avec les autres serveurs Ganeti.

Chez nous, le nom du cluster est flotte.grenode.net, défini dans /etc/hosts, et l'interface master est le bridge br-grenode.

On utilise également une autre interface bridge br-devnull qui n'est reliée à rien. Cela permet d'isoler complètement le réseau d'une VM si nécessaire. On configure ce bridge par défaut lors de la création d'une VM pour éviter les erreurs.

Pour initialiser le cluster :

export volumegroup="vms"
export master_interface="br-grenode"
export vm_interface="br-devnull"
sudo gnt-cluster init --vg-name $volumegroup --master-netdev $master_interface --nic-parameters link=$vm_interface --enabled-hypervisors kvm --enabled-disk-templates plain,diskless flotte.grenode.net

On modifie ensuite certains paramètres du cluster (ça peut aussi être fait directement à l'initialisation).

Noyau des VM

Le paramètre kernel_path="" force KVM à booter les VM avec un noyau propre (par défaut, c'est le noyau de l'hyperviseur qui est utilisé…).

sudo gnt-cluster modify --hypervisor-parameters kvm:kernel_path=""

Port SSH des noeuds

Nos hyperviseurs écoutent sur un port SSH non-standard. Comme Ganeti exécute beaucoup d'opérations à travers SSH, il faut lui dire, même si on n'a qu'un seul noeud dans le cluster :

export ssh_port=4242
sudo gnt-cluster modify --node-parameters ssh_port=$ssh_port

Performance

Cf. https://code.google.com/p/ganeti/wiki/PerformanceTuning

Pour utiliser toutes les fonctionnalités du CPU (AES-NI, AVX, etc) dans les VM :

sudo gnt-cluster modify -H kvm:cpu_type=host

Attention, ça peut poser des problèmes lorsqu'on migre des VM sur des machines physiques qui ont des CPU différents. On n'a pas ce problème pour l'instant.

Allocateur de ressources

Ganeti est fait pour des clusters avec plusieurs noeuds, et les algorithmes d'allocation de ressources ont parfois du mal à fonctionner avec un seule noeud. Ça peut conduire à des erreurs à la création de VM comme par exemple :

Failure: prerequisites not met for this operation:
error type: insufficient_resources, error details:
Can't compute nodes using iallocator 'hail': Request failed: Group default (preferred): No valid allocation solutions, failure reasons: FailN1: 1

Le plus simple est de passer des options par défaut à l'allocateur pour désactiver ce genre de vérifications. Voir le man pour les options disponibles, en l'occurrence on peut utiliser :

sudo gnt-cluster modify --default-iallocator-params "-no-capacity-checks"

Les anciennes versions de Ganeti n'ont pas cette option, on peut utiliser l'option suivante à la place (assurez-vous quand même de savoir ce que vous faites) :

sudo gnt-cluster modify --default-iallocator-params "-ignore-soft-errors"

Configuration de debootstrap

Ganeti sait utiliser debootstrap pour installer le système des VM.

Ajout d'une variante d'OS

Pour comprendre comment ça marche, il est indispensable de lire /usr/share/doc/ganeti-instance-debootstrap/README.gz. Notamment, il y a un système de « variantes » assez bien fichu pour avoir plusieurs configurations debootstrap en parallèle, ça se passe dans /etc/ganeti/instance-bootstrap/.

Attention : bien penser à rajouter des paquets supplémentaires par rapport à ceux que debootstrap installe ! Par exemple, debootstrap n'installe pas de noyau par défaut… Dans /etc/ganeti/instance-bootstrap/variants/buster.conf :

ARCH="amd64"
SUITE="buster"
PARTITION_STYLE="msdos"
EXTRA_PKGS="acpi-support-base,udev,locales,linux-image-amd64,openssh-server,ssh,e2fsprogs,vim,htop"

Après avoir modifié cette configuration, il faut supprimer le cache debootstrap (/var/cache/ganeti-instance-debootstrap/*) pour que ce soit pris en compte à la prochaine création de VM.

Il y a également des hooks dans /etc/ganeti/instance-debootstrap/hooks/ qui configurent divers aspects de la VM en cours d'installation : grub, réseau, etc.

Hook de configuration de grub

Ce hook est nécessaire, sinon la VM ne bootera pas, faute d'avoir un grub fonctionnel.

TODO: mettre un lien vers le script.

Autres hooks

On peut pré-configurer d'autres choses : la locale, la timezone, le support ACPI pour que la VM réagisse aux signaux "shutdown" et "reboot", etc.

TODO: mettre des liens.

Création d'une nouvelle VM

Documentation : http://docs.ganeti.org/ganeti/2.15/html/admin.html#instance-management

Avec debootstrap

En supposant qu'une variante "buster" ait été créée précédemment, la commande gnt-instance add permet de créer une VM, ici avec 10 GB de disque et 1 GB de RAM, un disque ajouté au VG vms_hdd (disques rotationnels sur gaillard), et une interface réseau ajoutée au bridge br-rzn-205 :

gnt-instance add -o debootstrap+buster -t plain --disk 0:size=10G,vg=vms_hdd -B memory=1G --net=0:link=br-rzn-205 --no-name-check --no-ip-check $ma_vm

Sur certains hyperviseurs, d'autres VG peuvent être disponibles, par exemple vms_ssd sur gaillard qui est composé de SSD (voir sudo vgs pour obtenir la liste)

La première fois, ça va prendre quelques minutes (debootstrap). Ensuite, il y a un cache du système de fichiers créé par debootstrap, donc la création prend quelques secondes.

Pour finir la configuration, notamment réseau, il suffit de se connecter via la console :

gnt-instance console $ma_vm

On peut se logguer en root sans mot de passe. Attention du coup, bien penser à définir un mot de passe root !

Manuellement (debian-installer)

Une installation manuelle avec le debian-installer peut être utile si on veut chiffrer le disque de sa VM.

gnt-instance add -o noop -t plain -s 10G -B memory=1G --net=0:link=$mon_bridge --no-name-check --no-ip-check --no-start $ma_vm
gnt-instance modify -H vnc_bind_address="127.0.0.1" $ma_vm
gnt-instance start -H boot_order=cdrom,cdrom_image_path=$iso_path

Sur ?tillac, les ISO sont dans /srv/iso.

On se connecte ensuite en VNC via SSH (cf. ci-dessous) pour installer l'OS.

Accès aux VM

Démarrage et arrêt d'une VM

gnt-instance startup $ma_vm
gnt-instance shutdown $ma_vm
gnt-instance reboot $ma_vm

Note : Ganeti envoie un signal ACPI pour éteindre la VM, donc il faut que ce signal soit pris en compte. Sous Debian, le paquet à installer est acpi-support-base.

Accès en VNC

Pour chaque VM, qemu configure un accès VNC sur un port TCP dédié, qui écoute sur localhost. Pour connaître ce port :

gnt-instance list -o +network_port

Il faut donc faire un tunnel SSH vers ce port pour se connecter en VNC :

ssh -v -N -L 4444:127.0.0.1:110XX $hyperviseur

Ensuite, diriger son client VNC vers localhost, port 4444.

Si on n'aime pas VNC, il est possible de désactiver l'accès VNC pour une VM :

gnt-instance modify -H vnc_bind_address="" $ma_vm
gnt-instance reboot $ma_vm

Si jamais on veut le réactiver par la suite :

gnt-instance modify -H vnc_bind_address="127.0.0.1" $ma_vm
gnt-instance reboot $ma_vm

Accès par port série

Il peut aussi être pratique d'avoir accès à une VM via un port série depuis l'hôte.

Pour une VM sous Debian wheezy, il faut installer le paquet console-tools.

Pour une VM utilisant systemd (Debian jessie ou supérieur), la console est gérée par systemd :

systemctl enable serial-getty@ttyS0.service
systemctl start serial-getty@ttyS0.service

Ensuite, pour accéder au port série depuis l'hôte :

gnt-instance console $ma_vm

Si on veut aussi avoir grub sur le port série, il faut changer la configuration de grub dans /etc/default/grub :

GRUB_TERMINAL="console serial"

De même, pour avoir les messages du noyau sur le port série, c'est également dans /etc/default/grub :

GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0"

Ne pas oublier de lancer update-grub dans la VM après avoir modifié ce fichier.

Boot sur image CD

Il peut être pratique de booter sur une image CD, par exemple pour utiliesr le mode "rescue" de l'installeur Debian. Par exemple :

gnt-instance start -H cdrom_image_path=/srv/iso/debian-9.2.1-amd64-netinst.iso,boot_order=cdrom nom_de_la_vm

Il faut alors se connecter en VNC.

Gestion des VM

Ajout de RAM à une VM

gnt-instance modify -B memory=1024M $ma_vm

Il est ensuite nécessaire de rebooter la VM depuis Ganeti :

gnt-instance reboot $ma_vm

Lister les disques des VM

La commande suivante permet de lister les VM avec leur disque :

gnt-node volumes

C'est pratique pour avoir la correspondance volume LVM - machine, parce que les noms des volumes LVM ne sont pas humainement compréhensibles...

Modification ou ajout d'interface réseau à une VM

Ajout d'une interface réseau à une VM, ici connecté au bridge br-foo :

gnt-instance modify --hotplug --net add:link=br-foo $ma_vm

Changement de bridge pour une interface réseau (ici, changement pour la première interface, numérotée 0, et ajout de cette interface au bridge br-foo) :

gnt-instance modify --net 0:modify,link=br-foo $ma_vm

Par défaut, le changement s'applique au prochain reboot de la VM depuis l'hyperviseur. Pour appliquer la modification immédiatement, sachant que l'interface passera down dans la VM (il faut avoir une console série ou un autre moyen de joindre la VM), on utilise l'option --hotplug:

gnt-instance modify --hotplug --net 0:modify,link=br-foo $ma_vm

Suppression d'une interface réseau, ici la deuxième interface de la VM (eth1/ens6) :

gnt-instance modify --hotplug --net 1:remove $ma_vm

Note : il n'est pas possible de supprimer la NIC 0 d'une VM. Du coup, il existe un bridge br-devnull dans lequel on peut mettre la VM, qui n'est relié à rien.

Changer le VG d'une VM

Si un cluster a plusieurs VG (un en SSD et un en disque rotationnel), on peut vouloir déplacer un disque de machine virtuelle d'un VG à un autre. La méthode consiste à copier les données entre les deux VG, puis changer la configuration de Ganeti à la main. Une méthode plus simple serait la bienvenue.

On suppose qu'on veut déplacer un disque de VM depuis le VG vms_hdd (source) vers le VG vms_ssd (destination).

Repérer le nom du LV du disque à bouger (de la forme "$uuid.disk0") :

gnt-node volumes

Eteindre la VM :

gnt-instance stop $ma_vm

Créer le LV dans le nouveau VG, avec le même nom que l'ancien :

lvcreate -n ${uuid}.disk0 -L ${size} vms_ssd

Pour être certain de la taille, utiliser lvdisplay sur le nom du disque.

Copier les données de l'ancien LV vers le nouveau LV :

dd if=/dev/vms_hdd/${uuid}.disk0 of=/dev/vms_ssd/${uuid}.disk0 bs=2M

Editer la configuration de ganeti, pour remplacer vms_hdd/{$uuid}.disk0 par vms_ssd/{$uuid}.disk0 :

service ganeti stop
vim /var/lib/ganeti/config.data
service ganeti start

Rallumer la VM sur son nouveau disque, et vérifier que tout fonctionne bien dessus :

gnt-instance start $ma_vm

Après une dernière vérification, supprimer l'ancien LV :

gnt-node volumes
lvs
lvremove vms_hdd/${uuid}.disk0

Agrandir le disque d'une VM

Pour ajouter 10 GB de disque à une VM :

gnt-instance grow-disk $ma_vm 0 10g

"0" est l'identifiant du disque. Attention, regarder le numéro adéquat avec par exemple :

gnt-instance list -o name,os,status,oper_ram,disk.count,disk.size/0,disk.size/1

Après un reboot (reboot depuis l'hyperviseur pas depuis l'intérieur de la VM), on peut agrandir le système de fichiers dans la VM :

fsadm resize /dev/vda1

Si il y a une table de partition dans la VM, il faut d'abord agrandir la partition correspondante, par exemple avec cfdisk.

Une méthode "barbare" consiste à supprimer la partition et à la recréer avec la nouvelle taille, en s'assurant qu'elle commence bien au même endroit et qu'elle a le même type…

Depuis Debian stretch, il est possible d'installer le paquet « cloud-guest-utils » dans la VM, et ainsi utiliser la commande growpart /dev/vda 1.

Cas d'un serveur avec LUKS+LVM

Exemple Ilico

Si vous avez suivi l'install par défaut d'une Debian Jessie avec LUKS+LVM, la procédure est un peu différente.

# lsblk -f /dev/vda
NAME                   FSTYPE      LABEL UUID                                   MOUNTPOINT
vda
├─vda1                 ext2              xxxxxxxxxxxxxxxxxxxxxxxx               /boot
├─vda2
└─vda5                 crypto_LUKS       xxxxxxxxxxxxxxxxxxxxxxxx
  └─vda5_crypt         LVM2_member       xxxxxxxxxxxxxxxxxxxxxxxx
    └─tourton--vg-root ext4              xxxxxxxxxxxxxxxxxxxxxxxx               /

Il faut d'abord étendre vda2, puis vda5, puis vda5_crypt puis le fs en ext4.

parted /dev/vda

(parted) resizepart 2
End? [160GB]? <entrez la taille désirée>

On effectue la même opération pour la partition vda5 :

parted /dev/vda

(parted) resizepart 5
End? [160GB]? <entrez la taille désirée>

Il faut maintenant étendre au niveau LUKS avec cryptsetup, puis le PV et enfin le LV :

cryptsetup resize vda5_crypt
pvresize /dev/mapper/vda5_crypt
pvchange -x y /dev/mapper/vda5_crypt
lvresize -l +100%FREE /dev/tourton-vg/root
pvchange -x n /dev/mapper/vda5_crypt

Enfin, on s'occupe du FS :

resize2fs -p /dev/mapper/tourton--vg-root

Et voilà, un redémarrage pour s'assurer que tout est OK et l'affaire est jouée.

Exemple Grésille

Une fois le disque agrandi sur l'hyperviseur, on va :

  1. changer la table de partition dans la VM (avec fdisk /dev/vdb) :
    • supprimer la partition puis
    • créer la partition en utilisant tout l'espace
  2. agrandir le disque chiffré (cryptsetup resize /dev/mapper/xvdb1_crypt)
  3. agrandir le PV (pvresize /dev/mapper/xvdb1_crypt)
  4. agrandir le LV (lvresize -L +35G -r /dev/coccinelle/web)

Réduire un disque

Ganeti ne supporte pas de base la réduction de disque. À Grésille, nous avons cependant eu le cas d'un disque agrandi par erreur, que nous avons réduit ensuite (le filesystem derrière n'ayant pas été agrandi).

On a fait comme ça, des fois que ça puisse (re)servir :

gnt-instance info <la machine>
# noter l'ID du disque dur (sans se tromper cette fois)
# et le chemin (/dev/vms/<ID>.diskX)
service ganeti stop
lvresize -L -<la taille> /dev/vms/<ID>.diskX
# faire une copie de sauvegarde de /var/lib/ganeti/config.data
cp /var/lib/ganeti/config.data  /root/backup-config.data

Ensuite, on édite /var/lib/ganeti/config.data pour modifier la taille du disque (en blocs de 1M). Il faut d'abord chercher l'id du disque, puis la size juste après. Ce qui donne par exemple :

{"logical_id":["vms","7e640c14-a5f6-476d-9cda-b767003cff33.disk0"],"dev_type":"plain","children":[],"nodes":["39395a09-dad8-43c5-aa82-a69da30e0702"],"iv_name":"disk/0","size":52224,"mode":"rw","params":{},"uuid":"4cc375b9-1c56-4240-af00-7514abcfc61a","serial_no":2,"ctime":1.474889243565636e9,"mtime":1.5117963326473444e9}

devient

{"logical_id":["vms","7e640c14-a5f6-476d-9cda-b767003cff33.disk0"],"dev_type":"plain","children":[],"nodes":["39395a09-dad8-43c5-aa82-a69da30e0702"],"iv_name":"disk/0","size":1024,"mode":"rw","params":{},"uuid":"4cc375b9-1c56-4240-af00-7514abcfc61a","serial_no":2,"ctime":1.474889243565636e9,"mtime":1.5117963326473444e9}

On redémarre ganeti :

service ganeti start

Enfin, on reboote la vm (pas un reboot dans la vm, shutdown puis démarrage depuis ganeti), et tout roule.

Savoir à quelle interface tap a été associée l'interface N de la vm INSTANCE

Ça se trouve dans /var/run/ganeti/kvm-hypervisor/nic/$INSTANCE/$N

Export d'une VM existante

Avant l'export, sur l'hyperviseur

Il faut disposer d'un espace de stockage suffisant sur l'hyperviseur pour recevoir l'export de la VM. Chez Grenode les partitions root des hyperviseurs ne font quelques 10ène de gigaoctets et ne sont pas adaptées à recevoir un export de VM.

On crée donc un volume logique temporaire pour accueillir notre export:

lvcreate -L500G -n tmp_transfer vms
mkfs.ext4 /dev/vms/tmp_transfer
mount /dev/vms/tmp_transfer /var/lib/ganeti/export/

Étrangement, Ganeti ne semble pas posséder d'options permetant de choisir le répertoire d'export. Les exports sont placés dans /var/lib/ganeti/export. On monte donc notre volume temporaire sur cet emplacement.

Export de la VM

Pour lancer l'export à chaud :

gnt-backup export -n $hyperviseur --noshutdown $ma_vm

On peut ensuite récupérer les fichiers dans /var/lib/ganeti/export/$mavm

Ménage post export

Une fois la VM récupérée, on supprime l'export et le volume logique temporaire:

umount /var/lib/ganeti/export
lvremove /dev/vms/tmp_transfer

Migration inter-cluster

http://docs.ganeti.org/ganeti/master/html/move-instance.html

Préparatation des clusters

dépendance pour la compression des données

Sur tous les clusters :

gnt-cluster command apt-get install -y lzop

cluster domain secret

C'est un secret à partager dans un même domaine ganeti (plusieurs cluster). Il se trouve dans le fichier /var/lib/ganeti/cluster-domain-secret.

  • copier /var/lib/ganeti/cluster-domain-secret du cluster source sur le cluster destination.
  • et lancer gnt-cluster renew-crypto --cluster-domain-secret=/root/cluster-domain-secret

Créer un compte sur rapi

Le script de déplacement d'une vm intercluster a besoin d'avoir accès à RAPI des deux cotés. Pour le créer des utilisateurs et mot de passe voir :

http://docs.ganeti.org/ganeti/current/html/rapi.html#users-and-passwords

Penser à propager le fichier avec gnt-cluster copyfile

Et mettre les mots de passe dans des fichiers sur le compte root sur la destination.

Copier le certificat rapi source sur le cluster destination

Il se trouve dans /var/lib/ganeti/rapi.pem

Déplacer une machine entre les deux clusters

Sur le cluster source, passer la machine avec l'os noop avant, sinon certains hooks sont lancés et plante manifestement.

VM_FQDN=example.grenode.net
gnt-instance modify -o noop $VM_FQDN

S'assurer également que la console fonctionne

gnt-instance console $VM_FQDN

Sur le master destination :

SRC_CLUSTER=flotte.grenode.net
DEST_CLUSTER=flotte-gre.grenode.net
VM_FQDN=
/usr/share/ganeti/2.15/move-instance \
        --src-ca-file /root/src-rapi.pem \
        --src-username grenode \
        --src-password-file /root/src-rapi.password \
        --dest-ca-file /var/lib/ganeti/rapi.pem \
        --dest-username grenode \
        --dest-password-file /root/dest-rapi.password \
        $SRC_CLUSTER $DEST_CLUSTER $VM_FQDN \
        --verbose
  1. La nouvelle vm est préparée sur le cluster destination
  2. La vm actuelle est éteinte sur le cluster source
  3. La copie des données est lancée
  4. La nouvelle vm est lancée sur le cluster destination
  5. La vm actuelle (mais ancienne) est supprimé sur le cluster source (seulement si tout se passe bien...)

Par défaut, la configuration de la VM est conservée : RAM, CPU, interfaces réseau, etc. Ça suppose que les bridges aient le même nom sur les deux clusters. Si ce n'est pas le cas, ajouter la configuration réseau à la commande ci-dessus :

--net 0:link=br-XXX

Par ailleurs, si le réseau n'est pas très rapide, on peut ajouter :

--compress gzip-fast

Problèmes

Changement de nom d'interface réseau

Lorsqu'on migre une VM entre un vieux cluster et un nouveau cluster, le nom d'interface réseau des VM peut changer :

  • hyperviseur jessie, qemu 2.1: ens5, ens6, etc
  • hyperviseur stretch, qemu 2.8: ens5, ens6, etc
  • hyperviseur buster, qemu 3.1: ens13, ens14, etc

Pour gérer ça, il faut soit modifier la configuration réseau de la VM avant de la migrer, soit s'y connecter via la console série ou VNC. Dans les deux cas, il faut s'assurer d'avoir un accès console si on se plante...

I/O très lentes sur le cluster de destination

La copie sur la cluster de destination utilise dd avec l'option dsync, ce qui est très lent : https://github.com/grnet/ganeti-os-noop/blob/master/ganeti/os/noop/import

Hack simple : modifier /usr/share/ganeti/os/noop/import sur la machine de destination :

dd of="$IMPORT_DEVICE" conv=nocreat,notrunc,fdatasync bs=1048576

fdatasync est utile pour s'assurer que tout a bien été écrit sur le disque à la fin de la copie.

socat & cluster en jessie-backports / cluster en stretch

Entre autre : https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=871771

Sur stretch :

diff -u -r old/etc/ganeti/share/ganeti/impexpd/__init__.py new/etc/ganeti/share/ganeti/impexpd/__init__.py
--- old/etc/ganeti/share/ganeti/impexpd/__init__.py 2018-02-28 21:03:45.152292871 +0100
+++ new/etc/ganeti/share/ganeti/impexpd/__init__.py 2018-02-28 21:02:52.513463188 +0100
@@ -88,7 +88,7 @@

 # Common options for socat
 SOCAT_TCP_OPTS = ["keepalive", "keepidle=60", "keepintvl=10", "keepcnt=5"]
-SOCAT_OPENSSL_OPTS = ["verify=1", "cipher=%s" % constants.OPENSSL_CIPHERS]
+SOCAT_OPENSSL_OPTS = ["verify=0", "cipher=%s" % constants.OPENSSL_CIPHERS]

 if constants.SOCAT_USE_COMPRESS:
   # Disables all compression in by OpenSSL. Only supported in patched versions

puis :

gnt-cluster copyfile /etc/ganeti/share/ganeti/impexpd/__init__.py

Sur jessie-backports :

diff -u -r old/etc/ganeti/share/ganeti/impexpd/__init__.py new/etc/ganeti/share/ganeti/impexpd/__init__.py
--- old/etc/ganeti/share/ganeti/impexpd/__init__.py 2018-02-28 21:03:45.152292871 +0100
+++ new/etc/ganeti/share/ganeti/impexpd/__init__.py 2018-02-28 21:02:52.513463188 +0100
@@ -88,8 +88,7 @@

 # Common options for socat
 SOCAT_TCP_OPTS = ["keepalive", "keepidle=60", "keepintvl=10", "keepcnt=5"]
-SOCAT_OPENSSL_OPTS = ["verify=1", "method=TLSv1",
-                      "cipher=%s" % constants.OPENSSL_CIPHERS]
+SOCAT_OPENSSL_OPTS = ["verify=0", "cipher=%s" % constants.OPENSSL_CIPHERS]

 if constants.SOCAT_USE_COMPRESS:
   # Disables all compression in by OpenSSL. Only supported in patched versions

Puis :

gnt-cluster copyfile /etc/ganeti/share/ganeti/impexpd/__init__.py

Import d'une VM depuis Xen

Le but est de migrer une VM depuis rouf (qui tournait donc avec Xen) vers tillac.

Attention : cette doc date de 2016, et rouf tournait sous Debian wheezy. Il faut sûrement adapter certaines des commandes et options pour faire une telle migration aujourd'hui.

Avant la migration, sur la VM

Installer les paquets suivants dans la VM pour le support console série et ACPI :

apt-get install acpi-support-base               # Pour jessie, stretch, buster
apt-get install acpi-support-base console-tools # Pour wheezy

Pour stretch et suivants, adapter le nom de l'interface réseau dans /etc/network/interfaces. Le nom de l'interface réseau après migration sera probablement ens5. Le plus simple est de recopier la configuration réseau existante (en changeant eth0 en ens5) pour avoir du réseau fonctionnel avant et après la migration. Wheezy et jessie n'ont pas ce problème, l'interface s'appelera toujours eth0 après migration.

Adapter si besoin le résolveur DNS (/etc/resolv.conf), la gateway réseau, etc.

Enfin, s'assurer que Grub est bien installé et configuré :

apt-get install grub-pc
update-grub
grub-install /dev/vda # à adapter

Si grub est mal installé, la VM ne démarrera pas sur le nouvel hyperviseur. Il est cependant possible de réinstaller Grub après la migration, au prix de quelques efforts.

Si le disque de la VM n'a pas de table de partition, c'est compliqué parce qu'il n'est alors pas possible d'installer grub... Passer directement à la partie "Migrer une VM qui n'a pas de table de partitions".

Avant la migration, sur le futur hyperviseur

Il est nécessaire de créer les bridges sur l'hyperviseur et s'assurer que les VLAN fonctionnent comme il faut. Repérer également quel VG LVM est le plus pertinent.

Copie du disque : méthode basique

Avec la méthode basique :

  • on éteint la VM sur l'ancien hyperviseur
  • on copie l'intégralité du disque par le réseau
  • on rallume la VM sur le nouvel hyperviseur

Ce n'est donc pas adapté si le disque de la VM est gros, ou bien si le réseau entre les deux hyperviseurs est lent.

Commencer par créer le volume logique sur le nouvel hyperviseur, de même taille que l'ancien :

lvcreate -n vm-disk -L 25G vms

Ensuite lancer la copie sur l'ancien hyperviseur :

dd if=/dev/domU/vm-disk bs=1M | pv --size 25G | ssh root@tillac.grenode.net "dd of=/dev/vms/vm-disk bs=1M"

Méthode plus avancée, avec de la compression (utile si le réseau est lent) et une limitation du débit à 950 Ko/s (utile pour ne pas saturer le réseau) :

dd if=/dev/domU/vm-disk bs=1M | pv --size 25G | lzop | pv -q -L 950K | ssh root@tillac.grenode.net "lzop -d | dd of=/dev/vms/vm-disk bs=1M"

Copie du disque : utilisation de lvmsync

Avec cette méthode, on peut copier le disque alors que la VM tourne encore sur l'ancien hyperviseur.

Installation

Il faut installer lvmsync sur le serveur source & destination :

sudo apt-get install ruby
sudo gem install lvmsync

Ca va installer le binaire dans /usr/local/bin/, vérifier que c'est dans le PATH.

lvmsync utilise rsync via ssh. Il faut donc aussi s'assurer que le serveur source est capable de se connecter en ssh sur le compte root du serveur de destination.

Copie initiale

Il faut créer un snapshot lvm sur le serveur source. La taille du snapshot doit être suffisante pour accepter les écritures le temps de la copie : un bon ordre de grandeur est 10% de la taille totale.

lvcreate -n coccinelle-disk-snapshot -L 20G -s /dev/domU/coccinelle-disk

Sur le serveur destination, il faut créer le volume logique lvm de destination, de même taille que l'original :

lvcreate -n coccinelle-disk -L 250G vms

Pendant que la vm est en cours de fonctionnement on peut donc copier les données du snapshot. Depuis le serveur source :

dd if=/dev/domU/coccinelle-disk-snapshot bs=8M | pv --size 250G | ssh destination.grenode.net "dd of=/dev/vms/coccinelle-disk bs=8M"

On peut répéter cela pour chacun des volumes disques de la vm.

Synchronisation finale

On peut maintenant éteindre la VM et terminer la migration des données.

S'assurer que la VM est bien éteinte, puis lancer depuis le serveur source :

lvmsync /dev/domU/coccinelle-disk-snapshot  destination.grenode.net:/dev/vms/coccinelle-disk

Une fois la copie des volumes disques finie, on peut continuer sur la création de l'instance ganeti.

Import de la VM dans Ganeti

Il est d'abord nécessaire d'installer le paquet ganeti-os-noop.

Puis pour créer la VM, ça ressemble à une création normale mais on "adopte" le volume logique LVM $nom_du_lv :

gnt-instance add -n "$hyperviseur" -o noop -t plain --disk 0:adopt="$nom_du_lv" -B memory="512M",vcpus="1" --net=0:link="$mon_bridge" --no-name-check --no-ip-check --no-start $nom_de_la_vm

Pour une raison obscure d'allocation, il est nécessaire de passer en argument (-n) le nom du noeud courant.

Optionnel : réinstaller grub

Si grub n'est pas installé ou mal installé dans le MBR, la VM ne pourra pas booter.

Pour réinstaller Grub, on boote sur une image CD Debian :

gnt-instance start -H cdrom_image_path=/srv/iso/debian-9.2.1-amd64-netinst.iso,boot_order=cdrom nom_de_la_vm

Le menu de boot du CD devrait être accessible en VNC.

  • dans les options avancées, choisir "rescue mode"
  • avancer dans les étapes, ne pas configurer le réseau
  • choisir la partition contenant la racine du système de fichiers
  • choisir "réinstaller grub" et entrer le nom du disque (quelque chose comme /dev/vda)
  • rebooter

Relancer la VM sans CD, elle devrait booter normalement.

Script de migration

Un script de migration qui reprend ces étapes est disponible : migrate vm from xen.sh

Limitations :

  • n'utilise pas lvmsync (à éviter pour les grosses VM)
  • ne supporte pas plusieurs disques par VM

Après la migration

  • Si la migration se passe mal, essayer d'accéder à la VM avec la console série ou le VNC.

  • Il est possible que la console ne fonctionne pas. Vérifier alors dans la configuration de grub qu'il n'y ait pas de console=hvc0 dans les options de linux et penser à configurer la console serie (cf. plus haut).

Migrer une VM qui n'a pas de table de partitions

Si le disque de la VM n'a pas de table de partitions, il faut adapter toutes les étapes :

  • sur le nouvel hyperviseur, créer une partition légèrement plus grande (25.1 GB au lieu de 25 GB)

  • créer une table de partition, avec une unique partition :

    fdisk /dev/vms/vm-disk n w

  • mapper cette nouvelle partition pour pouvoir y accéder depuis l'hyperviseur :

    kpartx -av /dev/vms/vm-disk

  • copier le disque de la VM avec la méthode basique ou lvmsync, mais en copiant vers /dev/vms/vm-disk1 (partition créée précédemment)

  • enlever le mapping :

    kpartx -dv /dev/vms/vm-disk

  • installer grub avec un CD Debian en "rescue mode" (cf. ci-dessus)