Replicación Master Esclavo de MariaDB en Contenedores Docker

Introducción

Una de las funciones principales de MariaDB es la replicación Master Esclavo. Como se explica en la documentación:

La replicación es una funcionalidad que permite que el contenido de uno o más servidores (llamados masters) sea duplicado en uno o más servidores (llamados esclavos).

Vamos a crear una Replicación Master Esclavo básica de dos nodos usando Contenedores de Docker en una Virtual Machine de la Google Cloud Platform.
Previamente habíamos instalado y configurado una Replicación Master Esclavo de MariaDB en Instancias Virtuales, esta vez haremos lo mismo pero usando contenedores.

Prerrequisitos

Un anfitrión de Docker en cualquier Sistema Operativo. Nosotros estamos usando una virtual machine instance en Google Cloud Platform con Container Optimized OS el cual ya incluye el Docker 19.03.

Crear Contenedores de MariaDB

Crear un Red de Docker

Con el fin de facilitar la referencia entre los nodos del cluster vamos a usar nuestra propia red de docker tipo bridge previamente creada para que ambos contenedores puedan encontrarse a través de su nombre:

pato@patocontainer ~ $ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
...
522c4b821356        pato-net            bridge              local

Generar Contenedores a partir de nuestra Imagen Customizada

Creemos nuestros contenedores con el comando docker run usando nuestra imagen personalizada patomx/patomariadb. Para más información sobre esta imagen visita Mi Imagen y Volumen de MariaDB en Docker.

Usaremos la red previamente creada --network pato-net y le asignaremos una etiqueta al volumen para el datadir-v patovolgm:/var/lib/mysql.

pato@patocontainer ~ $ docker run -d --name patomariadb --network pato-net -v patovoldb:/var/lib/mysql patomx/patomariadb
9480dd3937c18a034406875f9f2e8b3c39dafff65e677052f8bc39d763df2734

pato@patocontainer ~ $ docker run -d --name patomariarp --network pato-net -v patovolrp:/var/lib/mysql patomx/patomariadb
638f5ce36f85c6a64b3b684c59cd5ddf9b6fcd705389fbc4a7face0f674c0a90

pato@patocontainer ~ $ docker stop patomariadb patomariarp
patovoldb
patovolrp

Una vez creados replicaremos los datos de nuestra base de datos customizada hacia los volúmenes de los nuevos contenedores:

pato@patocontainer ~ $ docker run --rm -i -t -v patovolmariadb:/origen -v patovoldb:/destino alpine sh -c "cp -avr /origen/* /destino"
'/origen/aria_log.00000001' -> '/destino/aria_log.00000001'
'/origen/aria_log_control' -> '/destino/aria_log_control'
...
pato@patocontainer ~ $ docker run --rm -i -t -v patovolmariadb:/origen -v patovolrp:/destino alpine sh -c "cp -avr /origen/* /destino"
...

Iniciemos los contenedores y validemos que estén en ejecución:

pato@patocontainer ~ $ docker start patomariadb patomariarp
patomariadb
patomariarp

pato@patocontainer ~ $ docker container ls
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS               NAMES
638f5ce36f85        patomx/patomariadb   "docker-entrypoint.s…"   6 minutes ago       Up 18 seconds       3306/tcp            patomariarp
9480dd3937c1        patomx/patomariadb   "docker-entrypoint.s…"   7 minutes ago       Up 19 seconds       3306/tcp            patomariadb


pato@patocontainer ~ $ docker volume ls
DRIVER              VOLUME NAME
local               patovoldb
local               patovolmariadb
local               patovolrp

Replicación Master Esclavo

Configurar la Replicación en el Master

Accede a nuestro recién creado contenedor con una sesión shell usando docker exec -it patomariadb bash y genera el archivo de configuración, definiendo el identificador único server_id y el nombre y formato del binary log:

