19 mars 2024

Tuto V.2018 : Partie X, Cluster MariaDB Galera et Failover HAproxy

Dixième partie du tutoriel sur la virtualisation « Xen et OpenVswitch sont dans une Debian« .
Nous venons de mettre un place un cluster de données avec GlusterFS, passons maintenant à un cluster pour nos bases SQL.
Nous allons utiliser pour cela MariaDB Galera Cluster.

I – Préparatifs

A – Principe

MariaDB est un fork de MySQL, crée par le fondateur de ce dernier lors du rachat de MySQL par Oracle. Énormément de monde a migré dessus, dont la plupart des distributions Linux (et donc notre Debian préférée).
Pour les clients, c’est transparent, rien à modifier et coté serveur, on est également en terrain connu. Le langage SQL reste le même… Au final, le nom des paquets a changé, mais les fondamentaux restent (bon, je simplifie, mais à notre niveau, c’est kif-kif).
Idéalement, il faut monter un tel cluster sur au moins trois serveurs afin d’éviter les situations de « splitbrain ».
Si vous êtes un peu limité en place, etc.., je vous donnerai, un peu plus loin, une solution pour remplacer le troisième serveur par Garb, un arbitre qui remplacera le troisième nœud (il ne fera rien au niveau SQL, mais servira juste pour éviter les fameux splitbrain)

B – Création des VMS

Nous avons besoin de quatre VMs : Maria1, Maria2, Maria3 , et Mariaprox (qui servira à Haproxy)

dom0# xen-create-image --hostname maria1 --role debugo --size 20G --memory 1G--swap 1G --vcpus=1 --ip=99.99.99.99
dom0# xen-create-image --hostname maria2 --role debugo --size 20G --memory 1G--swap 1G --vcpus=1 --ip=99.99.99.99
dom0# xen-create-image --hostname maria3 --role debugo --size 20G --memory 1G--swap 1G --vcpus=1 --ip=99.99.99.99
dom0# xen-create-image --hostname mariaprox --role debugo --size 5G --memory 1G--swap 1G --vcpus=1 --ip=99.99.99.99

Puis, la routine, pour les quatre vms :
Fichier /etc/xen/mariaX.cfg :

vif         = [ 'vifname=mariaX.0,ip=10.20.1.15X ,mac=00:16:3E:A1:5X:20,bridge=brint.20',
                'vifname=mariaX.1,ip=10.99.1.15X ,mac=00:16:3E:A1:5X:99,bridge=brint.99',
                'vifname=mariaX.2,ip=10.10.1.15X ,mac=00:16:3E:A1:5X:10,bridge=brint.10'
]

Interfaces réseaux :

dom0# mount /dev/vg0/mariaX-disk /mnt/vm/
dom0# nano /mnt/vm/etc/network/interfaces

Collez cela :

auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
 address 10.20.1.15X
 netmask 255.255.255.0
auto eth1
iface eth1 inet static
 address 10.99.1.15X
 netmask 255.255.255.0

Et démontez :

dom0# umount /mnt/vm

Je te détaille pas les trois machines, mais Maria1 > Ip en 151, Maria2 -> IP en 152, Maria3 -> IP en 153 et Mariaprox -> IP en  150.

 C – Ajout des VMs dans le DNS

Pensez au passage à ajouter les entrées dans votre DNS (fichier intra20, intra99 et intra.rev) sans oublier, bien sur, l’incrémentation des sérials et le rechargement avec :

# rndc reload

 

II – Installation de MariaDB

Sur les trois machines, Maria1, Maria2 et Maria3 :

# apt-get install -y mariadb-server

Une fois tout cela installé, toujours sur les trois machines :

# service mysql stop
# rm -f /var/lib/mysql/ib_logfile*

Maintenant, sur Maria1, on va éditer le fichier de configuration : /etc/mysql/mariadb.cnf pour y ajouter :

[mysqld]
bind-address=0.0.0.0
binlog_format=ROW
innodb_autoinc_lock_mode=2
innodb_flush_log_at_trx_commit=0
wsrep_cluster_name=DebugoSQL
wsrep_cluster_address="gcomm://maria2,maria3"
wsrep_node_name=db1
wsrep_node_address="10.20.1.151"
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_sst_method=rsync

