MariaDB et Galera

MariaDB et Galera jpp

J'ai décidé de faire un test de la dernière version de MariaDB associée à Galera, non ce n'est pas la galère, puis y associer Maxscale.  
Ceci nécessite une certaine infrastucture (ici réalisée avec des machines virtuelles KVM) : 

  • 1 machine pour Maxscale  
    3 machines pour MariaDB/Galera 

Pourquoi trois machines ? 
Parce que avec seulement deux machines un système plus simple est possible et qu'un système comme Galera se comporte mieux avec 3 machines car cela permet d'éviter des duels fratricides en cas d'incident sur une des machines ce que les anglicistes nomment "split brain" et je n'ai pas de traduction sensée à fournir !  

Le test de Maxscale est repoussé car bien que IPV6 soit inhibé ici, le module de traitement "lecture seule" cherche un utilisateur avec une adresse "bizarre" de style "IPV6" et refuse donc la connexion. 
L'accès lecture/écriture, lui, fonctionne fort bien mais je voudrais trouver l'explication de ces adresses "fantaisie" pour le module lecture-seule avant de passer à des tests complets. 
Je n'ai pas réglé ce problème pseudo "IPv6", mais après une mise à jour cela ne semble plus se produire ... 
 

Installation machines BDD

Installation machines BDD jpp

Préambule.

Les configurations suivantes sont adoptées, elles sont "légères" mais largement suffisantes pour nos tests :     
  - GALE_1 : future machine "Maxscale"     
    Disque 40GB     
    Mémoire 2048M     
    2 VCPU     
 - GALE-2, GALE-3 et GALE-4 nos trois machines bases de données :     
    Disque 40GB     
    Mémoire 4096M     
    2 VCPU     
Le partitionnement adopté, volontairement simple, est suffisant pour des tests :     
   /boot 656Mo     
   / 36Go     
   Swap 3,5Go

Les deux premières machines ont été installées "normalement" à partir d'une image ISO, les machines 3 et 4 ont été "clonées" depuis la machine 2 après l'installation de la base de données et les premiers tests de validation. "dd" est un bon ami.

Installation.     
Il faut commencer par installer la définition du repository spécifique à MariaDB qui installe tout ce qu'il faut pour MariaDB, Maxscale et quelques outils complémentaires.     
- Commencer par installer les outils curl, net-tools, vim ou gvim-gtk3 ...     
Pour pouvoir ensuite installer, valider, suivre et mettre à jour confortablement tout ce qu'il faut pour un système "normal".     
- Installer le repository MariaDB :     
curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | sudo bash     
Ce script gère tout, y compris un "apt update" pour mettre à jour les listes de paquets.      
Comme les machines sont installées en Debian Bullseye on est limité aux versions 10.5 de MariaDB, 22.08 de Maxscale et Galera 3 ou 4 (on utilisera bien sûr la version 4).     
- On installe ici (GALE-2) MariaDB et Galera :     
apt install mariadb-client-10.5 mariadb-server-10.5 galera-4     
Cela récupère un paquet de dépendances : #28Mo d'archives et promet d'occuper 213MO sur disque.     
Après le fatidique "sysctl start mariadb" tout se passe bien !    
Lancée sous "root" la commande "mysql" nous lance gentiment le client connecté à notre nouvelle base.      
On peut alors mettre un mot de passe à l'utilisateur "root", limité à localhost et créer un compte spécifique d'administration avec une visibilité plus importante (/24 par exemple). Bien le faire avant le clonage de GALE-2 sur les deux machines suivantes.

Le système "modèle" est prêt et on peut le cloner dans les deux autres machines, il suffira de changer :     
- hostname      /etc/hostname     
- IP                  /etc/network.interfaces IP statiques    
et pour la base MariaDB.     
- server_id      /etc/mysql/mariadb.conf.d/50-server.cnf      
y mettre 2,3 et 4, les numéros de nostrois  braves machines.     
Maintenant que nos trois machines bases de données sont prêtes on va pouvoir passer à la mise en service de Galera ce qui promet d'être plus amusant.