pato@patocontainer ~ $ docker exec -it patomariadb bash
root@9480dd3937c1:/# nano /etc/mysql/conf.d/replication.cnf
# MariaDB Replication Configuration
[mariadb]
server_id=1
log_bin=master-bin
binlog-format=mixed
log_slave_updates=on

Luego conéctate a la base de datos y crea un usuario para la replicación:

pato@9480dd3937c1:/# mysql

MariaDB [(none)]> GRANT REPLICATION SLAVE ON *.* TO 'replicador'@'%' IDENTIFIED BY '********';
Query OK, 0 rows affected (0.007 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.015 sec)

Finalmente reinicia el contenedor de la base de datos para que la nuevo configuración se cargue:

pato@patocontainer ~ $ docker restart patomariadb

Configurar la Replicación en el Esclavo

Accede a nuestro recién creado contenedor con una sesión shell usando docker exec -it patomariarp bash y genera el archivo de configuración, definiendo el identificador único server_id y el nombre y formato del binary log:

pato@patocontainer ~ $ docker exec -it patomariarp bash
root@638f5ce36f85:/# nano /etc/mysql/conf.d/replication.cnf
# MariaDB Replication Configuration
[mariadb]
server_id=11
log_bin=slave-bin
binlog-format=mixed
log_slave_updates=on

Finalmente reinicia el contenedor de la base de datos para que la nuevo configuración se cargue:

pato@patocontainer ~ $ docker restart patomariarp

Generar Datos y Objetos de Prueba

Conéctate a la base de datos Master y genera una tabla e insértale un registro:

pato@patocontainer ~ $ docker exec -it --user pato patomariadb bash
pato@9480dd3937c1:/$ mysql
MariaDB [(none)]> create database taller ;
Query OK, 1 row affected (0.012 sec)

MariaDB [(none)]> use taller;
Database changed
MariaDB [taller]> create table r1 (i1 int auto_increment primary key, c1 varchar(20), d1 datetime) ;
Query OK, 0 rows affected (0.085 sec)

MariaDB [taller]> insert into r1 (c1,d1) values ('Before Master Slave',now());
Query OK, 1 row affected (0.021 sec)

MariaDB [taller]> commit ;
Query OK, 0 rows affected (0.000 sec)

MariaDB [taller]> select * from r1;
+----+---------------------+---------------------+
| i1 | c1                  | d1                  |
+----+---------------------+---------------------+
|  1 | Before Master Slave | 2020-05-22 17:49:14 |
+----+---------------------+---------------------+
1 row in set (0.000 sec)

Copia Inicial de Datos

Congela toda la actividad en la base de datos Master:

pato@patocontainer ~ $ docker exec -it --user pato patomariadb bash
pato@9480dd3937c1:~$ mysql
MariaDB [(none)]> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (0.013 sec)

Entonces respalda la base de datos Master:

pato@9480dd3937c1:~$ mysqldump --all-databases > masterfull.sql
pato@9480dd3937c1:~$ mysql

Obtén las coordenadas del binary log para el punto de comienzo de la replicación:

MariaDB [(none)]> SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 |     1029 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.000 sec)

Descongela la actividad en el Master:

MariaDB [(none)]> UNLOCK TABLES;
Query OK, 0 rows affected (0.000 sec)

Restaurar el Replado en el Esclavo

Transfiere el respaldo del nodo Master al nodo Esclavo:

pato@patocontainer ~ $ docker cp patomariadb:/home/pato/masterfull.sql .

pato@patocontainer ~ $ docker cp masterfull.sql patomariarp:/home/pato

Restaura el respaldo:

pato@patocontainer ~ $ docker exec -it --user pato patomariarp bash
pato@638f5ce36f85:~$ mysql < masterfull.sql

Iniciar la Replicación

Configura la base de datos Esclavo con la posición del binlog master-bin.000001 - 1029 de la copia inicial y luego modifica la replicación para usar la posición GTID:

pato@638f5ce36f85:~$ mysql

