Suite à la réalisation d’un Proof-of-Concept (PoC) en entreprise sur une infrastructure MySQL en mode cluster (master résilient, multi slave), je vais vous présenter ici l’infrastructure retenue et sa configuration.
Notre configuration se base sur deux serveurs pouvant faire office de maître et un pool de slaves dont le nombre n’est pas fixe. Cette configuration est plutôt réservée pour des applicatifs supportant la gestion de serveurs d’écriture et de serveurs de lecture. Néanmoins vous pouvez exclure la partie esclave si seul un maître redondant vous convient.
Pour la partie maître, l’un des serveur est actif, l’autre en stand-by. Si le serveur actif tombe, l’autre serveur prend le relai et dessert le service MySQL maître.
Pour la partie eslave, ceux-ci répliquent leurs données depuis le maître actif en se basant sur une adresse IP virtuelle.Voici le schéma d’architecture de la réplication des données
Au niveau composants logiciels, la solution utilise:
Au niveau hardware il vous faudra:
Afin de bien se repérer, voici la topologie réseau de nos serveurs
Dans un premier temps nous allons configurer la réplication de disques HAST. Créez le fichier hast.conf suivant sur chacun de vos serveurs MySQL maîtres:
resource mymasters {
checksum sha256
on master1 {
local /dev/da1
remote 10.255.255.2
}
on master2 {
local /dev/da1
remote 10.255.255.1
}
}
Dans un premier temps on définit une ressource HAST nommée mymasters. Celle-ci contient deux noeuds: master1 et master2, noms d’hôtes respectifs de chaque machine. On définit également l’utilisation d’un checksum en sha256 afin de vérifier l’intégrité des blocs.
Pour chaque hôte, on définit le disque local à répliquer et l’adresse IP du noeud sur lequel répliquer.
On active ensuite le service hastd et on le lance
sysrc hastd_enable=YES
service hastd start
Lors du démarrage du service hast les volumes sont en état init. Cela peut se vérifier avec la commande hastctl status.
Name Status Role Components
mymasters - init /dev/da1 10.255.255.2
Tapez ensuite la commande suivante afin d’initialiser les disques pour HAST sur chaque serveur:
hastctl create mymasters
Il convient alors de définir un noeud primaire maître et un noeud secondaire. Sur le primaire entrez la commande suivante:
hastctl role primary mymasters
Et sur le secondaire:
hastctl role secondary mymasters
Le volume va se retrouver dans l’état suivant:
Name Status Role Components
mymasters complete primary /dev/da1 10.255.255.2
Il faut maintenant laisser le temps aux deux volumes de se synchroniser. Vérifiez le champ dirty sur les deux noeuds afin de vérifier l’état d’avancement. Le volume HAST ne sera pas présenté sur le secondaire lors de son passante en primaire si le champ dirty contient des données à synchroniser lors de la synchronisation initiale.
Sur les deux serveurs maîtres installer tout d’abord le port sysutils/heartbeat (ou le paquet heartbeat). Les options de compilation par défaut sont suffisantes.
Dans un premier temps créez le fichier /usr/local/etc/ha.d/ha.cf, contenant la configuration globale de Heartbeat, suivant:
logfile /var/log/ha.log
logfacility local0
node DB1 DB2
auto_failback off
keepalive 1
deadtime 3
initdead 10
bcast bce1
udpport 694
deadping 3
ping 192.168.150.250
respawn hacluster /usr/local/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster
On applique ici la stratégie suivante:
Il faut maintenant configurer la stratégie de noeud heartbeat. Créez le fichier /usr/local/etc/ha.cf/haresources et insérez le contenu suivant
DB1 hastdev::mymasters 192.168.150.99 MailTo::admin@example.org
On déclare ici le noeud primaire par défaut DB1 qui devra lancer les ressources suivantes dans l’ordre:
Lors de la bascule (bascule forcée proprement), les tâches s’exécuteront dans l’ordre inverse.
Note: le noeud primaire ne reprendra pas la main s’il y a déjà un maître présent (directive initdead)
Puis on créée la clef d’authentification heartbeat entre les noeuds dans le fichier /usr/local/etc/ha.cf/authkeys
auth 1
1 sha1 mysqld-ha
Spécifiez ensuite les droits 600 sur le fichier, auquel cas heartbeat refusera de fonctionner:
chmod 600 /usr/local/etc/ha.cf/authkeys
Créez ensuite le fichier de ressource /usr/local/etc/ha.d/resources.d/hastdev avec le contenu suivant puis attribuez lui les droits d’écriture (chmod +x)
#!/bin/sh
#
#
# License: BSD
# usage: $0 {start|stop}
#
usage() {
echo "usage: $0 $LEGAL_ACTIONS"
exit 1
}
start() {
hastctl role primary $1
while [ ! -e /dev/hast/$1 ];
do
sleep 1;
done
fsck_ufs -y /dev/hast/$1
mount -o sync,noatime /dev/hast/$1 /mnt/$1
if [ $? -ne 0 ]; then
echo "Failed to mount /dev/hast/$1 (code $?)"
return 1;
fi
service mysql-server onestart
return 0
}
stop() {
service mysql-server onestop
umount /dev/hast/$1
sleep 1;
hastctl role secondary $1
return 0
}
case $2 in
start)
start $1
;;
stop)
stop $1
;;
*)
usage
exit 1
;;
esac
exit $?
Ce script heartbeat va se charger de basculer et monter le volume HAST précédemment créé et de démarrer le service MySQL. Il faut noter que le volume HAST est monté avec l’option sync garantissant l’écriture sur le disque, permettant de ne pas perdre de données en cas de bascule suite à une panne.
Note: si vous souhaitez l’utiliser sous Linux, remplacez onestart/onestop par start et stop et désactivez le service au niveau système.
La couche basse de notre cluster de maîtres MySQL étant maintenant rodée, il nous faut installer et configurer MySQL. Nous aurons ici besoin de MySQL 5.6 ou supérieur puisque nous allons utiliser les GTID. Installez le depuis les packages ou les ports (database/mysql56-server), suivant votre préférence, sur les deux serveurs maîtres.
pkg install mysql56-server
Créez le répertoire /mnt/mymasters et configurez MySQL au niveau du système afin qu’il utilise ce répertoire, correspondant au point de montage HAST
mkdir -p /mnt/mymasters
sysrc mysql_dbdir="/mnt/mymasters"
Créez ensuite le fichier /mnt/mymasters/my.cnf, contenant la configuration du serveur MySQL suivante:
[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 16K
max_allowed_packet = 1M
table_open_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 128K
server-id = 1
log-bin=mysql-bin
binlog_format=mixed
sync_binlog=1
gtid_mode = ON
log-slave-updates = ON
enforce-gtid-consistency = true
innodb_flush_log_at_trx_commit = 1
Nous ne nous attarderons pas sur le premier paragraphe de la configuration.
Pour la réplication, nous avons besoin de définir un server-id unique, notre maître redondé sera d’ID 1. On active ensuite les logs binaires du serveur maître afin que les esclaves puissent les lire.
Afin de garantir la cohérence des enregistrements sur le disque et éviter une perte de données, en cas de bascule, on va demander à la base MySQL de lancer des fsync sur le disque à chaque écriture et de flusher les logs InnoDB à chaque transaction. Cela rend la base plus lente en écriture mais assure la cohérence des données.
Enfin on active les GTID:
Lancez maintenant le service MySQL grâce à Heartbeat sur le noeud maître.
service heartbeat start
Une fois la base MySQL démarrée, lancez heartbeat sur le second noeud.
Connectez vous maintenant à la base SQL sur le noeud actif et créez un utilisateur de réplication:
CREATE USER 'repl'@'192.168.150.%' IDENTIFIED BY 'mypwd';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.150.%' IDENTIFIED BY 'mypwd';
Vos noeuds maîtres sont désormais prêts.
La configuration de nos noeuds esclaves sera relativement similaire aux noeuds maîtres
Installez tout d’abord le paquet/port mysql56-server
pkg install mysql56-server
Créez ensuite le fichier /var/db/mysql/my.cnf avec la section mysqld suivante:
[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 16K
max_allowed_packet = 1M
table_open_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 128K
server-id = 13
log-bin=mysql-bin
slave-net-timeout=5
gtid_mode = ON
log-slave-updates = ON
enforce-gtid-consistency = true
sync_master_info=1
master_info_repository=TABLE
sync_relay_log_info=1
relay_log_info_repository=TABLE
Je ne détaillerai pas ici les options précédémment définies. Interessons nous aux options qui diffèrent avec le maître:
Cette configuration permet d’obtenir un esclave crash-safe. Activez et lancez le service:
sysrc mysql_enable=YES
service mysql-server start
Connectez vous ensuite à la base de données et activez la réplication par GTID:
CHANGE MASTER TO
MASTER_HOST='192.168.150.99',
MASTER_USER='repl',
MASTER_PASSWORD='mypwd',
MASTER_AUTO_POSITION=1;
Enfin activez le processus slave:
START SLAVE;
Votre esclave est désormais opérationnel. Si vous souhaitez suivre l’état de la réplication, tapez
SHOW SLAVE STATUS;
Note: si vous activez la réplication sur une base maître déjà existante, n’oubliez pas de faire les étapes suivantes avant d’activer le slave:
Répétez les opérations précédentes sur chacun des esclaves que vous souhaitez créer (n’oubliez pas de changer le server-id).
Vous avez plusieurs moyens de basculer le noeud heartbeat:
Vérifiez ensuite l’état de la bascule en regardant le fichier /var/log/ha.log, et en tapant les commandes hastctl status et ps ax|grep mysql
Vérifiez également l’état de la réplication sur les esclaves au moyen de la commande MySQL SHOW SLAVE STATUS;
Vous avez plusieurs moyen de tester le noeud esclave:
Ce projet complet basé sur FreeBSD 9.3 et MySQL 5.6 vous permet d’appréhender et construire une architecture MySQL robuste et résiliente, utilisant des mécaniques de cluster lecture/écriture avec de multiples noeuds, au moyen d’une technique de réplication plus moderne (les GTIDs) et robuste que le curseur de logs binaires, tels qu’on le retrouve dans un cluster Galera.