Login Logout

Réplication MySQL avec Galera

Galera est un module de réplication synchrone et multi-master avec une tolérance de panne transparente. Il se base sur la Write-Set Replication API (wsrep API) de MySQL.

La réplication est totalement transparente pour l’application, aucun potentiel délai de réplication ou gestion des locks entre les serveurs n’est à prévoir. Cependant les tables non-transactionnelles de type MyISAM ne sont pas supportées par la réplication et ne seront donc pas répliquées !

Il est conseillé d’avoir au minimum 3 serveurs en cas de conflit de réplication, mais 2 peuvent suffire.

Installation

Depuis Debian 9 (Stretch), le MariaDB plugin de réplication Galera est présent dans le paquet MariaDB serveur. De même, le paquet galera-4 (ou galera-3 suivant la version de MariaDB) est une dépendance de mariadb-serveur. Il n’y a donc aucune action supplémentaire à faire.

Pour revoir la partie installation de MariaDB, il y a notre Howto MySQL

Mise en place

Configuration réseau / Firewalling

La réplication Galera utilise des ports réseau dédiés. Il est donc nécessaire d’autoriser les ports suivant dans les pare-feu des machines :

  • 4567/tcp, 4567/udp
  • 4568/tcp
  • 4444/tcp

Configuration de MariaDB

Ajouter la configuration suivante dans le fichier /etc/mysql/mariadb.conf.d/galera.cnf, sur toutes les machines du cluster :

[mysqld]

# The following MySQL options are mandatory for Galera to work

bind-address=0.0.0.0

default-storage-engine=innodb
innodb_autoinc_lock_mode=2
innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=<votre innodb_buffer_pool_size actuel + ~ 5% pour Galera>

binlog_format=ROW

# Galera cluster configuration

wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_provider_options="gcache.size=300M; gcache.page_size=300M"

wsrep_cluster_name="<nom arbitraire du cluster>"
wsrep_cluster_address="gcomm://<liste des adresses IP des machines du cluster, séparées par des virgules>"

wsrep_sst_method=rsync

wsrep_node_address="<adresse IP de la machine - Communication inter-noeuds>"
wsrep_node_name="<nom de la machine>"
wsrep_retry_autocommit=4

Note Importante : seul wsrep_node_address et wsrep_node_name sont différents d’une machine à l’autre.

Bien s’assurer que le fichier est lisible par MariaDB :

# chmod 644 /etc/mysql/mariadb.conf.d/galera.cnf

Amorce d’un cluster

Pour initialiser le nouveau cluster, il est nécessaire de démarrer l’une des machines avec l’option --wsrep-new-cluster.

Avant tout, s’assurer que MariaDB est éteint sur chaque serveur :

# systemctl stop mariadb.service

Depuis MariaDB 10.1 (Debian stretch), il y a le script galera_new_cluster qui s’occupe de l’amorce du cluster. il est préférable de l’utiliser pour la première initialisation. Cette invocation soit être réalisée sur un seul serveur

# galera_new_cluster

Dès que la commande est terminée, on peut démarrer les autres noeuds MariaDB de manière normale

# systemctl start mariadb.service

Administration

Vérifier l’état du cluster :

mysql> SHOW STATUS LIKE 'wsrep_%';
+---------------------------+------------+
| Variable_name             | Value      |
+---------------------------+------------+
...
| wsrep_local_state_comment | Synced (6) |
| wsrep_cluster_size        | 3          |
| wsrep_ready               | ON         |
+---------------------------+------------+

wsrep_cluster_size indique ici le nombre de machine dans le cluster.

Monitoring

Nagios

Pour un monitoring simple du cluster, on peut utiliser le check nagios suivant https://github.com/fridim/nagios-plugin-check_galera_cluster sur chaque noeuds.

Celui-ci surveillera :

  • Qu’il y ait assez de noeuds actifs dans le cluster
  • Que le noeud surveillé soit master (ie: donc cluster opérationel)
  • Que le cluster n’ait pas mis le noeud en pause trop longtemps pour qu’il récupère du retard (en surveillant wsrep_flow_control_paused)

Munin

TODO

Plomberie

Récupération d’un cluster complètement arrêté.

Dans certains cas, on peut se retrouver dans une situation ou tous les nœuds du cluster sont arrêtés. Lors du démarrage d’un noeud il devient impossible de rejoindre le cluster, car il n’existe plus.

Cela nécessite de réamorcer manuellement le cluster. Commencer par inspecter le fichier /var/lib/mysql/grastate.dat sur chaque machines pour identifier le nœud qui contient la version la plus avancée de la base de donnée.

Si tous les nœuds ont bien été arrêtés, c’est donc le nœud avec le “seqno” le plus grand qui contient la dernière version de la base. C’est lui qui doit servir de point de départ.

Il se peut que seqno soit à -1. Dans ce cas-là, le nœud n’a pas été arrêté proprement. On peut alors récupérer le numéro de séquence avec la commande mysqld --wsrep-recover. L’information peut être récupéré dans /var/log/mysql/error.log

Voici les étapes pour réamorcer manuellement à partir du nœud le plus à jour:

  • Modifier /etc/mysql/mariadb.conf.d/galera.cnf pour définir wsrep_cluster_address="gcomm://" et ainsi le forcer à démarrer seul
  • Démarrer mariadb : systemctl start mariadb
  • Rétablir la configuration du cluster dans /etc/mysql/mariadb.conf.d/galera.cnf (Un redémarrage n’est pas nécessaire)

Après le démarrage correct du premier nœud, on peut démarrer un à un les autres nœuds du cluster

Récupération d’un noeud avec un datadir corrompu

Dans une situation de corruption de données sur un noeud (causée par exemple par une saturation disque), on peut alors détruire le datadir pour le forcer à se resynchroniser de zéro. Simplement créer le dossier avec les bon droits suiffit. Galera s’occupera du reste.

Remarque importante : Attention, il est préférable d’avoir deux noeuds “sains”. En effet, le noeud corrompu va récupérer l’état du cluster via un des noeuds sains avec un rsync des données. Mais pendant l’opération, le noeud sain source du rsync, va passer en état “DONOR”, et donc ne pas accepter de faire des écritures. S’il n’y a qu’un seul noeud sain, l’opération va donc causer une interruption de service.

# mv /var/lib/mysql /var/lib/mysql.delete_me
# mkdir /var/lib/mysql
# chmod 700 /var/lib/mysql
# chown mysql: /var/lib/mysql
# systemctl start mariadb