Nous savons qu’une coupure électrique peut survenir à la maison et même dans un datacenter avec des onduleurs mais quand aucun signe d’extinction nous prévient, c’est souvent le drame.

Pour des novices comme pour des experts, il est fort possible qu’essayer d’offrir de nouveau la disponibilité de leur Cloud à leurs utilisateurs puisse être un vrai casse-tête.

Dans cet article, nous allons voir une méthode de remise en état d’un cloud OpenStack.

Public visé : Administrateurs systèmes, Administrateur OpenStack, Utilisateurs OpenStack

Par Christophe Useinovic, Consultant Cloud @Objectif Libre

Que faire en cas de panne totale d’un cluster OpenStack ?

OpenStack, une boite noire ?

OpenStack n’est pas une grosse boite noire, il est composé de plusieurs services. Certains plus critiques que d’autres.
Dans les explications que je vais amener dans de cette article, notre infrastructure sera composée de 3 nœuds contrôleur.

Les composants de bases installés sont:
– Keepalived
– SQL / MariaDB
– RabbitMQ-server
– Haproxy
– Les composants OpenStack

Vous pouvez retrouver la documentation officielle sur l’architecture et les différents composants  sur le site OpenStack

Nous allons maintenant regarder en détail plusieurs composants principaux  pour la remise en état du cluster OpenStack.

Keepalived

Pour rappel, ce composant nous permet de définir une IP virtuelle qui sera présente sur un des trois contrôleur. Si l’un des
contrôleur ayant l’interface de la VIP qui ne répond plus alors cette VIP va basculer sur un des nœuds disponible et continuer à rendre le service.
Cette VIP sera utilisée pour la partie frontend de notre HAproxy. Nous retrouvons deux VIP, une pour les services Openstack et l’autre pour la partie BD.

On peut retrouver la configuration de la VIP BD dans /etc/keepalived/keepalived.conf

$ cat /etc/keepalived/keepaliverd.conf
[...]
vrrp_instance vrrp_db {
  interface enp1s0.100
  virtual_router_id 1
  priority 100
  nopreempt
  authentication {
    auth_type PASS
    auth_pass supermotdepasse
  }
  track_script {
    check_mysql 
  }
  virtual_ipaddress {
    172.10.10.5
  }
}
[...]

Lors d’un crash total, il est possible que cette VIP remonte mal sur l’interface.

Dans ce cas un simple ping de la VIP et une vérification des interfaces nous permet de vérifier sa présence.

$ ping 172.10.10.5

$ ip -c -4 a | grep 172.10.10.5
 
$ ip -c -4 a |grep enp1s0.100 

  6: enp1s0.100@enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
  inet 172.10.100.7/24 brd 172.20.100.255 scope global enp1s0.100
  valid_lft forever preferred_lft forever

si ce n’est pas le cas un restart des 3 services keepalived sur les controlleurs suffit.

$ sudo systemctl restart keepalived

et de nouveau revérifier sa présence.

$ ip -c -4 a |grep enp1s0.100 

  6: enp1s0.100@enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
  inet 172.10.100.7/24 brd 172.20.100.255 scope global enp1s0.100
  valid_lft forever preferred_lft forever
  inet 172.10.10.5/32 scope global enp1s0.100
  valid_lft forever preferred_lft forever

MySQL / MariaDB

Le plus critique est évidemment la base de données. La fondation OpenStack préconise une utilisation de mariadb/Galera afin de mettre en place un cluster.

Dans ce scénario, une perte totale de quorum s’est produite et le cluster n’accepte aucune requête SQL. Après un crash brutal comme celui-ci même si les nœuds redémarrent, le service MariaDB ne pourra pas démarrer. Aucun nœud n’a pu effectuer la dernière validation de donnée.

Il y a deux méthodes de remise en route de notre cluster:

  • Récupération basée sur la valeur seqno la plus élevée
  • Récupération basée sur le dernier engagement

Selon la nature du crash, soit tous les nœuds auront une valeur seqno négative identique, soit l’un des nœuds aura la valeur seqno positive la plus élevée.
Après un arrêt brutal, il y a peu de chance qu’on puisse repartir sur la première méthode, je vais présenter alors la seconde.

C’est le pire scénario car tous les nœuds se sont complètement éteints et pas d’une bonne manière ce qui provoque une valeur seqno de -1.

La commande galera_new_cluster nous permet de créer un nouveau cluster avec un ensemble d’ID, ensuite les autres nœuds se joignent à lui.

Avant de lancer la commande sur un nœud, il faut repérer quel nœud à le dernier commit grâce à la valeur wsrep_last_commit.
Nous avons besoin de modifier la configuration de chaque nœud de mariadb pour lancer le service

$ sudo systemctl stop mariadb
$ sudo vi /etc/mysql/conf.d/mariadb.cnf
  [galera]
  wsrep_cluster_address = "gcomm: //"
  systemctl start mariadb

