MariaDB MaxScale è un proxy di database plug-in avanzato per i server di database MariaDB. Si trova tra le applicazioni client e i server di database, instradando le query dei client e le risposte del server. MaxScale monitora anche i server, quindi noterà rapidamente eventuali modifiche allo stato del server o alla topologia di replica. Ciò rende MaxScale una scelta naturale per il controllo del failover e di funzionalità simili.
In questa serie di blog in due parti forniremo una panoramica completa su come eseguire MariaDB MaxScale su Docker. Questa parte copre la distribuzione come container Docker autonomo e il clustering MaxScale tramite Docker Swarm per un'elevata disponibilità.
MariaDB MaxScale su Docker
Ci sono un certo numero di immagini Docker MariaDB disponibili in Docker Hub. In questo blog utilizzeremo l'immagine ufficiale mantenuta e pubblicata da MariaDB chiamata "mariadb/maxscale" (tag:latest). L'immagine ha una dimensione di circa 71 MB. Al momento della scrittura, l'immagine è preinstallata con MaxScale 2.3.4 come parte dei suoi pacchetti richiesti.
In genere, sono necessari i seguenti passaggi per eseguire MaxScale con questa immagine in un ambiente contenitore:
- Una replica MariaDB (master-slave o master-master) in esecuzione/Galera Cluster o NDB Cluster
- Crea e concedi un utente del database dedicato al monitoraggio di MaxScale
- Prepara il file di configurazione di MaxScale
- Mappa il file di configurazione nel container o caricalo in Kubernetes ConfigMap o Docker Swarm Configs
- Avvia il container/pod/service/replicaset
Nota che MaxScale è un prodotto di MariaDB, il che significa che è adattato al server MariaDB. La maggior parte delle funzionalità sono ancora compatibili con MySQL, ad eccezione di alcune parti come ad esempio la gestione di GTID, la configurazione di Galera Cluster e i file di dati interni. La versione che utilizzeremo è la 2.3.4, rilasciata sotto Business Source License (BSL). Consente a tutto il codice di essere aperto e l'utilizzo in TRE server è gratuito. Quando l'utilizzo supera tre server back-end, l'azienda che lo utilizza deve pagare un abbonamento commerciale. Dopo un periodo di tempo specifico (2 anni nel caso di MaxScale) il rilascio passa a GPL e tutto l'utilizzo è gratuito.
Giusto per essere chiari, poiché questo è un ambiente di test, possiamo avere più di 2 nodi. Come indicato nella pagina delle domande frequenti su MariaDB BSL:
D:Posso utilizzare i prodotti MariaDB con licenza BSL in un ambiente di test e sviluppo?
R:Sì, in un ambiente di test e sviluppo non di produzione, puoi utilizzare prodotti con licenza BSL senza che sia necessario un abbonamento da MariaDB
In questa procedura dettagliata, abbiamo già una replica MariaDB a tre nodi distribuita utilizzando ClusterControl. Il diagramma seguente illustra la configurazione che andremo a distribuire:
La nostra architettura di sistema è composta da:
- mariadb1 - 192.168.0.91 (maestro)
- mariadb2 - 192.168.0.92 (slave)
- mariadb3 - 192.168.0.93 (slave)
- docker1 - 192.168.0.200 (host Docker per contenitori - maxscale, app)
Preparazione dell'utente MaxScale
Innanzitutto, crea un utente del database MySQL per MaxScale e consenti a tutti gli host nella rete 192.168.0.0/24:
MariaDB> CREATE USER 'maxscale'@'192.168.0.%' IDENTIFIED BY 'my_s3cret';
Quindi, concedi i privilegi richiesti. Se vuoi solo monitorare i server back-end con il bilanciamento del carico, sarebbero sufficienti le seguenti sovvenzioni:
MariaDB> GRANT SHOW DATABASES ON *.* TO 'maxscale'@'192.168.0.%';
MariaDB> GRANT SELECT ON `mysql`.* TO 'maxscale'@'192.168.0.%';
Tuttavia, MaxScale può fare molto di più dell'instradamento delle query. Ha la capacità di eseguire il failover e il passaggio, ad esempio promuovendo uno slave a un nuovo master. Ciò richiede i privilegi SUPER e CLIENTE DI REPLICA. Se desideri utilizzare questa funzione, assegna invece TUTTI I PRIVILEGI all'utente:
mysql> GRANT ALL PRIVILEGES ON *.* TO [email protected]'192.168.0.%';
Questo è tutto per la parte utente.
Preparazione del file di configurazione MaxScale
L'immagine richiede che un file di configurazione funzionante venga mappato nel contenitore prima di essere avviata. Il file di configurazione minimo fornito nel contenitore non ci aiuterà a creare il proxy inverso che desideriamo. Pertanto, il file di configurazione deve essere preparato in anticipo.
Il seguente elenco può aiutarci a raccogliere le informazioni di base necessarie per costruire il nostro file di configurazione:
- Tipo di cluster:MaxScale supporta la replica MariaDB (master-slave, master-master), Galera Cluster, Amazon Aurora, MariaDB ColumnStore e NDB Cluster (noto anche come MySQL Cluster).
- Indirizzo IP di back-end e/o nome host:indirizzo IP o nome host raggiungibile per tutti i server di back-end.
- Algoritmo di routing:MaxScale supporta due tipi di routing delle query:suddivisione in lettura-scrittura e bilanciamento del carico in round-robin.
- Porta per l'ascolto di MaxScale - Per impostazione predefinita, MaxScale utilizza la porta 4006 per le connessioni round-robin e la 4008 per le connessioni divise in lettura e scrittura. Puoi usare il socket UNIX se vuoi.
Nella directory corrente, crea un file di testo chiamato maxscale.cnf in modo da poterlo mappare nel contenitore all'avvio. Incolla le seguenti righe nel file:
########################
## Server list
########################
[mariadb1]
type = server
address = 192.168.0.91
port = 3306
protocol = MariaDBBackend
serv_weight = 1
[mariadb2]
type = server
address = 192.168.0.92
port = 3306
protocol = MariaDBBackend
serv_weight = 1
[mariadb3]
type = server
address = 192.168.0.93
port = 3306
protocol = MariaDBBackend
serv_weight = 1
#########################
## MaxScale configuration
#########################
[maxscale]
threads = auto
log_augmentation = 1
ms_timestamp = 1
syslog = 1
#########################
# Monitor for the servers
#########################
[monitor]
type = monitor
module = mariadbmon
servers = mariadb1,mariadb2,mariadb3
user = maxscale
password = my_s3cret
auto_failover = true
auto_rejoin = true
enforce_read_only_slaves = 1
#########################
## Service definitions for read/write splitting and read-only services.
#########################
[rw-service]
type = service
router = readwritesplit
servers = mariadb1,mariadb2,mariadb3
user = maxscale
password = my_s3cret
max_slave_connections = 100%
max_sescmd_history = 1500
causal_reads = true
causal_reads_timeout = 10
transaction_replay = true
transaction_replay_max_size = 1Mi
delayed_retry = true
master_reconnection = true
master_failure_mode = fail_on_write
max_slave_replication_lag = 3
[rr-service]
type = service
router = readconnroute
servers = mariadb1,mariadb2,mariadb3
router_options = slave
user = maxscale
password = my_s3cret
##########################
## Listener definitions for the service
## Listeners represent the ports the service will listen on.
##########################
[rw-listener]
type = listener
service = rw-service
protocol = MariaDBClient
port = 4008
[ro-listener]
type = listener
service = rr-service
protocol = MariaDBClient
port = 4006
Un po' di spiegazioni per ogni sezione:
- Elenco server:i server back-end. Definire ogni server MariaDB di questo cluster nella propria stanza. Il nome della stanza verrà utilizzato quando specifichiamo la definizione del servizio più in basso. Il tipo di componente deve essere "server".
- Configurazione MaxScale - Definisci lì tutte le configurazioni relative a MaxScale.
- Modulo Monitor - Come MaxScale dovrebbe monitorare i server back-end. Il tipo di componente deve essere "monitor" seguito da uno dei moduli di monitoraggio. Per l'elenco dei monitor supportati, fare riferimento a Monitor MaxScale 2.3.
- Servizio - Dove instradare la query. Il tipo di componente deve essere "servizio". Per l'elenco dei router supportati, fare riferimento a Router MaxScale 2.3.
- Listener - Come MaxScale dovrebbe ascoltare le connessioni in entrata. Può essere un file di porta o socket. Il tipo di componente deve essere "ascoltatore". Di solito, gli ascoltatori sono legati ai servizi.
Quindi, in pratica, vorremmo che MaxScale fosse in ascolto su due porte, 4006 e 4008. La porta 4006 è specifica per la connessione round-robin, adatta per carichi di lavoro di sola lettura per la nostra replica MariaDB mentre la porta 4008 è specifica per carichi di lavoro critici di lettura e scrittura. Vogliamo anche utilizzare MaxScale per eseguire azioni sulla nostra replica in caso di failover, switchover o ricongiungimento slave, quindi utilizziamo il modulo monitor per chiamato "mariadbmon".
Eseguire il container
Ora siamo pronti per eseguire il nostro contenitore MaxScale autonomo. Mappa il file di configurazione con -v e assicurati di pubblicare entrambe le porte listener 4006 e 4008. Facoltativamente, puoi abilitare l'interfaccia API REST MaxScale sulla porta 8989:
$ docker run -d \
--name maxscale \
--restart always \
-p 4006:4006 \
-p 4008:4008 \
-p 8989:8989 \
-v $PWD/maxscale.cnf:/etc/maxscale.cnf \
mariadb/maxscale
Verifica con:
$ docker logs -f maxscale
...
2019-06-14 07:15:41.060 notice : (main): Started REST API on [127.0.0.1]:8989
2019-06-14 07:15:41.060 notice : (main): MaxScale started with 8 worker threads, each with a stack size of 8388608 bytes.
Assicurati di non vedere alcun errore quando guardi i log sopra. Verifica se i processi del proxy docker sono in ascolto sulle porte pubblicate - 4006, 4008 e 8989:
$ netstat -tulpn | grep docker-proxy
tcp6 0 0 :::8989 :::* LISTEN 4064/docker-proxy
tcp6 0 0 :::4006 :::* LISTEN 4092/docker-proxy
tcp6 0 0 :::4008 :::* LISTEN 4078/docker-proxy
A questo punto, il nostro MaxScale è in esecuzione ed è in grado di elaborare le query.
MaxCtrl
MaxCtrl è un client di amministrazione della riga di comando per MaxScale che utilizza l'API REST MaxScale per la comunicazione. È destinato a essere il software sostitutivo per il client della riga di comando MaxAdmin legacy.
Per accedere alla console MaxCtrl, esegui il comando "maxctrl" all'interno del contenitore:
$ docker exec -it maxscale maxctrl
maxctrl: list servers
┌──────────┬──────────────┬──────┬─────────────┬─────────────────┬─────────────┐
│ Server │ Address │ Port │ Connections │ State │ GTID │
├──────────┼──────────────┼──────┼─────────────┼─────────────────┼─────────────┤
│ mariadb1 │ 192.168.0.91 │ 3306 │ 0 │ Master, Running │ 0-5001-1012 │
├──────────┼──────────────┼──────┼─────────────┼─────────────────┼─────────────┤
│ mariadb2 │ 192.168.0.92 │ 3306 │ 0 │ Slave, Running │ 0-5001-1012 │
├──────────┼──────────────┼──────┼─────────────┼─────────────────┼─────────────┤
│ mariadb3 │ 192.168.0.93 │ 3306 │ 0 │ Slave, Running │ 0-5001-1012 │
└──────────┴──────────────┴──────┴─────────────┴─────────────────┴─────────────┘
Per verificare se tutto è a posto, esegui semplicemente i seguenti comandi:
maxctrl: list servers
maxctrl: list services
maxctrl: list filters
maxctrl: list sessions
Per avere maggiori informazioni su ogni componente, prefisso invece il comando "show", ad esempio:
maxctrl: show servers
┌──────────────────┬──────────────────────────────────────────┐
│ Server │ mariadb3 │
├──────────────────┼──────────────────────────────────────────┤
│ Address │ 192.168.0.93 │
├──────────────────┼──────────────────────────────────────────┤
│ Port │ 3306 │
├──────────────────┼──────────────────────────────────────────┤
│ State │ Slave, Running │
├──────────────────┼──────────────────────────────────────────┤
│ Last Event │ new_slave │
├──────────────────┼──────────────────────────────────────────┤
│ Triggered At │ Mon, 17 Jun 2019 08:57:59 GMT │
├──────────────────┼──────────────────────────────────────────┤
│ Services │ rw-service │
│ │ rr-service │
├──────────────────┼──────────────────────────────────────────┤
│ Monitors │ monitor │
├──────────────────┼──────────────────────────────────────────┤
│ Master ID │ 5001 │
├──────────────────┼──────────────────────────────────────────┤
│ Node ID │ 5003 │
├──────────────────┼──────────────────────────────────────────┤
│ Slave Server IDs │ │
├──────────────────┼──────────────────────────────────────────┤
│ Statistics │ { │
│ │ "connections": 0, │
│ │ "total_connections": 0, │
│ │ "persistent_connections": 0, │
│ │ "active_operations": 0, │
│ │ "routed_packets": 0, │
│ │ "adaptive_avg_select_time": "0ns" │
│ │ } │
├──────────────────┼──────────────────────────────────────────┤
│ Parameters │ { │
│ │ "address": "192.168.0.93", │
│ │ "protocol": "MariaDBBackend", │
│ │ "port": 3306, │
│ │ "extra_port": 0, │
│ │ "authenticator": null, │
│ │ "monitoruser": null, │
│ │ "monitorpw": null, │
│ │ "persistpoolmax": 0, │
│ │ "persistmaxtime": 0, │
│ │ "proxy_protocol": false, │
│ │ "ssl": "false", │
│ │ "ssl_cert": null, │
│ │ "ssl_key": null, │
│ │ "ssl_ca_cert": null, │
│ │ "ssl_version": "MAX", │
│ │ "ssl_cert_verify_depth": 9, │
│ │ "ssl_verify_peer_certificate": true, │
│ │ "disk_space_threshold": null, │
│ │ "type": "server", │
│ │ "serv_weight": "1" │
│ │ } │
└──────────────────┴──────────────────────────────────────────┘
Connessione al database
L'utente del database dell'applicazione deve essere concesso all'host MaxScale poiché dal punto di vista del server MariaDB può vedere solo l'host MaxScale. Considera il seguente esempio senza MaxScale nell'immagine:
- Nome database:myapp
- Utente:myapp_user
- Host:192.168.0.133 (server delle applicazioni)
Per consentire all'utente di accedere al database all'interno del server MariaDB, è necessario eseguire la seguente istruzione:
MariaDB> CREATE USER 'myapp_user'@'192.168.0.133' IDENTIFIED BY 'mypassword';
MariaDB> GRANT ALL PRIVILEGES ON myapp.* to 'myapp_user'@'192.168.0.133';
Con MaxScale nell'immagine, è necessario eseguire invece la seguente istruzione (sostituire l'indirizzo IP del server delle applicazioni con l'indirizzo IP MaxScale, 192.168.0.200):
MariaDB> CREATE USER 'myapp_user'@'192.168.0.200' IDENTIFIED BY 'mypassword';
MariaDB> GRANT ALL PRIVILEGES ON myapp.* to 'myapp_user'@'192.168.0.200';
Dall'applicazione, ci sono due porte che puoi usare per connetterti al database:
- 4006 - Listener round-robin, adatto per carichi di lavoro di sola lettura.
- 4008 - Listener diviso in lettura-scrittura, adatto per carichi di lavoro in scrittura.
Se la tua applicazione può specificare solo una porta MySQL (ad es. Wordpress, Joomla, ecc.), scegli invece la porta RW 4008. Questa è la connessione endpoint più sicura indipendentemente dal tipo di cluster. Tuttavia, se la tua applicazione può gestire connessioni a più porte MySQL, puoi inviare le letture al listener round-robin. Questo listener ha meno sovraccarico e molto più veloce rispetto al listener diviso in lettura-scrittura.
Per la nostra configurazione di replica MariaDB, connettiti a uno di questi endpoint come combinazione host/porta del database:
- 192.168.0.200 porta 4008 - MaxScale - lettura/scrittura o sola scrittura
- 192.168.0.200 porta 4006 - MaxScale - sola lettura bilanciata
- 192.168.0.91 porta 3306 - MariaDB Server (master) - lettura/scrittura
- 192.168.0.92 porta 3306 - MariaDB Server (slave) - sola lettura
- 192.168.0.93 porta 3306 - MariaDB Server (slave) - sola lettura
Nota per il tipo di cluster multi-master come Galera Cluster e NDB Cluster, la porta 4006 può essere utilizzata invece come connessioni bilanciate multi-scrittura. Con MaxScale hai molte opzioni tra cui scegliere quando ti connetti al database, ognuna con i propri vantaggi.
Clustering MaxScale con Docker Swarm
Con Docker Swarm, possiamo creare un gruppo di istanze MaxScale tramite il servizio Swarm con più di una replica insieme a Swarm Configs. Innanzitutto, importa il file di configurazione in Swarm:
$ cat maxscale.conf | docker config create maxscale_config -
Verifica con:
$ docker config inspect --pretty maxscale_config
Quindi, concedi all'utente del database MaxScale di connettersi da qualsiasi host Swarm nella rete:
MariaDB> CREATE USER 'maxscale'@'192.168.0.%' IDENTIFIED BY 'my_s3cret';
MariaDB> GRANT ALL PRIVILEGES ON *.* TO [email protected]'192.168.0.%';
Quando si avvia il servizio Swarm per MaxScale, è possibile creare più container (chiamati repliche) mappati sullo stesso file di configurazione come di seguito:
$ docker service create \
--name maxscale-cluster \
--replicas=3 \
--publish published=4008,target=4008 \
--publish published=4006,target=4006 \
--config source=maxscale_config,target=/etc/maxscale.cnf \
mariadb/maxscale
Quanto sopra creerà tre contenitori MaxScale distribuiti tra i nodi Swarm. Verifica con:
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
yj6u2xcdj7lo maxscale-cluster replicated 3/3 mariadb/maxscale:latest *:4006->4006/tcp, *:4008->4008/tcp
Se le applicazioni sono in esecuzione all'interno della rete Swarm, puoi semplicemente utilizzare il nome del servizio "maxscale-cluster" come host del database per le tue applicazioni. Esternamente, puoi connetterti a qualsiasi host Docker sulle porte pubblicate e la rete Swarm instraderà e bilancerà le connessioni ai contenitori corretti in modalità round robin. A questo punto la nostra architettura può essere illustrata come segue:
Nella seconda parte, esamineremo casi d'uso avanzati di MaxScale su Docker come il controllo del servizio, la gestione della configurazione, l'elaborazione delle query, la sicurezza e la riconciliazione del cluster.