Mode opératoire — Monter un cluster Galera à 3 nœuds
Document autonome. Partie 1 théorique, partie 2 pas-à-pas appliqué à l’infrastructure
sio.internal.Prérequis : trois machines identiques — voir MO-1-Clonage-VM.md Dernière mise à jour : 27/09/2026
Sommaire
| § | Contenu |
|---|---|
| 1 | Théorie — ce qu’est Galera, et ce qu’il n’est pas |
| 2 | Réplication synchrone, certification, quorum |
| 3 | SST, IST, et les quatre ports |
| 4 | Pas à pas — préparer les trois nœuds |
| 5 | Pas à pas — le fichier de configuration |
| 6 | Pas à pas — amorcer le cluster |
| 7 | Validation et tests |
| 8 | Exploitation courante et pièges |
1 · Théorie — Galera n’est pas une machine
C’est la confusion la plus fréquente, et il faut l’écarter d’emblée.
UN RÉPARTITEUR INTERCEPTE GALERA COORDONNE
───────────────────────── ────────────────
client ─► proxy ─► serveur A nœud 1 ◄══╗
└─► serveur B nœud 2 ◄══╬══ pair-à-pair
nœud 3 ◄══╝
il est SUR le chemin rien ne s'intercale
→ il lui faut sa propre machine → AUCUNE machine supplémentaire
Galera est une bibliothèque de réplication intégrée à MariaDB :
/usr/lib/galera/libgalera_smm.so. Elle est déjà installée avec le paquet mariadb-server —
on la voit défiler à l’installation :
Paramétrage de galera-4 (26.4.23-0+deb13u1) ...
On ne l’installe donc pas : on l’active par un fichier de configuration posé sur chaque nœud.
La règle générale : un composant qui intercepte du trafic (proxy, pare-feu, répartiteur) a besoin d’exister quelque part sur le chemin — il se dessine comme une boîte. Un composant qui coordonne des serveurs entre eux (réplication, cluster, grappe) vit à l’intérieur de ces serveurs — il se dessine comme des flèches entre des boîtes existantes.
1.1 Ce que Galera apporte, et ce qu’il n’apporte pas
| Sans Galera | Avec Galera | |
|---|---|---|
| Un disque meurt | données perdues | deux copies restantes |
| Un serveur s’arrête | service interrompu | les autres continuent |
| L’application s’en aperçoit | — | oui, sauf répartiteur devant |
Résilience des données ≠ disponibilité du service. Galera protège la donnée. Pour que l’application ne s’aperçoive de rien, il faut un répartiteur devant — voir MO-3-HAProxy.md. C’est une distinction que les jurys apprécient.
2 · Réplication synchrone, certification, quorum
2.1 Synchrone vs asynchrone
ASYNCHRONE (réplication MySQL classique)
────────────────────────────────────────
maître : valide ──► répond au client
└─► envoie aux esclaves (plus tard)
→ si le maître meurt maintenant : transaction PERDUE
SYNCHRONE (Galera)
──────────────────
nœud : soumet aux autres ──► tous acceptent ──► valide ──► répond au client
→ la transaction existe partout AVANT que le client ne soit informé
Conséquence directe : une écriture sur un nœud est immédiatement lisible sur les autres. Pas de délai de rattrapage, pas de lecture périmée.
2.2 La certification
Avant de valider, le nœud soumet la transaction aux autres pour certification : le contrôle qu’aucune transaction concurrente ne modifie les mêmes lignes ailleurs.
nœud 1 modifie la ligne 42 ─┐
├─ au même instant → CONFLIT
nœud 2 modifie la ligne 42 ─┘ l'un des deux reçoit une erreur de verrou
C’est pour cela qu’on n’écrit jamais sur plusieurs nœuds à la fois. L’application — WordPress, GLPI — ne sait pas gérer une erreur de certification : elle affichera une erreur à l’utilisateur.
La configuration canonique envoie toutes les écritures sur un seul nœud, les autres étant en attente de bascule. On parle de haute disponibilité active/passive pour les écritures, même si les trois nœuds en sont techniquement capables.
2.3 Le quorum — pourquoi trois et pas deux
3 nœuds, 1 tombe → 2 survivants sur 3 = MAJORITÉ → écritures autorisées
2 nœuds, 1 tombe → 1 survivant sur 2 = 50 % → écritures REFUSÉES
Avec deux nœuds, le survivant ne peut pas savoir si son partenaire est mort ou simplement injoignable. S’il continuait seul alors que l’autre en fait autant de son côté, on obtiendrait deux bases qui divergent : le split-brain, irréparable sans sacrifier des données.
Le cluster préfère donc s’arrêter d’écrire plutôt que risquer la divergence. Il passe en état
non-Primary.
Deux nœuds n’apportent aucune disponibilité supplémentaire, seulement une copie des données. Le premier nombre utile est trois, et on reste toujours sur un nombre impair.
3 · SST, IST, et les quatre ports
3.1 Deux façons de rattraper un nœud
| SST (State Snapshot Transfer) | IST (Incremental State Transfer) | |
|---|---|---|
| Quoi | copie complète de la base | seulement les transactions manquées |
| Quand | nœud neuf, ou répertoire de données vide | nœud absent quelques minutes |
| Durée | minutes à heures selon la taille | quasi instantané |
| Port | 4444 | 4568 |
C’est précisément pour forcer un SST qu’on vide /var/lib/mysql sur un clone : on veut une
copie cohérente prise à l’instant de la jonction, pas une base figée au moment du clonage.
3.2 Choisir la méthode de SST
| Méthode | Fonctionnement | Le donneur pendant ce temps |
|---|---|---|
rsync | copie brute des fichiers | bloqué en lecture seule |
mariabackup | sauvegarde à chaud, cohérente | continue de servir |
mariabackup est la méthode canonique : l’application reste disponible pendant que les
nouveaux nœuds se synchronisent. Elle exige le paquet mariadb-backup sur tous les nœuds —
chacun peut devenir donneur ou receveur.
3.3 Les quatre ports
| Port | Rôle |
|---|---|
3306 | connexions des clients — le seul que le pare-feu verra |
4567 | communication du groupe : découverte, votes, transactions (TCP et UDP) |
4568 | IST — rattrapage incrémental |
4444 | SST — copie complète |
Si les trois nœuds sont dans le même VLAN — le cas de ce TP — aucune règle de pare-feu n’est nécessaire : le trafic est commuté et ne traverse pas le routeur. C’est un choix d’architecture qui a pour conséquence d’échapper au filtrage. À expliciter plutôt qu’à masquer : « on ne filtre pas ce qui ne passe pas par le routeur ».
Créer quand même un alias
PORTS_GALERAdocumente les ports employés et prépare le jour où les nœuds seraient répartis sur plusieurs sites.
4 · Pas à pas — préparer les trois nœuds
Contexte appliqué :
srv-mysql-0110.0.20.10(détient les données WordPress),srv-mysql-0210.0.20.11etsrv-mysql-0310.0.20.12(clones, répertoire de données vidé — voir MO-1 §5). VLAN 20, Debian 13, MariaDB 11.8.6.
4.1 Accès Internet temporaire
Le VLAN BDD est volontairement coupé d’Internet. Rouvrir la règle de sortie le temps de l’installation, puis la refermer.
Vérification depuis un nœud :
sudo apt update
apt updateest lui-même le test : s’il atteint les dépôts, la règle est ouverte. Inutile de chercher un autre outil —curln’est pas forcément installé sur ces machines.
4.2 Installer mariadb-backup — sur les trois nœuds
sudo apt install -y mariadb-backup curl
Profiter de la fenêtre ouverte pour ajouter
curl, utile au diagnostic. Après fermeture de la règle, plus aucun paquet ne pourra être téléchargé sans rouvrir.
4.3 Le compte de synchronisation — sur le nœud 1 uniquement
sudo mariadb -e "CREATE USER 'sst_user'@'localhost' IDENTIFIED BY '<mot-de-passe-sst_user>'; GRANT RELOAD, PROCESS, LOCK TABLES, BINLOG MONITOR ON *.* TO 'sst_user'@'localhost';"
Les nœuds 2 et 3 recevront ce compte par la synchronisation elle-même : Galera réplique aussi les tables système.
| Privilège | Ce qu’il autorise |
|---|---|
RELOAD | poser un verrou global cohérent le temps du cliché |
PROCESS | lire la liste des transactions en cours |
LOCK TABLES | verrouiller les tables non transactionnelles |
BINLOG MONITOR | lire la position du journal binaire — le point de reprise |
BINLOG MONITORs’appelaitREPLICATION CLIENTavant MariaDB 10.5 ; l’ancien nom reste accepté comme alias, mais les tutoriels qui l’emploient datent.Surtout pas
GRANT ALL, que donnent la moitié des guides en ligne. Un compte de service n’a que les privilèges de son service.
Vérification :
sudo mariadb -e "SHOW GRANTS FOR 'sst_user'@'localhost';"
5 · Pas à pas — le fichier de configuration
Une seule commande, à lancer telle quelle sur les trois nœuds. Les deux dernières lignes se remplissent toutes seules.
sudo tee /etc/mysql/mariadb.conf.d/60-galera.cnf > /dev/null <<EOF
[mysqld]
bind-address = 0.0.0.0
[galera]
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
wsrep_cluster_name = galera-sio
wsrep_cluster_address = gcomm://10.0.20.10,10.0.20.11,10.0.20.12
wsrep_sst_method = mariabackup
wsrep_sst_auth = sst_user:<mot-de-passe-sst_user>
binlog_format = ROW
default_storage_engine = InnoDB
innodb_autoinc_lock_mode = 2
wsrep_node_address = $(ip -4 -br addr show ens18 | awk '{print $3}' | cut -d/ -f1)
wsrep_node_name = $(hostname)
EOF
Le
<<EOFsans guillemets autorise le shell à évaluer les$( )avant d’écrire : chaque nœud inscrit sa propre adresse et son nom. Une seule commande pour trois machines, zéro risque de recopier la mauvaise valeur. (Avec<<'EOF'— guillemets simples — rien ne serait substitué. C’est la forme à utiliser quand on veut préserver des$littéraux, par exemple${APACHE_LOG_DIR}dans un VirtualHost.)
5.1 Les directives, une par une
| Directive | Rôle |
|---|---|
wsrep_on | active la réplication — l’interrupteur principal |
wsrep_provider | chemin de la bibliothèque Galera |
wsrep_cluster_name | identique sur tous les nœuds, sinon ils se rejettent |
wsrep_cluster_address | la liste des membres — comment un nœud trouve les autres |
wsrep_sst_method | mariabackup : le donneur reste disponible |
wsrep_sst_auth | le compte créé au §4.3 |
wsrep_node_address / _name | l’identité propre du nœud |
5.2 Les trois directives qu’on oublie toujours
| Directive | Pourquoi elle est obligatoire |
|---|---|
binlog_format = ROW | Galera réplique les lignes modifiées, pas les requêtes. Un UPDATE … WHERE id = RAND() donnerait un résultat différent sur chaque nœud. Le mode ROW transmet le résultat, pas l’instruction. |
default_storage_engine = InnoDB | Galera ne réplique que l’InnoDB, transactionnel. Une table MyISAM ne serait pas répliquée, silencieusement. |
innodb_autoinc_lock_mode = 2 | Sans cela, deux nœuds insérant simultanément attribueraient le même identifiant auto-incrémenté. Le mode 2 décale les plages par nœud. |
5.3 Le renoncement sur bind-address
Galera impose d’écouter sur plusieurs ports : bind-address doit passer de l’adresse précise du
serveur à 0.0.0.0.
C’est un assouplissement réel, à documenter comme tel. Il reste compensé par deux barrières :
| Verrou | Où | Toujours en place ? |
|---|---|---|
1 · bind-address restreint | le serveur | abandonné |
| 2 · règle de pare-feu | le routeur | seule porte vers le VLAN 20 |
3 · GRANT … @'adresse' | MariaDB | origine vérifiée |
Effet de bord bienvenu : les clones ont hérité du
bind-addressde leur source — une adresse qu’ils ne portent pas. MariaDB refuserait de démarrer avecCan't assign requested address. Comme60-galera.cnfest lu après50-server.cnf(ordre alphabétique), sa valeur écrase la précédente et corrige le problème au passage.
5.4 Vérifier
grep -E "wsrep_node_|bind-address" /etc/mysql/mariadb.conf.d/60-galera.cnf
Sur chaque nœud, les deux lignes wsrep_node_* doivent porter ses propres valeurs.
6 · Pas à pas — amorcer le cluster
6.1 L’ordre est impératif
# sur le nœud qui DÉTIENT LES DONNÉES, et lui seul
sudo systemctl stop mariadb
sudo galera_new_cluster
# puis nœud 2 — attendre « Synced » — ENSUITE nœud 3
sudo systemctl start mariadb
sudo systemctl enable mariadb
6.2 galera_new_cluster ne se lance qu’une fois, sur un seul nœud
galera_new_cluster → « je suis la semence, mes données font référence » → CRÉE le cluster
systemctl start → « je cherche un cluster existant » → le REJOINT
L’exécuter sur deux nœuds produirait deux clusters distincts portant le même nom, chacun convaincu d’être le vrai : le split-brain, irréparable sans choisir quelles données sacrifier.
Le nœud amorceur est celui qui détient les données — ici srv-mysql-01, qui héberge la base
WordPress.
6.3 Un nœud à la fois
Deux SST simultanés font travailler le donneur deux fois, sans gain. Attendre l’état Synced
du nœud 2 avant de démarrer le nœud 3.
Pour suivre en direct :
sudo journalctl -u mariadb -f
Les états traversés : Joiner (réception du SST) → Synced (à jour).
Côté donneur, on observe Donor/Desynced pendant la copie.
systemctl enableà ne pas oublier sur les nœuds 2 et 3 : ils avaient été désactivés parce que leur répertoire de données était vide (MO-1 §5). Sans cela, un redémarrage de VM sortirait le nœud du cluster sans prévenir.
7 · Validation et tests
7.1 L’état du cluster — sur les trois nœuds
sudo mariadb -e "SHOW STATUS WHERE Variable_name IN ('wsrep_cluster_size','wsrep_cluster_status','wsrep_local_state_comment','wsrep_incoming_addresses');"
Résultat attendu, identique partout :
| wsrep_local_state_comment | Synced |
| wsrep_incoming_addresses | 10.0.20.11:0,10.0.20.12:0,10.0.20.10:0 |
| wsrep_cluster_size | 3 |
| wsrep_cluster_status | Primary |
| Variable | Signification |
|---|---|
wsrep_cluster_size | nombre de membres vus par ce nœud — les trois doivent dire 3 |
wsrep_cluster_status | Primary = cette partition détient le quorum |
wsrep_local_state_comment | Synced = ce nœud est à jour |
wsrep_incoming_addresses | la liste des membres, vue par ce nœud |
Primaryne signifie pas « nœud principal » — c’est l’état de la partition. Tous les nœuds d’un cluster sain sontPrimarysimultanément.
Interroger les trois nœuds, pas un seul. Un nœud isolé du groupe afficherait
wsrep_cluster_size = 1en toute bonne foi. La cohérence se vérifie en croisant les réponses.
7.2 Le test de réplication
Sur le nœud 2 :
sudo mariadb -e "CREATE DATABASE test_replication; CREATE TABLE test_replication.preuve (id INT PRIMARY KEY, note VARCHAR(50)); INSERT INTO test_replication.preuve VALUES (1,'ecrit sur le noeud 2');"
Sur le nœud 3 :
sudo mariadb -e "SELECT * FROM test_replication.preuve;"
La ligne doit s’y trouver immédiatement. Nettoyage :
sudo mariadb -e "DROP DATABASE test_replication;"
7.3 Le test qui impressionne : la réplication des comptes
Créer un utilisateur sur le nœud 1 :
sudo mariadb -e "CREATE USER 'demo'@'10.0.10.10' IDENTIFIED BY 'x';"
Le retrouver sur le nœud 3 :
sudo mariadb -e "SELECT user, host FROM mysql.global_priv WHERE user='demo';"
Plus parlant qu’une table de démonstration : ce ne sont pas des données applicatives mais
les tables système de MariaDB. Galera réplique tout le serveur, comptes et privilèges
compris. 40-replication-comptes-et-site.png
7.4 Le test du quorum — le plus formateur
Corrigé le 02/11/2026 : un arrêt propre ne fait PAS perdre le quorum. Avec
systemctl stop, le nœud prévient les autres qu’il part : les survivants recalculent la majorité entre eux et restentPrimary, même à un seul (c’est ce qui s’est passé dans H-39). Le quorum ne se perd que si des nœuds disparaissent sans prévenir : panne, ou coupure réseau. On simule donc une coupure : la carte réseau des deux nœuds est débranchée dans Proxmox.
Dans Proxmox, pour le nœud 2 puis le nœud 3 : Hardware → Network Device (net0) → Edit → cocher
Disconnect. En ligne de commande sur l’hyperviseur, l’équivalent (en reprenant toute la ligne net0 lue par
qm config <vmid>, sinon on perd les autres réglages de la carte) :
qm set <vmid> --net0 virtio=<MAC>,bridge=vmbr1,tag=20,link_down=1
Sur le survivant :
sudo mariadb -e "SHOW STATUS LIKE 'wsrep_cluster_status';"
sudo mariadb -e "CREATE DATABASE test_quorum;"
Attendu : non-Primary, et l’écriture refusée.
C’est contre-intuitif, et c’est tout l’intérêt. On s’attend à ce qu’un système « tienne » le plus longtemps possible. Or le survivant refuse délibérément d’écrire : ne détenant plus la majorité, il ne peut pas savoir s’il est le dernier debout ou simplement isolé du reste. Il préfère s’arrêter plutôt que produire une base qui divergerait de celle des autres.
Rebrancher les deux cartes (décocher Disconnect, ou la même commande sans link_down=1) : le cluster se reforme
seul, sans galera_new_cluster.
Validé le 02/11/2026 : non-Primary, wsrep_ready OFF, CREATE DATABASE refusé par ERROR 1047 … WSREP has not yet prepared node for application use ; site en 503 pendant la panne ; après rebranchement, 3 / Primary /
Synced sur les trois nœuds en moins de 10 s (capture 145).
Effet de bord à connaître : tout ce dont la base est dans le cluster s’arrête avec lui, y compris Grafana et donc les alertes (H-66).
8 · Exploitation courante et pièges
8.1 Arrêt complet du cluster — le cas qui piège
Si les trois nœuds sont arrêtés, aucun ne redémarrera seul : chacun cherchera un cluster qui n’existe plus.
Il faut ré-amorcer depuis le nœud le plus à jour. Pour l’identifier :
sudo cat /var/lib/mysql/grastate.dat
seqno: 1234
safe_to_bootstrap: 1
| Champ | Lecture |
|---|---|
seqno | numéro de la dernière transaction — le plus élevé gagne |
safe_to_bootstrap: 1 | ce nœud s’est arrêté en dernier, il peut amorcer |
Sur ce nœud uniquement : sudo galera_new_cluster, puis démarrer les autres normalement.
Ne jamais forcer
safe_to_bootstrapà 1 sur un nœud qui affiche0sans avoir comparé lesseqno. Ce serait choisir arbitrairement quelles transactions perdre.
8.2 Les pièges rencontrés
| Symptôme | Cause | Correction |
|---|---|---|
Can't connect … through socket | le service n’a pas été démarré | systemctl start mariadb |
Can't assign requested address | bind-address hérité du clone | 60-galera.cnf avec 0.0.0.0 |
SST échoue · wsrep_sst_mariabackup: No such file | mariadb-backup absent sur un nœud | l’installer partout |
Access denied for user 'sst_user' | mot de passe erroné dans wsrep_sst_auth | vérifier la concordance |
failed to reach primary view | le nœud amorceur n’est pas joignable sur 4567 | vérifier le réseau |
journalctl : No journal files were found | machine-id changé après le boot | systemctl restart systemd-journald |
8.3 Commandes de diagnostic à connaître
# état complet
sudo mariadb -e "SHOW STATUS LIKE 'wsrep_%';"
# les cinq variables qui comptent
sudo mariadb -e "SHOW STATUS WHERE Variable_name IN ('wsrep_cluster_size','wsrep_cluster_status','wsrep_local_state_comment','wsrep_connected','wsrep_ready');"
# qui est dans le groupe
sudo mariadb -e "SHOW STATUS LIKE 'wsrep_incoming_addresses';"
# le journal
sudo journalctl -u mariadb -n 50 --no-pager
8.4 Checklist de montage
Trois machines, identités régénérées (MO-1)
/var/lib/mysql vidé sur les futurs joignants
mariadb-backup installé sur LES TROIS
Compte sst_user créé sur le nœud amorceur
60-galera.cnf posé sur les trois, valeurs propres vérifiées
galera_new_cluster sur UN SEUL nœud — celui qui a les données
Nœuds 2 puis 3, UN À LA FOIS, attendre « Synced »
systemctl enable mariadb sur les nœuds 2 et 3
wsrep_cluster_size = 3 vérifié sur LES TROIS
Test de réplication croisée
Accès Internet du VLAN refermé
À retenir en une phrase : Galera ne se déploie pas, il s’active — et le seul moment délicat est l’amorçage, qui n’a lieu qu’une fois, sur un seul nœud, celui qui détient la vérité.