Puis sur Maria2 et Maria3, on va copier le fichier de configuration contenant le compte debian-sys (afin d’avoir le même mot de passe sur chaque nœud pour ce compte particulier) et ainsi éviter les erreurs au lancement

maria2# scp -p root@maria1:/etc/mysql/debian.cnf /etc/mysql/
maria3# scp -p root@maria1:/etc/mysql/debian.cnf /etc/mysql/

Sur Maria2, on édite le fichier /etc/mysql/mariadb.cnf à l’identique de Maria1, sauf les lignes :

wsrep_cluster_address="gcomm://maria1,maria3"
wsrep_node_name=db2

Et sur Maria3, on édite le fichier /etc/mysql/mariadb.cnf à l’identique de Maria1, sauf les lignes :

wsrep_cluster_address="gcomm://maria1,maria2"
wsrep_node_name=db3

 

III – Manipulation du Cluster

A – Lancement

On revient sur Maria1 et on lance le cluster :

maria1# galera_new_cluster

On vérifie :

maria1# mysql -u root -e 'SELECT VARIABLE_VALUE as "cluster size" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME="wsrep_cluster_size"' -p

Doit nous retourner un membre.
Sur Maria 2, on démarre le serveur :

maria2# service mysql start

Puis sur Maria 3 :

maria3# service mysql start

 

B – Vérification

On vérifie alors sur les trois vms :

# mysql -u root -e 'SELECT VARIABLE_VALUE as "cluster size" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME="wsrep_cluster_size"' -p

Doit retourner trois membres.
On peut aussi utiliser :

# mysql -u root -p -e 'SHOW STATUS LIKE "wsrep_%"'

qui affichera alors toutes les informations liées au cluster.

C – Coupure

Si vous avez besoin de couper complètement l’ensemble du cluster, prenez soin de couper en dernier le nœud qui vous a servi à démarrer le cluster.
Et pour relancer le cluster (donc si tous les nœuds sont coupés), sur un des nœud, vous lancerez :

# galera_new_cluster

Si le cluster ne se lance pas (message d’erreur), faites un:

# tail /var/log/mysql/error.log

qui peut vous expliquer ce qu’il se passe :

 WSREP: It may not be safe to bootstrap the cluster from this node. It was not the last one to leave the cluster and may not contain all the updates. To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .

Je sais donc que ce n’est pas le serveur qui a été le dernier à se lancer. Tentez alors sur les autres nœuds.
Si le nœud sur lequel vous avez démarré le cluster est, par la suite, coupé, mais que les autres sont toujours actifs, relancez simplement avec :

# service mysql start

IV – Garb, l’arbitrator

Vous êtes limité en ressources ? Pas de soucis : au lieu d’avoir un troisième nœud SQL, on peut installer Garb sur la machine Mariaprox.
Bien évidement, dans ce cas, sur Maria1 et Maria2, dans le fichier /etc/mysql/mariadb.cnf, remplacez les occurrences de Maria3 par Mariaprox :

wsrep_cluster_address="gcomm://mariaX,mariaprox"

Installons le logiciel :

mariaprox# apt-get install galera-arbitrator-3

Le fichier de configuration se trouve dans /etc/default/garb. Éditez le de la sorte :

GALERA_NODES="maria1:4567,maria2:4567"
GALERA_GROUP="DebugoSQL"
LOG_FILE="/var/log/garbd.log"

On lance :

marialb# service garb start

On vérifie sur Maria1 et Maria2 :

# mysql -u root -e 'SELECT VARIABLE_VALUE as "cluster size" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME="wsrep_cluster_size"' -p

Doit retourner trois membres.


V – Tests de réplication

Pour faire vos tests, c’est simple, créez des bases, tables, vérifiez la réplication. Coupez un des serveurs, créez, modifiez des bases, rallumez le serveur, vérifiez la réplication, bref, vous voyez le principe !
Normalement, tout devrait être transparent sans la moindre perte de données. J’ai fait pas mal de tests et aucune faiblesse à démontrer pour le moment.