Avant de se lancer dans Galera proprement dit il vaut mieux "arranger un peu" la configuration de MariaDB. 
Par exemple mettre les fichiers "binlog" ailleurs que dans /var/log/mariadb ! 
J'ai donc ici créé un répertoire /var/lib/binlogs : 
mkdir /var/lib/binlogs 
chown mysql: /var/lib/binlogs 
et modifié en conséquence le fichier /etc/mysql/mariadb.conf.d/50-server.cnf. 
 

Galera en route

Galera en route jpp

Pour Galera le fichier de paramétrage est /etc/mysql/mariadb.conf.d/60-galera.cnf, voir ci-dessous mon paramétrage :

#
# * Galera-related settings
#
[galera]
# Mandatory settings
wsrep_on                 = ON
wsrep_provider           = "/usr/lib/libgalera_smm.so"
wsrep_cluster_name       = "clustertest"
#
wsrep_node_name          = gale-2
wsrep-node-address	 = 192.168.2.153
#
wsrep_cluster_address    = "gcomm://192.168.2.153,192.168.2.154,192.168.2.155"
binlog_format            = row
default_storage_engine   = InnoDB
innodb_autoinc_lock_mode = 2
# Allow server to accept connections on all interfaces.
bind-address = 0.0.0.0
# Optional settings
wsrep_slave_threads = 1
innodb_flush_log_at_trx_commit = 0
# pour restart si cluster planté
wsrep_provider_options="gcache.recover=yes"

Pour le premier lancement il faut impérativement utiliser la commande suivante : 
mysqld --wsrep-new-cluster 
sur chacun des trois membres du cluster.  
Malheureusement cette commande ne "rends pas la main" j'ai donc du passer par la suite de commandes suivantes : 
mysqladmin shutdown 
systemctl start mariadb 
pour "rendre la main" et démarrer normalement, j'ai fait cela sur chacun des nœuds en laissant un petit temps intermédiaire pour laisser les machines se re-synchroniser.

