Crear clúster MariaDB

Esta entrada es una guía para desplegar un clúster de MariaDB en CentOS 7, aunque es aplicable para cualquier otra distribución (Debian, Ubuntu, Suse…).

Añadir el repositorio de MariaDB

El primer paso es agregar el repositorio de la versión de MariaDB y para la distribución donde se hará el despliegue, en este caso de MariaDB 10.1 para CentOS 7.

1
2
3
4
5
6
7
8
9
cat << EOF >> /etc/yum.repos.d/MariaDB.repo
# MariaDB 10.1 CentOS repository list
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.1/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
EOF

Instalar MariaDB

1
yum install -y MariaDB-server MariaDB-client

Preparar los nodos del clúster MariaDB

En todos los del cluster, iniciar MariaDB y crear el usuario que se usará para la sincronización:

1
2
3
4
5
systemctl start mariadb
mysql_secure_installation
mysql -uroot -p -e "CREATE USER sst_user@'%' IDENTIFIED BY 'password-here';"
mysql -uroot -p -e "GRANT ALL PRIVILEGES ON *.* TO sst_user@'%';"
mysql -uroot -p -e "FLUSH PRIVILEGES;"

Configurar los nodos del clúster MariaDB

Para levantar un cluster MariaDB basado el Galera es necesario configurar los siguientes parámetros en /etc/my.cnf.d/server.cnf.

  • wsrep_on, determina si la replicación está activa o no.
  • wsrep_provider, especifica la localización de la biblioteca wsrep.
  • wsrep_cluster_name, especifica el nombre del clúster. Sin este parámetro es posible levantar el clúster, pero no es recomendable; además en caso de querer añadir árbitros (Galera Arbitrator) es indispensable.
  • wsrep_cluster_address, especifica los nodos del clúster de acuerdo al formato gcomm:<ip>,<ip>,<ip>. Si se especifica vacío, gcom://, el nodo creará un nuevo clúster, por este motivo no es buena idea dejarlo vacío en los archivos de configuración de MariaDB de lo contrario se creará un nuevo clúster con cada reinicio.
  • wsrep_node_address, indica la IP del nodo.
  • wsrep_node_name, indica el nombre del nodo.
  • wsrep_sst_auth, indica el usuario y contraseña que se usará para la sincronización entre los nodos del clúster. Debe especificarse como usuario:contraseña.
  • wsrep_sst_method, indica el método usado para la transferencia de estado, `state snapshot transfer (sst), los valores posibles son rsync (por defecto), mysqldump, xtrabackup, xtrabackup-v2. Actualmente ninguna versión de xtrabackup soporta Global Transaction ID (GTID).
  • wsrep_retry_autocommit, número de reintentos de commit, debido a conflictos dentro del cluster, antes de volver un error al cliente. El valor por defecto es 1.
  • innodb_autoinc_lock_mode, modo de bloqueo usado para generar los valores de auto-incremento. En el caso de tratarse de un cluster Galera debe configurarse en 2.
  • default_storage_engine, motor de de la base de datos por defecto.
  • binlog_format, determina el tipo de replicación. Lo normal es replicación basada en filas (row).

Crear el clúster MariaDB

El último paso es crear el clúster y añadir los nodos. Es importante entender en que consistente crear el clúster. Cuando no existe nigún nodo activo, se dice que el clúster ha sido destruido, al no existir el clúster ningún nodo puede vincularse a él.

En este estado, el primer paso es crear el clúster para ello es necesario iniciar MariaDB con el parámetro --wsrep-new-cluster; esto hará que se inicie MariaDB y cree el clúster. Posteriormente tan solo es necesario iniciar el demonio MariaDB en el resto de nodos de forma normal.

Es importante tener en cuenta varias cosas:

  • Cada nodo que se inicie con el parámetro --wsrep-new-cluster, creará un clúster independiente; por este motivo solo un nodo debería iniciarse con el parámetro --wsrep-new-cluster.
  • El nodo que se inicia con el parámetro --wsrep-new-cluster, será el nodo principal lo que implica que cualquier nodo que se una al clúster se sincronizará con él y en caso de discrepancia prevalecerán los datos del nodo principal. Esto solo ocurre cuando el nodo se una al clúster, una vez el nodo es miembro del clúster las discrepancias se solventan mediante votaciones de los nodos (quorum), por este motivo es importante tener un número impar de nodos o en su defecto tener un árbitro (Galera Arbitrator) para evitar situaciones de votaciones divididas (split-brain).
  • En caso de que se destruya el clúster (se desconectan todos los nodos), es importante que el nodo que se inicie con el parámetro --wsrep-new-cluster sea el último nodo que se apago, es decir, el nodo más actualizado. Si crea el clúster con un nodo al azar, se perderán datos.

Ejemplo de clúster de tres nodos

Configuración de los nodos

A continuación un ejemplo para configurar un clúster de MariaDB con tres nodos:

  • MariaDB-01 con IP 192.168.100.104
  • MariaDB-02 con IP 192.168.1.104
  • MariaDB-03 con IP 192.168.50.104

La configuración del primer nodo, MariaDB-01, sería:

1
2
3
4
5
6
7
8
9
10
11
[galera]
wsrep_on=ON
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_cluster_name="MariaDB-Cluster"
wsrep_cluster_address=gcomm://192.168.100.104,192.168.1.104,192.168.50.104
wsrep_node_address='192.168.100.104'
wsrep_node_name='MariaDB01'
wsrep_sst_auth=sst_user:my-password
wsrep_sst_method=rsync
binlog_format=row
innodb_autoinc_lock_mode=2

Crear el clúster

Antes de poder iniciar un clúster MariaDB basado en Galera, es necesario que un nodo cree el clúster, para cual solo es necesario iniciar el demonio MariaDB con el parámetro --wsrep-new-cluster.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@MariaDB ~]# service mysql start --wsrep-new-cluster
Starting mysql (via systemctl): [ OK ]
[root@MariaDB ~]# systemctl status mariadb -l
mariadb.service - MariaDB database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled)
Drop-In: /etc/systemd/system/mariadb.service.d
└─migrated-from-my.cnf-settings.conf
Active: active (running) since Fri 2017-07-08 14:50:16 UTC; 3s ago
Main PID: 2703 (mysqld)
Status: "Taking your SQL requests now..."
CGroup: /lxc/100104/system.slice/mariadb.service
└─2703 /usr/sbin/mysqld
Jul 08 14:50:16 MariaDB mysqld[2703]: 2017-07-08 14:50:16 140688496950016 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification.
Jul 08 14:50:16 MariaDB mysqld[2703]: 2017-07-08 14:50:16 140688496950016 [Note] WSREP: REPL Protocols: 7 (3, 2)
Jul 08 14:50:16 MariaDB mysqld[2703]: 2017-07-08 14:50:16 140688497264768 [Note] /usr/sbin/mysqld: ready for connections.
Jul 08 14:50:16 MariaDB mysqld[2703]: Version: '10.1.14-MariaDB' socket: '/var/lib/mysql/mysql.sock' port: 3306 MariaDB Server
Jul 08 14:50:16 MariaDB mysqld[2703]: 2017-07-08 14:50:16 140688259806976 [Note] WSREP: Service thread queue flushed.
Jul 08 14:50:16 MariaDB mysqld[2703]: 2017-07-08 14:50:16 140688496950016 [Note] WSREP: Assign initial position for certification: 0, protocol version: 3
Jul 08 14:50:16 MariaDB mysqld[2703]: 2017-07-08 14:50:16 140688259806976 [Note] WSREP: Service thread queue flushed.
Jul 08 14:50:16 MariaDB mysqld[2703]: 2017-07-08 14:50:16 140688496950016 [Note] WSREP: Synchronized with group, ready for connections
Jul 08 14:50:16 MariaDB mysqld[2703]: 2017-07-08 14:50:16 140688496950016 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification.
Jul 08 14:50:16 MariaDB systemd[1]: Started MariaDB database server.

Unir nodos al clúster

A continuación solo es necesario iniciar el demonio MariaDB en el resto de nodos.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@MariaDB03 ~]# systemctl status mariadb
● mariadb.service - MariaDB database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/mariadb.service.d
└─migrated-from-my.cnf-settings.conf
Active: active (running) since Wed 2017-07-08 15:38:41 UTC; 12s ago
Main PID: 1029 (mysqld)
Status: "Taking your SQL requests now..."
CGroup: /lxc/100114/system.slice/mariadb.service
└─1029 /usr/sbin/mysqld
Jul 08 15:38:41 MariaDB03 mysqld[1029]: 2017-07-08 15:38:41 140431313041536 [Note] WSREP: SST received: f34703fa-43a4-11e6-85e9-bbcfcbd42fe0:0
Jul 08 15:38:41 MariaDB03 mysqld[1029]: 2017-07-08 15:38:41 140431002167040 [Note] WSREP: 0.0 (MariaDB03): State transfer from 1.0 (MariaDB...omplete.
Jul 08 15:38:41 MariaDB03 mysqld[1029]: 2017-07-08 15:38:41 140431002167040 [Note] WSREP: Shifting JOINER -> JOINED (TO: 0)
Jul 08 15:38:41 MariaDB03 mysqld[1029]: 2017-07-08 15:38:41 140431002167040 [Note] WSREP: Member 0.0 (MariaDB03) synced with group.
Jul 08 15:38:41 MariaDB03 mysqld[1029]: 2017-07-08 15:38:41 140431002167040 [Note] WSREP: Shifting JOINED -> SYNCED (TO: 0)
Jul 08 15:38:41 MariaDB03 mysqld[1029]: 2017-07-08 15:38:41 140431312726784 [Note] WSREP: Synchronized with group, ready for connections
Jul 08 15:38:41 MariaDB03 mysqld[1029]: 2017-07-08 15:38:41 140431312726784 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification.
Jul 08 15:38:41 MariaDB03 mysqld[1029]: 2017-07-08 15:38:41 140431313041536 [Note] /usr/sbin/mysqld: ready for connections.
Jul 08 15:38:41 MariaDB03 mysqld[1029]: Version: '10.1.14-MariaDB' socket: '/var/lib/mysql/mysql.sock' port: 3306 MariaDB Server
Jul 08 15:38:41 MariaDB03 systemd[1]: Started MariaDB database server.
Hint: Some lines were ellipsized, use -l to show in full.

Posibles errores

En una instalación limpia de CentOS 7, al crear el clúster y tratar de unir el primer nodo, obtenía el siguiente error:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@MariaDB03 my.cnf.d]# systemctl -l status mariadb
● mariadb.service - MariaDB database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/mariadb.service.d
└─migrated-from-my.cnf-settings.conf
Active: failed (Result: exit-code) since Wed 2017-07-08 15:24:02 UTC; 10min ago
Process: 916 ExecStart=/usr/sbin/mysqld $MYSQLD_OPTS $_WSREP_NEW_CLUSTER (code=exited, status=1/FAILURE)
Main PID: 916 (code=exited, status=1/FAILURE)
Status: "MariaDB server is down"
Jul 08 15:23:53 MariaDB03 mysqld[916]: /usr//bin/wsrep_sst_common: line 120: which: command not found
Jul 08 15:23:53 MariaDB03 mysqld[916]: 2017-07-08 15:23:53 139626329143040 [ERROR] WSREP: Failed to read 'ready <addr>' from: wsrep_sst_rsync --role 'joiner' --address '192.168.100.114' --datadir '/var/lib/mysql/' --parent '916' ''
Jul 08 15:23:53 MariaDB03 mysqld[916]: Read: '(null)'
Jul 08 15:23:53 MariaDB03 mysqld[916]: 2017-07-08 15:23:53 139626329143040 [ERROR] WSREP: Process completed with error: wsrep_sst_rsync --role 'joiner' --address '192.168.100.114' --datadir '/var/lib/mysql/' --parent '916' '' : 2 (No such file or directory)
Jul 08 15:23:53 MariaDB03 mysqld[916]: 2017-07-08 15:23:53 139626669431552 [ERROR] WSREP: Failed to prepare for 'rsync' SST. Unrecoverable.
Jul 08 15:23:53 MariaDB03 mysqld[916]: 2017-07-08 15:23:53 139626669431552 [ERROR] Aborting
Jul 08 15:24:02 MariaDB03 systemd[1]: mariadb.service: main process exited, code=exited, status=1/FAILURE
Jul 08 15:24:02 MariaDB03 systemd[1]: Failed to start MariaDB database server.
Jul 08 15:24:02 MariaDB03 systemd[1]: Unit mariadb.service entered failed state.
Jul 08 15:24:02 MariaDB03 systemd[1]: mariadb.service failed.

Al ejecutar wsrep_sst_rsync se ve claramente el problema:

1
2
3
4
[root@MariaDB03 my.cnf.d]# find / -name wsrep_sst_rsync 2>/dev/null
/usr/bin/wsrep_sst_rsync
[root@MariaDB03 my.cnf.d]# /usr/bin/wsrep_sst_rsync
/usr/bin/wsrep_sst_common: line 120: which: command not found

Así que la solución pasó por un simple yum install which.

Más información

Entradas de interés

Contenidos
  1. 1. Añadir el repositorio de MariaDB
  2. 2. Instalar MariaDB
  3. 3. Preparar los nodos del clúster MariaDB
  4. 4. Configurar los nodos del clúster MariaDB
  5. 5. Crear el clúster MariaDB
  6. 6. Ejemplo de clúster de tres nodos
    1. 6.1. Configuración de los nodos
    2. 6.2. Crear el clúster
    3. 6.3. Unir nodos al clúster
  7. 7. Posibles errores
  8. 8. Más información