MariaDB [(none)]> CHANGE MASTER TO
    ->    MASTER_HOST='patomariadb',
    ->    MASTER_USER='replicador',
    ->    MASTER_PASSWORD='********',
    ->    MASTER_PORT=3306,
    ->    MASTER_LOG_FILE='master-bin.000001',
    ->    MASTER_LOG_POS=1029,
    ->    MASTER_CONNECT_RETRY=10;
Query OK, 0 rows affected (0.117 sec)

MariaDB [(none)]> CHANGE MASTER TO MASTER_USE_GTID = slave_pos ;
Query OK, 0 rows affected (0.011 sec)

Inicia el Esclavo y valida su estatus:

MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.024 sec)

MariaDB [(none)]> SHOW SLAVE STATUS \G
*************************** 1. row ***************************
                Slave_IO_State: Waiting for master to send event
                   Master_Host: patomariadb
                   Master_User: replicador
                   Master_Port: 3306
                 Connect_Retry: 10
               Master_Log_File: master-bin.000001
           Read_Master_Log_Pos: 1029
                Relay_Log_File: mysqld-relay-bin.000002
                 Relay_Log_Pos: 1329
         Relay_Master_Log_File: master-bin.000001
              Slave_IO_Running: Yes
             Slave_SQL_Running: Yes
...
                    Using_Gtid: Slave_Pos
                   Gtid_IO_Pos: 0-1-4
...
       Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
...
1 row in set (0.001 sec)

¡Perfecto, nuestra replicación Master Esclavo está configurada y corriendo!

Probar la Replicación Master Esclavo

Con el fin de validar que la replicación está funcionando vamos a crear una tabla más e insertar datos:

pato@patocontainer ~ $ docker exec -it --user pato patomariadb bash
pato@9480dd3937c1:/$ mysql
MariaDB [(none)]> use taller
Database changed
MariaDB [taller]> create table r2 (i2 int auto_increment primary key, c2 varchar(20), d2 datetime) ;
Query OK, 0 rows affected (0.153 sec)

MariaDB [taller]> insert into r2 (c2,d2) values ('After Master Slave',now());
Query OK, 1 row affected (0.018 sec)

MariaDB [taller]> commit;
Query OK, 0 rows affected (0.000 sec)

MariaDB [taller]> select * from r2;
+----+--------------------+---------------------+
| i2 | c2                 | d2                  |
+----+--------------------+---------------------+
|  1 | After Master Slave | 2020-05-22 18:00:10 |
+----+--------------------+---------------------+
1 row in set (0.033 sec)

Verifica que los datos y objetos se replicaron desde el Master hacia el Esclavo, tanto los que vienen de la copia inicial table r1 - Before Master Slave como aquellos que vienen de la replicación table r2 - After Master Slave:

pato@patocontainer ~ $ docker exec -it --user pato patomariarp bash
pato@638f5ce36f85:/$ mysql
MariaDB [(none)]> use taller
Database changed

MariaDB [taller]> select * from r1;
+----+---------------------+---------------------+
| i1 | c1                  | d1                  |
+----+---------------------+---------------------+
|  1 | Before Master Slave | 2020-05-22 17:49:14 |
+----+---------------------+---------------------+
1 row in set (0.026 sec)

MariaDB [taller]> select * from r2;
+----+--------------------+---------------------+
| i2 | c2                 | d2                  |
+----+--------------------+---------------------+
|  1 | After Master Slave | 2020-05-22 18:00:10 |
+----+--------------------+---------------------+
1 row in set (0.000 sec)

¡Los datos y la tabla fueron replicados desde el Master hacia el Esclavo!

Conclusión

Hemos generado y configurado existosamente la Replicación Master Esclavo usando contenedores de Docker dentro de una virtual machine de la Google Cloud Platform y validado que estén funcionando.
Como puedes notar la configuración básica es bastante sencilla. Después de esto puedes intentar más funcionalidades como el filtrado de tablas, failover y switchover, así como múltiples esclavos.