Pour contrôle je crée une base : 
CREATE DATABASE montest; 
Et je vérifie qu'elle est bien créée sur les trois nœuds, youpi cette base existe bien partout ... c'est le pied. 
De même la création d'une table de test est parfaitement répliquée sur les trois nœuds : 
Create Table: CREATE TABLE `TT` ( 
 `ID` bigint(20) NOT NULL AUTO_INCREMENT, 
 `ZONE` varchar(32) DEFAULT NULL, 
 PRIMARY KEY (`ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

Vérifions maintenant l'insertion : 
Sur le nœud gale-2 (nœud 1) : 
insert into TT (ZONE) values ('UN'); 
Sur les deux autres nœuds on voit :

select * from TT;
+----+------+
| ID | ZONE |
+----+------+
|  3 | UN   |
+----+------+

Tiens, l'autoincrement débute à 3 ? 
Voyons voir un insert sur le nœud gale-3 (nœud 2) : 
insert into TT (ZONE) values ('DEUX'); 
L'ID généré est égal à 5. 
Un insert sur le nœud gale-4 (nœud 3) : 
insert into TT (ZONE) values ('TROIS'); 
L'ID généré est égal à 7; 
Retour sur le nœud 1 qui génère un ID à 9; 
En bref cela à l'air de bien fonctionner ... 
On essaye un arrêt de toutes les machines machines, puis on les redémarre, et ... c'est la catastrophe, rien ne redémarre. 
Il faut chercher quel était le nœud "maître" en examinant les fichiers "grastate.dat" (dans /var/lib/mysql) et chercher celui qui possède la ligne "safe_to_bootstrap: 1". 
Ici c'est le nœud "gale-4" qui a été stoppé en dernier ... donc il doit pouvoir repartir car il est réputé le plus à jour. Si aucun fichier ne comporte cette mention (cas de crash simultané) il faudra en éditer un "à la main" et mettre la valeur à 0. Dans le cas précédent le noeud "gale-4" démarre normalement, les autres peuvent alors démarrer et se connecter au cluster.

Si la situation est réellement "sérieuse" (refus complet de démarrage) mettre à jour le fichier "/var/lib/mysql/grastate.dat" de la machine stoppée en dernier et y forcer la valeur 0 dans la ligne "safe_to_bootstrap:", les autres membres du cluster pourront alors être démarrés avec un simple "systemctl start mariadb".

Utilisation du paramètre "wsrep_provider_options="gcache.recover=yes" ne change rien ... par contre en utilisant la commande "galera_new_cluster" sur le nœud 4 celui-ci démarre normalement et le démarrage des deux autres est alors possible ... Ouf! Le cluster se comporte ensuite normalement et il est possible de démarrer les autres systèmes avec "systemctl start mariadb".  
La commande "galera_new_cluster" ne fonctionne directement que sur la dernière machine stoppée du cluster afin d'être sûr qu'aucune donnée ne sera perdue. 
Souvenez-vous de cette commande ... qui peut servir en cas d'incident grave ou pour des machines de test que l'on stoppe souvent. 
Sinon il faut aller s'intéresser au fichier "/var/lib/mysql/grastate.dat" et, éventuellement (si la dernière machine stoppée est hors-service) et y passer la valeur de "safe_to_bootstrap" de 0 à 1. Mais le risque sera de perdre les dernières données traitées avant l'arrêt de la dernière machine du cluster.

Le redémarrage d'un seul des membres de notre cluster se passe fort bien et chacun des autres nœuds note que ce membre a disparu : 
2022-11-01 18:01:03 0 [Note] WSREP:  cleaning up e713c304-9429 (tcp://192.168.2.155:4567) 
192.168.2.155 est l'adresse du membre qui s'est absenté, lorsqu'il redémarre il se signale et les deux autres membres constatent ce fait avec un message : 
2022-11-01 18:03:24 0 [Note] WSREP: Member 0.0 (gale-4) synced with group. 
Une fonction qui peut être utile pour signaler ce type d'événement est disponible dans le paramétrage de Galera :

wsrep_notify_cmd = 'une commande shell' 
Cette commande permet de signaler les événements importants. 
J'en ai installé une très simple sur le nœud GALE_2 : 
#!/bin/bash 
FLOG=/var/tmp/MSG.LOG 
DTT=$(date +%Y/%m/%d_%H:%M:%S) 
echo ${DTT}' | '$* >>${FLOG} 
Lors du démarrage des machines (dans l'ordre inverse de celui dans lequel elles ont été stoppées, (le dernier membre actif doit redémarrer le premier) on obtient l'affichage suivant :

23:52:04 | --status connected
23:52:04 | --status joiner
23:52:04 | --status initializing
23:52:05 | --status initialized
23:52:05 | --status joined
23:52:05 | --status joined --uuid 28736ddb-59f8-11ed-abde-fe2234c75fO
23:52:05 | --status synced
23:53:15 | --status synced --uuid 28736ddb-59f8-11ed-abde-fe2234c75fO
23:53:15 | --status donor
23:53:15 | --status joined
23:53:15 | --status synced
23:54:42 | --status synced --uuid 28736ddb-59f8-11ed-abde-fe2234c75fO
23:54:42 | --status donor
23:54:42 | --status joined
23:54:42 | --status synced

C'est très anormal que toutes les machines soient stoppées, mais cela peut arriver, tant qu'il reste une machine en fonction les autres peuvent venir s'abonner au cluster et tout se passe bien.

Le seul problème est que lors de la "panne" d'une machine son adresse IP ne réponds plus et les clients n'ont plus accès aux données et établir un système de haute disponibilité entre trois machines n'est pas une sinécure. 
C'est là l'avantage d'utiliser Maxscale qui va, entre autres choses gérer l'accès à notre cluster. Maxscale permet de gérer des clusters disposant de plus de 3 nœuds, nous verrons cela dans un prochain chapitre ... à suivre 
 

Maxscale : paramétrage

Maxscale : paramétrage jpp

Cet article détaille, un peu, la mise en place de Maxscale.

Le paramétrage est relativement simple mais les dernières présentent un petit "piège" car l'adresse d'écoute par défaut est une adresse IPV6 et cela pourrait vous surprendre. Il est donc important de préciser "address=0.0.0.0" (ou une autre adresse IPV4) dans le paramétrage de Maxscale. 
D'abord la définition des serveurs du cluster Galera :

# Server definitions
#
[gale-2]
type=server
address=192.168.2.153
port=3306
protocol=MariaDBBackend
#
[gale-3]
type=server
address=192.168.2.154
port=3306
protocol=MariaDBBackend
#
[gale-4]
type=server
address=192.168.2.155
port=3306
protocol=MariaDBBackend

J'ai ensuite décidé de créer deux "voies d'accès" :

  1. Une en lecture seule
  2. Une en lecture/écriture
[lect-seule]
type=service
router=readconnroute
servers=gale-4
user=util_services
password=xxxxxxxx
router_options=running
# ReadWriteSplit documentation:
# https://mariadb.com/kb/en/mariadb-maxscale-6-readwritesplit/
[ecri-lect]
type=service
router=readwritesplit
servers=gale-2,gale-3
user=util_services
password=xxxxxxxx

Une fois ces deux services créés il faut leur affecter un "listener" qui permettra l'accès à nos services, nous aurons donc deux "listeners".

[Read-Only-Listener]
type=listener
service=lect-seule
protocol=MariaDBClient
port=3007
address=0.0.0.0
[Read-Write-Listener]
type=listener
service=ecri-lect
protocol=MariaDBClient
port=3006
address=0.0.0.0

C'est ici qu'il faut préciser l'adresse au format IPV4 pour éviter le piège de l'IPV6 par défaut.

Enfin le dernier paragraphe pour fixer les paramètres du monitoring de nos 3 serveurs :

# This will keep MaxScale aware of the state of the servers.
# MariaDB Monitor documentation:
# https://mariadb.com/kb/en/maxscale-6-monitors/
#
[MariaDB-Monitor]
type=monitor
module=mariadbmon
servers=gale-2,gale-3,gale-4
user=xxxxxxx
password=yyyyyyyy
monitor_interval=2s

Ne pas oublier de "protéger" ce fichier par :

chown maxscale: /etc/maxscale.cnf 
chmod 600  /etc/maxscale.cnf 

 

Maxscale GUI

Maxscale GUI jpp
Le GUI de gestion de Maxscale.

Il est accessible sur le port 8989 de la machine selon les paramètres du fichier de configuration :

# MAXGUI 
admin_host=192.168.2.152
# GUI without SSL
admin_secure_gui=false

Ici j'ai inhibé le SSL ce qu'il ne faudrait pas faire en production ... 
Le premier écran qui s'affiche est l'écran de surveillance (Dashboard) de notre cluster Galera première option a gauche dans le menu horizontal.

Ecran démarrage

Cet écran présente l'état de notre cluster, on y voit l'état de notre cluster "Running" en vert dans la colonne "STATE" et la liste de tous les membres du cluster avec le nombre de connexions, leur état (autre colonne "STATE"). 
Le master a droit à la couleur verte et au statut "Master, Running", les deux autres à une mension rouge et Running, donc tout va bien. La dernière colonne indique à quel "service" chaque machine est attachée. 
Un graphique, en haut de l'écran, montre la charge de chaque machine (nombre de sessions, connctions et le load). 
Un menu horizontal permet d'afficher : 
Les sessions courantes. Il est possible ici de "tuer" une session gênante. 
Les services avec les machines concernées et les les sessions en cours. 
Les listeners le nom du listener avec le port qu'ils utilisent, leur état (Running normalement !) et le nom du service. 
Les filtres actifs. Les filtres permettent de réaliser des actions en fonction de l'utilisateur, par exemple de "cacher" certaines données confidentielles .... 
En haut à droite de l'écran le bouton "Create New" permet de créer de nouveaux services, de nouveaux serveurs et des filtres. 
Pour les filtres voir la documentation de Maxscale qui présente toutes les possibilités.  
Depuis le menu principal les options suivantes :

  • Visualisation : permet d'afficher notre cluster en mode graphique.

 
 

  • Query-editor : permet d'exécuter des ordres SQL après s'être identifié auprès d'un service.
  • Users : permet de gérer les utilisateurs de Maxscale (pas ceux du cluster).
  • Logs archives : permet d'afficher le log de Maxscale.
  • Settings : permet de modifier les paramètres de Maxgui, et il y en a un bon paquet ! N'y toucher que si l'on sait ce que l'on fait. 
     

That's all folks.