Implémentation d'une haute disponibilité MySQL avec MHA

Principes et architecture de MHA

MHA (Master High Availability) est une solution de résilience éprouvée pour les déploiements MySQL. Développée en Perl, cette suite d'outils automatise la détection de panne et la promotion d'un nœud répliqué vers le rôle principal. En cas d'indisponibilité du serveur maître, le processus de basculement s'exécute généralement entre 0 et 30 secondes, en préservant l'intégrité des transactions.

Contrairement à d'autres approches nécessitant une réplication maître-maître, MHA fonctionne sur une topologie classique maître-réplique. Lors d'une défaillance, le superviseur analyse les journaux des esclaves pour identifier celui disposant des données les plus récentes, puis le promeut. La communication entre les composants repose exclusivement sur des connexions SSH authentifiées par clé, permettant l'exécution distante des commandes de gestion.

Fonctionnalités principales

  • Surveillance continue de la disponibilité du nœud maître.
  • Élection automatique du nouveau maître parmi les répliques en cas de défaillance.
  • Extraction forcée des événements du journal binaire (binlog) du maître tombé en panne afin de minimiser la perte de données. Cette opération échoue uniquement si le matériel hôte est irrémédiablement inaccessible.
  • Compatibilité avec la réplication semi-synchrone pour réduire les risques de divergence entre les répliques.
  • Support natif des modes de réplication basés sur les positions de journal et sur les identifiants globaux de transaction (GTID).

Séquence de basculement

  1. Connexion SSH au maître défaillant pour extraire les derniers événements binaires non transmis.
  2. Analyse des répliques pour déterminer laquelle possède l'horloge de transaction la plus avancée.
  3. Synchronisation des journaux relais (relay logs) manquants vers les autres répliques.
  4. Application des événements binaires extraits du maître initial sur la réplique candidate.
  5. Promotion de la réplique candidate vers le statut maître.
  6. Reconfiguration des autres répliques pour pointer vers le nouveau maître.
  7. Migration de l'adresse IP virtuelle (VIP) vers le nouveau nœud principal pour assurer la continuité des connexions applicatives.

Préparation de l'environnement

Le scénario décrit ci-après concerne un cluster composé d'un maître, de deux répliques et d'un serveur de supervision dédié. Les étapes d'installation de MySQL étant supposées accomplies, nous nous concentrerons sur la configuraton de la réplication et de MHA.

1. Définition des comptes de réplication

CREATE USER 'agent_repl'@'%' IDENTIFIED WITH mysql_native_password BY 'ReplSecur123!';
GRANT REPLICATION SLAVE ON *.* TO 'agent_repl'@'%';
FLUSH PRIVILEGES;

2. Ajustement des paramètres du moteur

Chaque nœud doit posséder un identifiant unique. Le maître et les répliques doivent activer la journalisation binaire et le mode GTID.

[mysqld]
# Maître
server-id = 101
log-bin = primary_bin
relay-log = primary_relay
log-slave-updates = ON
gtid-mode = ON
enforce-gtid-consistency = ON

# Réplique 1
server-id = 102
# Réplique 2
server-id = 103

3. Initialisation du flux de réplication

CHANGE MASTER TO 
  MASTER_HOST='192.168.10.50', 
  MASTER_PORT=3306, 
  MASTER_USER='agent_repl', 
  MASTER_PASSWORD='ReplSecur123!';
START SLAVE;

4. Configuration des accès distants

Générez une paire de clés RSA sur chaque machine et distribuez les clés publiques via ssh-copy-id pour établir une confiance mutuelle sans mot de passe entre tous les composants du cluster.

5. Installation des composants MHA

Installez les dépendances Perl nécessaires, puis déployez le paquet mha4mysql-node sur les bases de données et mha4mysql-manager sur le serveur de supervision.

6. Paramétrage du superviseur

[server default]
user = admin_mha
password = MhaMonit0r!
manager_workdir = /opt/mha/work
manager_log = /opt/mha/work/supervisor.log
remote_workdir = /opt/mha/work
ssh_user = root
repl_user = agent_repl
repl_password = ReplSecur123!
ping_interval = 2
master_binlog_dir = /var/lib/mysql
master_ip_failover_script = /usr/local/sbin/gestion_vip.pl
secondary_check_script = /usr/local/bin/masterha_secondary_check -s 192.168.10.50 -s 192.168.10.51 -s 192.168.10.52

[server1]
hostname = 192.168.10.50
candidate_master = 1

[server2]
hostname = 192.168.10.51
candidate_master = 1

[server3]
hostname = 192.168.10.52
candidate_master = 1

7. Script de migration de l'adresse IP virtuelle

