MySQL Replication è un modo molto diffuso per creare livelli di database ad alta disponibilità. È molto conosciuto, testato e robusto. Non è senza limitazioni, però. Uno di questi, sicuramente, è il fatto che utilizza solo un "punto di ingresso":hai un server dedicato nella topologia, il master, ed è l'unico nodo nel cluster a cui puoi inviare scritture. Ciò porta a gravi conseguenze:il master è l'unico punto di errore e, in caso di errore, nessuna scrittura può essere eseguita dall'applicazione. Non sorprende che sia stato dedicato molto lavoro allo sviluppo di strumenti che ridurrebbe l'impatto di una perdita master. Certo, ci sono discussioni su come affrontare l'argomento, il failover automatico è migliore di quello manuale o meno. Alla fine, questa è una decisione aziendale da prendere, ma se dovessi decidere di seguire il percorso di automazione, cercherai gli strumenti per aiutarti a raggiungerlo. Uno degli strumenti, ancora molto popolare, è MHA (Master High Availability). Anche se forse non viene più mantenuto attivamente, è ancora in una forma stabile e la sua enorme popolarità lo rende ancora la spina dorsale delle configurazioni di replica MySQL ad alta disponibilità. Cosa accadrebbe, tuttavia, se lo stesso MHA non fosse disponibile? Può diventare un singolo punto di errore? C'è un modo per evitare che accada? In questo post del blog daremo un'occhiata ad alcuni scenari.
Per prima cosa, se prevedi di utilizzare MHA, assicurati di utilizzare l'ultima versione del repository. Non utilizzare versioni binarie in quanto non contengono tutte le correzioni. L'installazione è abbastanza semplice. MHA è composto da due parti, manager e nodo. Il nodo deve essere distribuito sui server di database. Manager verrà distribuito su un host separato, insieme al nodo. Quindi, server di database:nodo, host di gestione:manager e nodo.
È abbastanza facile compilare MHA. Vai a GitHub e clona i repository.
https://github.com/yoshinorim/mha4mysql-manager
https://github.com/yoshinorim/mha4mysql-node
Poi si tratta di:
perl Makefile.PL
make
make install
Potrebbe essere necessario installare alcune dipendenze perl se non hai già installato tutti i pacchetti richiesti. Nel nostro caso, su Ubuntu 16.04, abbiamo dovuto installare quanto segue:
perl -MCPAN -e "install Config::Tiny"
perl -MCPAN -e "install Log::Dispatch"
perl -MCPAN -e "install Parallel::ForkManager"
perl -MCPAN -e "install Module::Install"
Una volta installato MHA, è necessario configurarlo. Non entreremo nei dettagli qui, ci sono molte risorse su Internet che coprono questa parte. Una configurazione di esempio (decisamente non di produzione) potrebbe assomigliare a questa:
[email protected]:~# cat /etc/app1.cnf
[server default]
user=cmon
password=pass
ssh_user=root
# working directory on the manager
manager_workdir=/var/log/masterha/app1
# working directory on MySQL servers
remote_workdir=/var/log/masterha/app1
[server1]
hostname=node1
candidate_master=1
[server2]
hostname=node2
candidate_master=1
[server3]
hostname=node3
no_master=1
Il prossimo passo sarà vedere se tutto funziona e come MHA vede la replica:
[email protected]:~# masterha_check_repl --conf=/etc/app1.cnf
Tue Apr 9 08:17:04 2019 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Tue Apr 9 08:17:04 2019 - [info] Reading application default configuration from /etc/app1.cnf..
Tue Apr 9 08:17:04 2019 - [info] Reading server configuration from /etc/app1.cnf..
Tue Apr 9 08:17:04 2019 - [info] MHA::MasterMonitor version 0.58.
Tue Apr 9 08:17:05 2019 - [error][/usr/local/share/perl/5.22.1/MHA/MasterMonitor.pm, ln427] Error happened on checking configurations. Redundant argument in sprintf at /usr/local/share/perl/5.22.1/MHA/NodeUtil.pm line 195.
Tue Apr 9 08:17:05 2019 - [error][/usr/local/share/perl/5.22.1/MHA/MasterMonitor.pm, ln525] Error happened on monitoring servers.
Tue Apr 9 08:17:05 2019 - [info] Got exit code 1 (Not master dead).
Bene, si è schiantato. Questo perché MHA tenta di analizzare la versione di MySQL e non si aspetta trattini al suo interno. Fortunatamente, la soluzione è facile da trovare:https://github.com/yoshinorim/mha4mysql-manager/issues/116.
Ora abbiamo MHA pronto per il lavoro.
[email protected]:~# masterha_manager --conf=/etc/app1.cnf
Tue Apr 9 13:00:00 2019 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Tue Apr 9 13:00:00 2019 - [info] Reading application default configuration from /etc/app1.cnf..
Tue Apr 9 13:00:00 2019 - [info] Reading server configuration from /etc/app1.cnf..
Tue Apr 9 13:00:00 2019 - [info] MHA::MasterMonitor version 0.58.
Tue Apr 9 13:00:01 2019 - [info] GTID failover mode = 1
Tue Apr 9 13:00:01 2019 - [info] Dead Servers:
Tue Apr 9 13:00:01 2019 - [info] Alive Servers:
Tue Apr 9 13:00:01 2019 - [info] node1(10.0.0.141:3306)
Tue Apr 9 13:00:01 2019 - [info] node2(10.0.0.142:3306)
Tue Apr 9 13:00:01 2019 - [info] node3(10.0.0.143:3306)
Tue Apr 9 13:00:01 2019 - [info] Alive Slaves:
Tue Apr 9 13:00:01 2019 - [info] node2(10.0.0.142:3306) Version=5.7.25-28-log (oldest major version between slaves) log-bin:enabled
Tue Apr 9 13:00:01 2019 - [info] GTID ON
Tue Apr 9 13:00:01 2019 - [info] Replicating from 10.0.0.141(10.0.0.141:3306)
Tue Apr 9 13:00:01 2019 - [info] Primary candidate for the new Master (candidate_master is set)
Tue Apr 9 13:00:01 2019 - [info] node3(10.0.0.143:3306) Version=5.7.25-28-log (oldest major version between slaves) log-bin:enabled
Tue Apr 9 13:00:01 2019 - [info] GTID ON
Tue Apr 9 13:00:01 2019 - [info] Replicating from 10.0.0.141(10.0.0.141:3306)
Tue Apr 9 13:00:01 2019 - [info] Not candidate for the new Master (no_master is set)
Tue Apr 9 13:00:01 2019 - [info] Current Alive Master: node1(10.0.0.141:3306)
Tue Apr 9 13:00:01 2019 - [info] Checking slave configurations..
Tue Apr 9 13:00:01 2019 - [info] Checking replication filtering settings..
Tue Apr 9 13:00:01 2019 - [info] binlog_do_db= , binlog_ignore_db=
Tue Apr 9 13:00:01 2019 - [info] Replication filtering check ok.
Tue Apr 9 13:00:01 2019 - [info] GTID (with auto-pos) is supported. Skipping all SSH and Node package checking.
Tue Apr 9 13:00:01 2019 - [info] Checking SSH publickey authentication settings on the current master..
Tue Apr 9 13:00:02 2019 - [info] HealthCheck: SSH to node1 is reachable.
Tue Apr 9 13:00:02 2019 - [info]
node1(10.0.0.141:3306) (current master)
+--node2(10.0.0.142:3306)
+--node3(10.0.0.143:3306)
Tue Apr 9 13:00:02 2019 - [warning] master_ip_failover_script is not defined.
Tue Apr 9 13:00:02 2019 - [warning] shutdown_script is not defined.
Tue Apr 9 13:00:02 2019 - [info] Set master ping interval 3 seconds.
Tue Apr 9 13:00:02 2019 - [warning] secondary_check_script is not defined. It is highly recommended setting it to check master reachability from two or more routes.
Tue Apr 9 13:00:02 2019 - [info] Starting ping health check on node1(10.0.0.141:3306)..
Tue Apr 9 13:00:02 2019 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..
Come puoi vedere, MHA sta monitorando la nostra topologia di replica, controllando se il nodo master è disponibile o meno. Consideriamo un paio di scenari.
Scenario 1 - MHA si è bloccato
Supponiamo che MHA non sia disponibile. In che modo questo influisce sull'ambiente? Ovviamente, poiché MHA è responsabile del monitoraggio dello stato di salute del master e del failover del trigger, ciò non accadrà quando MHA è inattivo. Il crash principale non verrà rilevato, il failover non si verificherà. Il problema è che non puoi davvero eseguire più istanze MHA contemporaneamente. Tecnicamente, puoi farlo anche se MHA si lamenterà del file di blocco:
[email protected]:~# masterha_manager --conf=/etc/app1.cnf
Tue Apr 9 13:05:38 2019 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Tue Apr 9 13:05:38 2019 - [info] Reading application default configuration from /etc/app1.cnf..
Tue Apr 9 13:05:38 2019 - [info] Reading server configuration from /etc/app1.cnf..
Tue Apr 9 13:05:38 2019 - [info] MHA::MasterMonitor version 0.58.
Tue Apr 9 13:05:38 2019 - [warning] /var/log/masterha/app1/app1.master_status.health already exists. You might have killed manager with SIGKILL(-9), may run two or more monitoring process for the same application, or use the same working directory. Check for details, and consider setting --workdir separately.
Si avvierà, tuttavia, e tenterà di monitorare l'ambiente. Il problema è quando entrambi iniziano a eseguire azioni sul cluster. Il caso peggiore sarebbe se decidono di utilizzare slave diversi come candidato master e il failover verrà eseguito contemporaneamente (MHA utilizza un file di blocco che impedisce il verificarsi di failover successivi ma se tutto accade contemporaneamente, ed è successo nel nostro test, questa misura di sicurezza non è sufficiente).
Sfortunatamente, non esiste un modo integrato per eseguire MHA in modo altamente disponibile. La soluzione più semplice sarà scrivere uno script che verificherà se MHA è in esecuzione e, in caso contrario, lo avvii. Tale script dovrebbe essere eseguito da cron o scritto sotto forma di demone, se 1 minuto di granularità di cron non è sufficiente.
Scenario 2 - Il nodo MHA Manager ha perso la connessione di rete al master
Siamo onesti, questa è davvero una brutta situazione. Non appena MHA non riesce a connettersi al master, tenterà di eseguire un failover. L'unica eccezione è se secondary_check_script è definito e ha verificato che il master è attivo. Spetta all'utente definire esattamente quali azioni MHA deve eseguire per verificare lo stato del master:tutto dipende dall'ambiente e dalla configurazione esatta. Un altro script molto importante da definire è master_ip_failover_script:viene eseguito in caso di failover e dovrebbe essere utilizzato, tra l'altro, per garantire che il vecchio master non venga visualizzato. Se ti capita di avere accesso a modi aggiuntivi per raggiungere e fermare il vecchio maestro, è davvero fantastico. Può essere strumenti di gestione remota come Integrated Lights-out, può essere l'accesso a prese di alimentazione gestibili (dove è possibile semplicemente spegnere il server), può essere l'accesso alla CLI del provider cloud, che consentirà di arrestare l'istanza virtuale . È della massima importanza fermare il vecchio master, altrimenti può succedere che, dopo che il problema di rete è scomparso, ti ritroverai con due nodi scrivibili nel sistema, che è una soluzione perfetta per il cervello diviso, una condizione in cui dati divergenti tra due parti dello stesso cluster.
Come puoi vedere, MHA può gestire abbastanza bene il failover di MySQL. Richiede sicuramente un'attenta configurazione e dovrai scrivere script esterni, che verranno utilizzati per uccidere il vecchio maestro e garantire che il cervello diviso non si verifichi. Detto questo, consigliamo comunque di utilizzare strumenti di gestione del failover più avanzati come Orchestrator o ClusterControl, che possono eseguire analisi più avanzate dello stato della topologia di replica (ad esempio, utilizzando slave o proxy per valutare la disponibilità del master) e che sono e sarà mantenuto in futuro. Se sei interessato a sapere come ClusterControl esegue il failover, ti invitiamo a leggere questo post sul blog sul processo di failover in ClusterControl. Puoi anche scoprire come ClusterControl interagisce con ProxySQL offrendo un failover fluido e trasparente per la tua applicazione. Puoi sempre testare ClusterControl scaricandolo gratuitamente.