Connectez vous à votre base de donnée et vérifier la valeur suivante :

$ show status like 'wsrep_last_committed';

Répétez l’opération sur les deux nœuds restants et notez le serveur ayant la valeur la plus élevée.

Remettez la valeur de wsrep_cluster_address de nouveau dans le fichier de mariadb:

$ sudo systemctl stop mariadb
$ sudo vi /etc/mysql/conf.d/mariadb.cnf
  [galera]
  wsrep_cluster_address = "gcomm: //IP1, IP2, IP3"

Sur le noeud avec la valeur la plus élevée, lancer la commande de cluster:

$ sudo galera_new_cluster

Une fois que le service est démarré, il suffit de démarrer un par un les services mariadb sur les deux autres serveurs.

Pour vérifier que la synchro est faite, vous pouvez vérifier les services mais aussi en base :

$ show status like '%wsrep_inco%';

+--------------------------+-------------------------------------------------------+
| Variable_name            | Value                                                 |
+--------------------------+-------------------------------------------------------+
| wsrep_incoming_addresses | 172.20.100.9:3306,172.20.100.7:3306,172.20.100.8:3306 |
+--------------------------+-------------------------------------------------------+

$ show status like '%wsrep_cluster_size%';

+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| wsrep_cluster_size | 3     |
+--------------------+-------+

RabbitMQ

De la même manière que notre base de donnée, ce composant est l’élément clé qui permet la communications entre les différents composants de notre OpenStack par le biais de files de messages AMQP.
Nous avons nos services RabbitMQ en cluster sur les trois controlleurs. il faut aller vérifier que les services de cluster fonctionne correctement.

$ sudo rabbitmqctl cluster_status

La sortie de la commande va nous sortir probablement une erreur. Ne partez pas de votre chaise encore, on va regarder ça ensemble.

Sur le premier contrôleur, on va arrêter le service et le relancer.

$ sudo systemctl stop rabbitmq-server 
$ sudo systemctl start rabbitmq-server

S’il refuse de s’éteindre, on va lancer la commande pkill pour l’éteindre.

$ sudo pkill -KILL -u rabbitmq
$ sudo systemctl start rabbitmq-server

Si le service démarre on peut relancer la commande rabbitmqctl cluster_status pour vérifier l’état du cluster.

Si cela ne fonctionne toujours pas, il y a la possibilité d’éteindre les trois service rabbitMQ et de les démarrer en même temps.

for i in {1..3} do; echo controlleur $i; ssh controller-$i -C "sudo systemctl stop rabbitmq-server"; done 
for i in {1..3} do; echo controlleur $i; ssh controller-$i -C "sudo systemctl start rabbitmq-server"; done

Si cela n’a toujours pas fonctionné, on peut supprimer le répertoire /var/lib/rabbitmq/mnesia/ qui contient les données de files de messages, de files d’échanges etc qui ne sont pas synchronisés entre les différents nœuds.

Les files de messages qui sont remplis vont être supprimés, les demandes utilisateurs sur les API OpenStack seront en echec.

$ sudo rm -rf /var/lib/rabbitmq/mnesia/*
$ sudo systemctl start rabbitmq-server

Vérification du cluster

$ sudo rabbitmqctl cluster_status

Pour plus d’informations sur la partie HA et recovery de RabbitMQ je vous invite à regarder cette page : https://www.rabbitmq.com/blog/2020/07/07/disaster-recovery-and-high-availability-101/

Services OpenStack

A ce stade, vous avez les services nécessaires au fonctionnement de votre OpenStack opérationnels ! On peut être content de nous.

Maintenant il faut regarder nos différents composants keystone, nova, neutron et de les redémarrer si la connexion à MariaDB ou à RabbitMQ a été trop longtemps attendu et a donc échoué.

Sans rentrer dans le détails de chaque composants OpenStack, avec ce qui a été présenté vous avez maintenant la possibilité de remettre en état de marche un OpenStack qui a été éteint de manière impromptu.

En complément voici une liste de commandes utile afin d’identifier rapidement quel composant n’est pas en bonne forme.

$ openstack token issue # vérification de Keystone
$ openstack compute service list # vérification des services Nova
$ openstack network agent list # vérification des services Neutron 
$ openstack volume service list # vérification des services Cinder
$ openstack orchestration service list # vérification des services Heat

 

Clap de fin ! 

J’espère qu’avec cet article j’ai pu vous aider à vous en sortir si vous êtes dans un cas similaire ou tout simplement vous apporter de nouvelles connaissances techniques.

Si vous avez d’autres problèmes au sein de votre OpenStack, vous pouvez vous référer à ces liens que je vous cite ci-dessous:

Les sites incontournables :

Ressource de discussion:

Pour compléter l’article, je vous conseille la lecture de ce livre chez Packt que j’ai pu découvrir lors de ma préparation à la certification OpenStack : openstack cloud computing cookbook 

Merci pour votre lecture !