MHA ne fournissant pas de gestionnaire VIP natif, un script Perl doit être fourni pour activer/désactiver l'adresse flottante via SSH. Voici une implémentation refactisée :

#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long qw(GetOptions);

my ($action, $user_ssh, $host_ancien, $ip_ancien, $port_ancien,
    $host_nouveau, $ip_nouveau, $port_nouveau,
    $port_ssh_ancien, $port_ssh_nouveau,
    $login_nouveau, $pass_nouveau);

my $adresse_virtuelle = '192.168.10.100/24';
my $suffixe_alias = 'vip01';
my $interface_reseau = 'eth0';

my $cmd_activer  = "sudo /sbin/ip addr add $adresse_virtuelle dev $interface_reseau:$suffixe_alias";
my $cmd_desactiver = "sudo /sbin/ip addr del $adresse_virtuelle dev $interface_reseau:$suffixe_alias";
my $cmd_arp      = "sudo /sbin/arping -I $interface_reseau -c 3 -A 192.168.10.100";

GetOptions(
    'action=s'            => \$action,
    'user_ssh=s'          => \$user_ssh,
    'host_ancien=s'       => \$host_ancien,
    'ip_ancien=s'         => \$ip_ancien,
    'port_ancien=i'       => \$port_ancien,
    'host_nouveau=s'      => \$host_nouveau,
    'ip_nouveau=s'        => \$ip_nouveau,
    'port_nouveau=i'      => \$port_nouveau,
    'port_ssh_ancien=i'   => \$port_ssh_ancien,
    'port_ssh_nouveau=i'  => \$port_ssh_nouveau,
    'login_nouveau=s'     => \$login_nouveau,
    'pass_nouveau=s'      => \$pass_nouveau
) or &afficher_aide();

exit &executer();

sub executer {
    $user_ssh //= 'root';
    print "\n=== Début du traitement VIP ===\n";
    
    if ($action eq 'stop' || $action eq 'stopssh') {
        eval {
            print "Désactivation sur l'ancien maître : $host_ancien\n";
            &retirer_vip();
        };
        if ($@) {
            warn "Erreur capturée : $@\n";
            return 1;
        }
        return 0;
    }
    elsif ($action eq 'start') {
        &installer_vip();
        &diffuser_arp();
        return 0;
    }
    elsif ($action eq 'status') {
        print "Vérification du statut : Opérationnel\n";
        return 0;
    }
    
    &afficher_aide();
    return 1;
}

sub installer_vip {
    system("ssh $user_ssh\@$host_nouveau '$cmd_activer'");
}

sub retirer_vip {
    system("ssh $user_ssh\@$host_ancien '$cmd_desactiver'");
}

sub diffuser_arp {
    system("ssh $user_ssh\@$host_nouveau '$cmd_arp'");
}

sub afficher_aide {
    print "Usage: $0 --action=start|stop|stopssh|status --user_ssh=root --host_ancien=... --host_nouveau=...\n";
}

Attribuez les permissions d'exécution au script et créez le compte de supervision SQL :

CREATE USER 'admin_mha'@'%' IDENTIFIED WITH mysql_native_password BY 'MhaMonit0r!';
GRANT ALL PRIVILEGES ON *.* TO 'admin_mha'@'%';
FLUSH PRIVILEGES;

8. Validation des connexions et démarrage

masterha_check_ssh --conf=/etc/mha/app1.cnf
masterha_check_repl --conf=/etc/mha/app1.cnf
nohup masterha_manager --conf=/etc/mha/app1.cnf > /opt/mha/work/manager.out 2>&1 &

9. Attribution initiale de l'adresse virtuelle

sudo /sbin/ip addr add 192.168.10.100/24 dev eth0: vip01

Atouts et contraintes

Points forts :

  • Code source entièrement ouvert et extensible en Perl.
  • Compatibilité avec les mécanismes GTID et position-based.
  • Extraction des dernières transacsions binaires pour limiter les pertes de données lors du basculement.
  • Capacité d'un seul superviseur à gérer plusieurs topologies de réplication distinctes.

Limitations :

  • Aucun gestionnaire d'adresse IP virtuelle intégré : nécessitant un script personnalisé ou l'usage d'outils tiers.
  • La supervision se concentre exclusivement sur le nœud principal et l'état de réplication, sans monitorer la charge ou la santé individuelle des répliques.
  • Dépendance à la configuration SSH trustless, ce qui impose une sécurisation rigoureuse du réseau interne.
  • Absence de répartition de charge pour les requêtes de lecture sur les répliques, nécessitant l'ajout d'un proxy ou d'un routeur d'applications.

Étiquettes: MySQL MHA RepriseSurIncident RepliqueBaseDeDonnees AdministrationSysteme

Publié le 19 septembre à 14h57