Evidian SafeKit apporte la haute disponibilité à MySQL. Cet article explique comment mettre en œuvre rapidement un cluster MySQL sans disque partagé et sans compétences spécifiques. Le module de haute disponibilité mysql.safe et un essai gratuit sont offerts dans la section instructions d'installation.
Cette solution de clustering est reconnue comme la plus simple à mettre en œuvre par nos clients et partenaires. C'est également une solution complète qui résout les pannes matérielles (20% des problèmes) incluant la panne complète d'une salle informatique, les défaillances logicielles (40% des problèmes) incluant le passage d'update serveur par serveur et les erreurs humaines (40% des problèmes) grâce à sa simplicité.
Sur la figure précédente, le serveur 1 / PRIM exécute les services MySQL. Les utilisateurs sont connectés à l'adresse IP virtuelle du cluster miroir. SafeKit réplique les fichiers ouverts par les services MySQL en temps réel. Seules les modifications apportées aux fichiers sont répliquées sur le réseau, limitant ainsi le trafic (réplication de fichiers au niveau octet). Les noms des répertoires de fichiers contenant les données des services MySQL sont simplement configurés dans SafeKit. Il n'existe pas de pré-requis sur l'organisation des disques entre les deux serveurs. Les répertoires à répliquer peuvent se trouver dans le disque système. SafeKit met en œuvre une réplication synchrone sans perte de données en cas de panne, contrairement à une réplication asynchrone.
En cas de défaillance du serveur 1, il y a un basculement automatique sur le serveur 2 avec redémarrage des services MySQL. Ensuite, lorsque le serveur 1 est redémarré, SafeKit met en œuvre son retour automatique dans le cluster avec la réintégration des données sans arrêter les services MySQL sur le serveur 2. Enfin, le système retourne à la réplication synchrone entre le serveur 2 et le serveur 1. L'administrateur peut décider d'échanger le rôle du primaire et du secondaire pour revenir à un serveur 1 qui exécute les services MySQL. Ce changement de rôle peut également être fait automatiquement par configuration.
Sur les deux serveurs Windows
Sur les deux serveurs Linux
La configuration est présentée avec la console web connectée à 2 serveurs Windows mais c'est la même chose avec 2 serveurs Linux.
Important : toute la configuration est réalisée à partir d'un seul navigateur.
Lancez la console Web dans un navigateur en vous connectant à http://localhost:9010 (image suivante)
Entrez l'adresse IP du premier nœud et cliquez sur Confirm (image suivante)
Cliquez sur New node et entrez l'adresse IP du deuxième nœud (image suivante)
Cliquez sur la disquette rouge pour sauvegarder la configuration (image précédente)
Dans l'onglet Configuration, cliquez sur mysql.safe puis entrez mysql comme nom du module et cliquez sur Confirm : images suivantes avec mysql au lieu de xxx
Cliquez sur Validate (image suivante)
Modifiez le chemin des répertoires répliqués uniquement si nécessaire (image suivante) et entrez une adresse IP virtuelle. Une adresse IP virtuelle est une nouvelle adresse IP inutilisée dans le même réseau IP que les adresses IP des deux nœuds. L'adresse IP virtuelle bascule automatiquement en cas de panne.
Pour information:
Cliquez sur Validate (image précédente)
Cliquez sur Configure (image précédente)
Vérifiez le message succès vert sur les deux serveurs et cliquez sur Next (image précédente). Sous Linux, vous pouvez avoir une erreur à cette étape si les répertoires répliqués sont des points de montage. Voir cet article pour résoudre le problème.
Sélectionnez le nœud avec les répertoires répliqués les plus récents et cliquez sur Start it pour effectuer la première resynchronisation dans la bonne direction (image précédente). Avant cette opération, nous vous suggérons de faire une copie des répertoires répliqués avant de démarrer le cluster pour éviter toute erreur.
Démarrer le deuxième nœud (image précédente) qui devient SECOND vert (image suivante) après la resynchronisation de tous les répertoires répliqués (copie binaire du nœud 1 vers le nœud 2).
Le cluster est opérationnel avec les services MySQL s'exécutant sur le nœud PRIM et ne s'exécutant pas sur le nœud SECOND (image précédente). Seules les modifications à l'intérieur des fichiers sont répliquées en temps réel dans cet état.
Attention, les composants qui sont clients des services MySQL doivent être configurés avec l'adresse IP virtuelle. La configuration peut être effectuée avec un nom DNS (si un nom DNS a été créé et associé à l'adresse IP virtuelle).
Vérifiez avec la console Microsoft Management Console (MMC) sous Windows ou avec des lignes de commande sous Linux que les services MySQL sont démarrés sur le serveur primaire et arrêtés sur le serveur secondaire.
Arrêtez le nœud PRIM en faisant défiler le menu du nœud primaire et en cliquant sur Stop. Vérifiez qu'il y a un basculement sur le nœud SECOND. Et vérifiez le basculement des services MySQL avec la console Microsoft Management Console (MMC) sous Windows ou avec des lignes de commande sous Linux.
Pour comprendre ce qui se passe dans le cluster, consultez les journaux SafeKit du serveur primaire et du serveur secondaire.
Pour voir le journal du module sur le serveur primaire (image suivante) :
Pour voir le journal applicatif du serveur primaire (image suivante) :
Pour voir les journaux du serveur secondaire (image précédente), cliquez à gauche sur W12R2server75/SECOND (il deviendra bleu) et répétez les mêmes opérations. Vous trouverez dans le log du module secondaire le volume et le temps de réintégration des données répliquées.
Dans l'onglet Advanced Configuration (image suivante), vous pouvez modifier les fichiers internes au module : bin/start_prim et bin/stop_prim et conf/userconfig.xml (image suivante sur le côté gauche). Si vous faites des changements dans les fichiers internes ici, vous devez appliquer la nouvelle configuration par un clic droit sur l'icône bleue/xxx sur le côté gauche (image suivante) : l'interface vous permettra de redéployer les fichiers modifiés sur les deux serveurs.
Configure boot start (image suivante sur le côté droit) configure le démarrage automatique du module au boot du serveur. Effectuez cette configuration sur les deux serveurs une fois que la solution de haute disponibilité fonctionne correctement.
Pour obtenir de l'aide sur le centre d'appel de https://support.evidian.com, prenez 2 Snaphots (2 fichiers .zip), un pour chaque serveur et téléchargez-les dans l'outil du centre d'appel (image suivante).
userconfig.xml
<!DOCTYPE safe>
<safe>
<service mode="mirror" defaultprim="alone" maxloop="3" loop_interval="24" failover="on">
<!-- Heartbeat Configuration -->
<!-- Names or IP addresses on the default network are set during initialization in the console -->
<heart pulse="700" timeout="30000">
<heartbeat name="default" ident="flow">
</heartbeat>
</heart>
<!-- Virtual IP Configuration -->
<!-- Replace
* VIRTUAL_TO_BE_DEFINED by the name of your virtual server
-->
<vip>
<interface_list>
<interface check="on" arpreroute="on">
<real_interface>
<virtual_addr addr="VIRTUAL_TO_BE_DEFINED" where="one_side_alias" />
</real_interface>
</interface>
</interface_list>
</vip>
<!-- Software Error Detection Configuration -->
<errd polltimer="10">
<!-- MySQL Server -->
<proc name="mysqld.exe" atleast="1" action="restart" class="prim" />
</errd>
<!-- File Replication Configuration -->
<!--
* C:\ProgramData\MySQL\MySQL Server 5.7: default directory containing MySQL database and logs
-->
<rfs async="second" acl="off" nbrei="3">
<replicated dir="C:\ProgramData\MySQL\MySQL Server 5.7" mode="read_only" />
</rfs>
<!-- User scripts activation -->
<user nicestoptimeout="300" forcestoptimeout="300" logging="userlog" />
</service>
</safe>
start_prim.cmd
@echo off
rem Script called on the primary server for starting application services
rem For logging into SafeKit log use:
rem "%SAFE%\safekit" printi | printe "message"
rem stdout goes into Application log
echo "Running start_prim %*"
set res=0
net start mysql > nul
if not %errorlevel% == 0 (
%SAFE%\safekit printi "MySQL start failed"
) else (
%SAFE%\safekit printi "MySQL started"
)
if %res% == 0 goto end
:stop
set res=%errorlevel%
"%SAFE%\safekit" printe "start_prim failed"
rem uncomment to stop SafeKit when critical
rem "%SAFE%\safekit" stop -i "start_prim"
:end
stop_prim.cmd
@echo off
rem Script called on the primary server for stopping application services
rem ----------------------------------------------------------
rem
rem 2 stop modes:
rem
rem - graceful stop
rem call standard application stop with net stop
rem
rem - force stop (%1=force)
rem kill application's processes
rem
rem ----------------------------------------------------------
rem For logging into SafeKit log use:
rem "%SAFE%\safekit" printi | printe "message"
rem stdout goes into Application log
echo "Running stop_prim %*"
set res=0
rem default: no action on forcestop
if "%1" == "force" goto end
%SAFE%\safekit printi "Stopping MySQL..."
net stop mysql > nul
rem wait a little for a real stop of services
%SAFEBIN%\sleep 10
:end
userconfig.xml
<!DOCTYPE safe>
<safe>
<service mode="mirror" defaultprim="alone" maxloop="3" loop_interval="24" failover="on">
<!-- Heartbeat Configuration -->
<!-- Names or IP addresses on the default network are set during initialization in the console -->
<heart pulse="700" timeout="30000">
<heartbeat name="default" ident="flow">
</heartbeat>
</heart>
<!-- Virtual IP Configuration -->
<!-- Replace
* VIRTUAL_TO_BE_DEFINED by the name of your virtual server
-->
<vip>
<interface_list>
<interface check="on" arpreroute="on">
<real_interface>
<virtual_addr addr="VIRTUAL_TO_BE_DEFINED" where="one_side_alias"/>
</real_interface>
</interface>
</interface_list>
</vip>
<!-- Software Error Detection Configuration -->
<errd polltimer="10">
<!-- MySQL Server -->
<proc name="mysqld" atleast="1" action="restart" class="prim" />
</errd>
<!-- File Replication Configuration -->
<!--
* /var/lib/mysql: default directory of MySQL database and logs
-->
<rfs mountover="off" async="second" acl="off" nbrei="3">
<replicated dir="/var/lib/mysql" mode="read_only" />
</rfs>
<!-- User scripts activation -->
<user nicestoptimeout="300" forcestoptimeout="300" logging="userlog" />
</service>
</safe>
start_prim
#!/bin/sh
# Script called on the primary server for starting applications
# For logging into SafeKit log use:
# $SAFE/safekit printi | printe "message"
#---------- Clean MYSQL residual processes
# Call this function before starting any MySQL databases
# to clean eventual resual MySQL processes
clean_mysql()
{
retval=0
$SAFE/safekit printw "Cleaning MySQL processes"
# kill started MySQL processes
ps -e -o pid,comm | grep mysql | $AWK '{print "kill " $1}'| sh >/dev/null 2>&1
return $retval
}
#---------- MySQL Databases
# Call this function for starting MySQL Server
start_MySQL()
{
retval=0
$SAFE/safekit printw "Starting MySQL Server"
# MySQL - Database Starting
service mysqld start
if [ $? -ne 0 ] ; then
$SAFE/safekit printw "MySQL server start failed"
else
$SAFE/safekit printw "MySQL server started"
fi
return $retval
}
# stdout goes into Application log
echo "Running start_prim $*"
res=0
[ -z "$OSNAME" ] && OSNAME=`uname -s`
OSNAME=`uname -s`
case "$OSNAME" in
Linux)
AWK=/bin/awk
;;
*)
AWK=/usr/bin/awk
;;
esac
# TODO
# remove MySQL boot start
# Clean MySQL residual processes
clean_mysql || res=$?
# Start MySQL databases
start_MySQL || res=$?
if [ $res -ne 0 ] ; then
$SAFE/safekit printi "start_prim failed"
# uncomment to stop SafeKit when critical
# $SAFE/safekit stop -i "start_prim"
fi
exit 0
stop_prim
#!/bin/sh
# Script called on the primary server for stopping application services
# For logging into SafeKit log use:
# $SAFE/safekit printi | printe "message"
#----------------------------------------------------------
#
# 2 stop modes:
#
# - graceful stop
# call standard application stop
#
# - force stop ($1=force)
# kill application's processes
#
#----------------------------------------------------------
#---------- Clean MySQL residual processes
# Call this function on force stop
# to clean eventual resual MySQL processes
clean_mysql()
{
retval=0
$SAFE/safekit printw "Cleaning MySQL processes "
# kill started MySQL
ps -e -o pid,comm | grep mysql | $AWK '{print "kill -9 " $1}'| sh >/dev/null 2>&1
return $retval
}
#---------- MySQL databases
# Call this function for stopping MySQL databases
stop_MySQL()
{
retval=0
if [ "$1" = "force" ] ; then
# MySQL databases force stop
clean_mysql
return $retval
fi
# MySQL databases graceful stop
$SAFE/safekit printw "Stopping MySQL server"
service mysqld stop
if [ $? -ne 0 ] ; then
$SAFE/safekit printw "MySQL server stop failed"
else
$SAFE/safekit printw "MySQL server stopped"
fi
return $retval
}
# stdout goes into Application log
echo "Running stop_prim $*"
res=0
[ -z "$OSNAME" ] && OSNAME=`uname -s`
case "$OSNAME" in
Linux)
AWK=/bin/awk
;;
*)
AWK=/usr/bin/awk
;;
esac
mode=
if [ "$1" = "force" ] ; then
mode=force
shift
fi
# Stop MySQL server
stop_MySQL $mode || res=$?
[ $res -ne 0 ] && $SAFE/safekit printi "stop_prim failed"
exit 0