VI – Failover avec HAproxy

A – Installation

Bon, tout ça, c’est bien joli, mais pour le moment les clients SQL doivent encore s’adresser à un serveur en particulier. Si celui ci tombe, on l’a dans l’os.
Il faudrait quelque chose en amont pour faire un point d’entrée unique. Plusieurs solutions techniques sont possibles.
Connaissant déjà HAproxy, nous allons l’utiliser ici et nous allons le déployer sur Mariaprox.
Simple à installer :

mariaprox# apt-get install haproxy

Ajoutez ce qui suit dans le fichier de config /etc/haproxy/haproxy.cfg :

frontend sql-front
 bind *:3306
 mode tcp
 default_backend sql-back
backend sql-back
 mode tcp
 balance leastconn
 option mysql-check user haproxy_check
 server maria1 10.20.1.151:3306 check port 3306
 server maria2 10.20.1.152:3306 check port 3306 backup
 server maria3 10.20.1.153:3306 check port 3306 backup
listen stats
 bind 0.0.0.0:8282
 mode http
 balance
 timeout client 5000
 timeout connect 4000
 timeout server 30000
 stats hide-version
 stats uri /
 stats realm HAProxy\ Statistics
 stats auth user:pass
 stats admin if TRUE

On crée un frontend qui écoute sur le port standard MySQL (3306). Haproxy transfère aux deux serveurs derrières. Ici, pas de loadbalancing, tout est envoyé sur Maria1. Maria2 et Maria3 ne sont utilisés qu’en cas de down du premier nœud (option backup).
Si vous mettez Garb à la place de Maria3, supprimez la ligne concernant Maria3 et ne rajoutez rien, je vous le disais, Garb ne sert à rien au niveau SQL.
L’interface pour les stats sera accessible avec notre futur reverse proxy.
Pour faire les vérifications de status des noeuds, on peut utiliser la vérification du socket toute bête. Le hic, c’est que cela incrémente un compteur de connexion en erreur côté SQL (et à un moment, le serveur refuse toute connexion venant du proxy et paf, plus de sites…. Et le fait que le serveur réponde sur le port 3306 ne veut pas dire que le serveur sql tourne correctement. Le mieux est donc de passer par une vérification avec connexion d’un user.
C’est l’option mysql-check.
Mais il faut donc ajouter un utilisateur sur les serveurs SQL.
On se connecte à Maria1 :

maria1# mysql -u root -p
mysql > CREATE USER 'haproxy_check'@'10.20.1.150';
mysql > GRANT USAGE ON *.* TO 'haproxy_check'@'10.20.1.150';
mysql > flush privileges;
mysql > quit

On revient sur mariaprox pour relancer Haproxy :

mariaprox# service haproxy restart

Dorénavant, nos clients SQL se connecteront à Mariaprox et non plus à Maria1 ou Maria2.

B – Tests

Pour tester cela, on va créer une base test sur maria1 :

maria1# mysql -u root -p
mysql > create database test;
mysql >  GRANT ALL PRIVILEGES ON test.* TO 'test'@'10.20.1.150' IDENTIFIED BY 'test';
mysql > flush privileges;

On peut tester sur la vm Web (10.20.1.30) par exemple :

web# apt-get install mysql-client
web# mysq -h marialb -u test -ptest
myqsl>...

Vous constatez surement que l’hôte de mon user sql n’est pas l’hôte de mon client. En effet, la connexion passant par le proxy, il faut donner les droits avec l’ip du proxy…

VII – Informations complémentaires

A – Répartition écriture/lecture

Un peu plus tard, nous verrons comment répartir les écritures et lectures entre les serveurs. Il existe plusieurs solutions à cela.

B – Format de table compatible

Attention, la réplication entre les serveurs ne fonctionne qu’avec des tables en InnoDB. Si jamais vous avez une application qui créé ses tables en MyISAM, elles ne seront pas répliquées sur les autres serveurs. Du coup, il sera nécessaire pour certaines applications de faire des retouches et la, sed sera notre ami !

Pour terminer, je vous invite à consulter ce qui remplace GlusterFS dont je parlais avant et a consulter l’article qui finalise cette série.

11 réflexions sur « Tuto V.2018 : Partie X, Cluster MariaDB Galera et Failover HAproxy »

  1. Salut, j’essaie de suivre ton tuto et rien n’y fait j’ai une erreur quand je démarre mes nodes 2 et 3..
    J’ai pas mal cherché et je trouve pas de solution, tu as pas eu cette erreur ?
    2018-07-12 15:19:10 0 [ERROR] WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 (Connection timed out)
    juil. 12 15:19:10 smaria3 mysqld[7902]: at gcomm/src/pc.cpp:connect():158
    juil. 12 15:19:10 smaria3 mysqld[7902]: 2018-07-12 15:19:10 0 [ERROR] WSREP: gcs/src/gcs_core.cpp:gcs_core_open():208: Failed to open backend connection: -110 (Connection timed out)
    juil. 12 15:19:10 smaria3 mysqld[7902]: 2018-07-12 15:19:10 0 [ERROR] WSREP: gcs/src/gcs.cpp:gcs_open():1458: Failed to open channel ‘LaineSQL’ at ‘gcomm://smaria1,smaria2…n timed out)
    juil. 12 15:19:10 smaria3 mysqld[7902]: 2018-07-12 15:19:10 0 [ERROR] WSREP: gcs connect failed: Connection timed out
    juil. 12 15:19:10 smaria3 mysqld[7902]: 2018-07-12 15:19:10 0 [ERROR] WSREP: wsrep::connect(gcomm://smaria1,smaria2) failed: 7
    juil. 12 15:19:10 smaria3 mysqld[7902]: 2018-07-12 15:19:10 0 [ERROR] Aborting

  2. Oui, j’ai testé de mille façon avec pleins de versions différentes et d’autres tutos, je ne comprends pas pourquoi ça ne marche jamais.. Quand je lance une node en plus, mysql ne se lance pas. Et le pire c’est que sur le 1 j’ai bien la taille de mon cluster qui augmente pendant que le service se lance sur le 2 (le service fini par fail) et après j »ai Desync/Donor toujours en taille 2 avec les 2 ip sur le 1 avec mon mysql2 qui est n’est pas démarré. Et quand je veux lancer mysql -uroot -p j’ai ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’ (111 « Connection refused »)..
    Bref 15h dessus hier, j’ai pensé que ça venait de mon infra mais il n’y a pas de raison. J’ai essayé plusieurs distro debian 9, 8, CentOS aussi. Je bosse sur un ESXi en local, rien de particulier donc je vois pas

  3. Je dois présenté mon infra semaine pro j’ai laché cette partie pour faire du simple master master esclave sans cluster.. Mais en gros il y avait aucune diff avec toi, et après j’ai bien creusé sur le net pour trouver (15h dessus hier..) rien n’y faisait, j’ai essayé toute les versions, avec des .cnf différents voir si il me manquait pas des choses bref… Je vais retenter plus tard malheureusement plus le temps la ! Mais merci quand même 🙂

  4. Bonjour pour Nicolas, est ce que dans la configuration du mariadb.cnf tu n’as pas changé wsrep_node_address du maria2 & maria3 par leur adresse ip propre????

  5. Oups, je n’avais pas vu ta question.
    Je passe par le dns pour la résolution des IPs. Au cas ou je les changerais..
    Mais tu as raison, on peut tout à fait mettre les IPs pour éviter la requête dns, ou mettre un unbound sur la VM (DNS léger pour faire du cache dans ce cas…)

  6. mise en place, ca a l’air pas mal. mais quid du dépannage ??
    comment on peut gèrer les problèmes éventuels.?
    c’est surtout la que se situe la difficulté..quand tout ou partie défaille..

  7. Super tuto merci
    Mais j’ai un souci.
    J’ai 3db sur site 1 et 3db sur site 2.
    Tout se synchronise nickel.

    Je coupe hard stop une vm le cluster tient le coup.
    MAIS
    Si le vpn tombe, le cluster ne fonctionne plus et j’ai des erreurs WSREP.
    Une idée de ce que ca pourrait etre ?
    Merci

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *