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.
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
Tu as bien lancé le premier serveur avec galera_new_cluster ?
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
Peux tu me copier coller le contenu du fichier /etc/mysql/mariadb.cnf de chacun de tes serveurs ?
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 🙂
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????
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…)
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..
Hello !
Tout à fait d’accord.
Des articles sont prévus sur ce point.
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
Hum… Comme ça, dur à dire…
Tu pourrais me montrer les logs de chaque serveur au moment de la chute du vpn ?