Skip to content

Instalar un ndb cluster de mysql en Ubuntu

by Gonzalo on 24 noviembre, 2011

A medida que nuestros servicios crecen (buena señal ;) ) veremos que uno de los primeros servicios con el que tenemos problemas de redimensionamiento es con las BBDD MySQL.
A mucha gente no se le ocurre otra solución que poner más y más RAM y CPU’s. Aunque llega un momento que obviamente ya no podemos poner más.
En estos casos la solución pasa por montar un cluster de MySQL, que nos permite redimensionar introduciendo nuevos nodos a medida que necesitamos más recursos.
Este cluster obviamente también tiene sus limitaciones y llegados a un punto en el que también se nos quede corto y necesitemos una BBDD para mover un mounstruo tipo Facebook o algo muy grande, creo que ya os prodiais permitir pagar a un experto en el tema o simplemente no necesitaríais estar leyendo esto.

Para hacernos una idea de que va la cosa podemos empezar por leer:
http://dev.mysql.com/doc/refman/5.0/es/ndbcluster.html
y
http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-replication.html

Como véis hay un MGM o Management node (que ejecuta el demonio “ndb_mgmd”) y los Nodos (ejecutando el servicio ndbd).
Después de un tiempo leyendo y habiendo aprendido los conceptos generales, empezamos:

Instalación MGM o Management node

Para instalar el MGM en ubuntu, teóricamente tendría que ser tan fácil como hacer:
# apt-get install mysql-server
# apt-get install mysql-cluster-server

No obstante instalar el paquete ‘mysql-cluster-server’ en Lucid 10.04 LTS3 (a día de hoy) es tarea de locos por temas de dependencias incumplidas.
Si hacemos eso, al instalar mysql-cluster-server-5.1 nos sale este error:

dpkg: error al procesar /var/cache/apt/archives/mysql-cluster-client-5.1_7.0.9-1ubuntu7_amd64.deb (--unpack):
 intentando sobreescribir `/usr/bin/mysql', que está también en el paquete mysql-client-core-5.1 0:5.1.41-3ubuntu12.10
dpkg-deb: el subproceso copiado fue terminado por la señal (Tubería rota)
Seleccionando el paquete mysql-cluster-server-5.1 previamente no seleccionado.
Desempaquetando mysql-cluster-server-5.1 (de .../mysql-cluster-server-5.1_7.0.9-1ubuntu7_amd64.deb) ...
dpkg: error al procesar /var/cache/apt/archives/mysql-cluster-server-5.1_7.0.9-1ubuntu7_amd64.deb (--unpack):
 intentando sobreescribir `/usr/bin/my_print_defaults', que está también en el paquete mysql-server-core-5.1 0:5.1.41-3ubuntu12.10
dpkg-deb: el subproceso copiado fue terminado por la señal (Tubería rota)
Seleccionando el paquete ssl-cert previamente no seleccionado.
Desempaquetando ssl-cert (de .../ssl-cert_1.0.23ubuntu2_all.deb) ...
Seleccionando el paquete postfix previamente no seleccionado.
Desempaquetando postfix (de .../postfix_2.7.0-1ubuntu0.2_amd64.deb) ...
Seleccionando el paquete bsd-mailx previamente no seleccionado.
Desempaquetando bsd-mailx (de .../bsd-mailx_8.1.2-0.20090911cvs-2ubuntu1_amd64.deb) ...
Seleccionando el paquete mysql-cluster-client previamente no seleccionado.
Desempaquetando mysql-cluster-client (de .../mysql-cluster-client_7.0.9-1ubuntu7_all.deb) ...
Seleccionando el paquete mysql-cluster-server previamente no seleccionado.
Desempaquetando mysql-cluster-server (de .../mysql-cluster-server_7.0.9-1ubuntu7_all.deb) ...
Procesando disparadores para ureadahead ...
Se encontraron errores al procesar:
 /var/cache/apt/archives/mysql-cluster-client-5.1_7.0.9-1ubuntu7_amd64.deb
 /var/cache/apt/archives/mysql-cluster-server-5.1_7.0.9-1ubuntu7_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

…que no se soluciona ni con un ‘apt-get -f install’ tal y como dice.
No se porque sucede esto y si alguien sabe por que pasa o sabe solucionarlo mejor agradecería que me lo comentase ;) .
Como lo slucioné yo fue haciendo un: ‘dpkg -l mysql*’ y “purgando” todos los paquetes relacionados con mysql instalados o a medio instalar:
# apt-get purge mysql-client-core-5.1 mysql-cluster-client mysql-cluster-client-5.1 mysql-cluster-server mysql-cluster-server-5.1 mysql-common mysql-server-5.1 mysql-server-core-5.1 libmysqlclient16 libdbd-mysql-perl

Luego un:
# apt-get autoremove

y ya finalmente nos deja instalarlo correctamente:
# apt-get install mysql-cluster-server

Una vez instalado configuramos el MGM. Creamos el archivo /etc/mysql/ndb_mgmd.cnf y ponemos:

[NDBD DEFAULT]
NoOfReplicas=2
DataMemory=256M    # How much memory to allocate for data storage
IndexMemory=18M   # How much memory to allocate for index storage
# For DataMemory and IndexMemory, we have used the
# default values. Since the "world" database takes up
# only about 500KB, this should be more than enough for
# this example Cluster setup.
[MYSQLD DEFAULT]
[NDB_MGMD DEFAULT]
[TCP DEFAULT]
# Section for the cluster management node
[NDB_MGMD]
# IP address of the management node (this system)
HostName=192.168.2.210

# Section for the storage nodes
[NDBD]
# IP address of the first storage node
HostName=192.168.2.211
DataDir=/var/lib/mysql-cluster
BackupDataDir=/var/lib/mysql-cluster/backup
DataMemory=512M

[NDBD]
# IP address of the second storage node
HostName=192.168.2.212
DataDir=/var/lib/mysql-cluster
BackupDataDir=/var/lib/mysql-cluster/backup
DataMemory=512M

# one [MYSQLD] per storage node
[MYSQLD]
[MYSQLD]

Como véis definimos la ip del mgm (la 2.210) y la de los dos nodos que vamos a poner (2.211 y 2.212).

Creamos los dirs de los backups:
# mkdir -p /var/lib/mysql-cluster/backup
# chown -R mysql:mysql /var/lib/mysql-cluster

Nodos

Instalamos 2 máquinas virtuales mínimas para los 2 Nodos.
Instalamos mysql-server con soporte ndb en cada uno de los nodos:
# apt-get install mysql-server
# apt-get install mysql-cluster-server

Si da el error de arriba de dependencias, ya sabéis…

Confuguramos los nodos. Editamos el archivo /etc/mysql/my.cnf de cada uno de ellos y añadimos:
- En la sección [mysqld] añandimos:
ndbcluster
# IP address of the cluster management node
ndb-connectstring=192.168.2.210

- Y al final del archivo añadimos:
[MYSQL_CLUSTER]
ndb-connectstring=192.168.2.210

Iniciamos el cluster

En el admin iniciamos el demonio ndb-mgmd:
# /etc/init.d/mysql-ndb-mgm restart

En cada uno de los nodos el demonio ndbd:
# /etc/init.d/mysql restart
# /etc/init.d/mysql-ndb restart

Comprobaciones

Comprobamos que todo ha ido bien.
En el manager ‘mgm’ ejecutamos:
# ndb_mgm

y en el prompt ejecutamos:
ndb_mgm> show;

Tendríamos que ver que los dos nodos están conectados:

Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=2    @192.168.2.211  (mysql-5.1.39 ndb-7.0.9, Nodegroup: 0, Master)
id=3    @192.168.2.212  (mysql-5.1.39 ndb-7.0.9, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=1    @192.168.2.210  (mysql-5.1.39 ndb-7.0.9)

[mysqld(API)]   2 node(s)
id=4    @192.168.2.211  (mysql-5.1.39 ndb-7.0.9)
id=5    @192.168.2.212  (mysql-5.1.39 ndb-7.0.9)

Probando el cluster

Creamos una database por ejemplo en el nodo1:

# mysqladmin -u username -p create mysqlclustertest

Hay que tener en cuenta que las tablas que se creen en la database han de ser creadas con el parámetro ‘ENGINE=NDBCLUSTER’ para que puedan ser replicadas entre los nodos

mysql>
USE mysqlclustertest;
CREATE TABLE testtable (I INT) ENGINE=NDBCLUSTER;
INSERT INTO testtable () VALUES (1);
SELECT * FROM testtable;
quit;

Al momento si vamos al nodo2 y hacemos un show databases; veremos que ya está creada.

Ahora una prueba de fuego. Vamos al nodo1 y lo paramos:
/etc/init.d/mysql-ndb stop

Si vamos a la consola del mgm y hacemos un show veremos que ese nodo está parado:

ndb_mgm> show;
Cluster Configuration
---------------------
[ndbd(NDB)]	2 node(s)
id=2 (not connected, accepting connect from 192.168.2.211)
id=3	@192.168.2.212  (mysql-5.1.39 ndb-7.0.9, Nodegroup: 0, Master)

[ndb_mgmd(MGM)]	1 node(s)
id=1	@192.168.2.210  (mysql-5.1.39 ndb-7.0.9)

[mysqld(API)]	2 node(s)
id=4	@192.168.2.211  (mysql-5.1.39 ndb-7.0.9)
id=5	@192.168.2.212  (mysql-5.1.39 ndb-7.0.9)

Ahora en el nodo dos si hacemos un:

mysql> SELECT * FROM testtable;
+------+
| I    |
+------+
|    1 |
+------+
1 rows in set (0.00 sec)

Veremos que la tabla sigue disponible aunque el primer nodo esté caído.
Vamos a insertar un campo mas en el nodo2 con el uno caído:
mysql> INSERT INTO testtable () VALUES (2);

Si volvemos a hacer una consulta:

mysql> SELECT * FROM testtable;
+------+
| I    |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

Ahora arrancamos el nodo1 de nuevo:
# /etc/init.d/mysql-ndb start

…veremos que en la consola del mgm ya aparecerá como disponible y si hacemos una consulta veremos que ya están los datos replicados:

mysql> SELECT * FROM testtable;
+------+
| I    |
+------+
|    2 |
|    1 |
+------+
2 rows in set (0.00 sec)

Apagando o reiniciando el cluster

Para apagarlo en orden, en la consola del mgm ejecutamos:

ndb_mgm> shutdown;
Node 2: Cluster shutdown initiated
Node 3: Cluster shutdown initiated
Node 3: Node shutdown completed.
Node 2: Node shutdown completed.
2 NDB Cluster node(s) have shutdown.
Disconnecting to allow management server to shutdown.

Y vemos como apaga el servicio ndb de los dos nodos. De echo si vamos a cada nodo y ejecutamos un:
# ps aux | grep ndbd | grep -iv grep

…veremos que no hay ningún servicio corriendo. (Ojo, mysql si que sigue corriendo en cada nodo pero sin soporte ‘ndbcluster’).

Ahora ya podríamos hacer un shutdown de los nodos y del mgm.

La forma de reinicio de los servers, sería primero el mgm y luego ir iniciando los nodos

Si no hemos reinciiado las máquinas, para volver a conectar los nodos iniciamos primero en ndb-mgm en el mgm:
# /etc/init.d/mysql-ndb-mgm start

Y luego los servicios ndb en cada nodo:
# /etc/init.d/mysql-ndb start

Nuevamente con un show en el mgm comprobamos que todo ha ido bien y veulvan a estar conectados.

Dimensionamiento

Hay que leer la documentación para ver cuantos nodos podemos poner hasta que el sistema se degrade, ya que no podemos poner nodos infinitamente. Aunque repito que si esto os pasa seguramente es que no necesitéis leer esto.
También hay que tener en cuenta que todos los datos de los nodos van sobre RAM, así que hace falta mucha RAM. Se puede aplicar esta ecuación:
(SizeofDatabase × NumberOfReplicas × 1.1 ) / NumberOfDataNodes

Así que si tienes una database de 1GB, necesitarás 1.1GB de RAM en cada nodo.

Para acabar

IMPORTANTE: Ojo, esta arquitectura es mínima. El LoadBalancer y el MGM son dos puntos de fallo crítico, así que estos servidores deberían de ir en HA con por ejemplo Heartbeat + Drdb y si cae alguno de los dos se levante el secundario. Así que una instalación fiable de un cluster mysql sería como mínimo 6 máquinas (2xLoadBalancer + 2xMGM + 1xNodo + 1xNodo).

Y todo esto está muy bien, pero con esta arquitectura cada servicio tendría que atacar a cada nodo mysql por separado y estamos en las mismas. Así que nos quedaría configurar un LoadBalancer con una ip virtual a la que atacar desde nuestro servicio y este reparta las peticiones entre los nodos disponibles.

El Lodabalancer y heartbeat están explicados en otros posts, aunque siempre podéis contratar los servicios de consultoría de servidor, que vive de esto ;)

Fuentes:
http://dev.mysql.com/doc/refman/5.0/es/ndbcluster.html
http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-replication.html
http://bieg.wordpress.com/2008/08/03/mysql-clustering-ubuntu/
http://www.awven.com/q141-crear-un-cluster-mysql-ubuntu-server-1104/
http://www.monkeedev.co.uk/blog/2009/04/01/setting-up-mysql-50-cluster-on-debian-and-ubuntu/
http://www.howtoforge.com/loadbalanced_mysql_cluster_debian
http://www.howtoforge.com/setting-up-a-loadbalanced-mysql-cluster-with-mysql5.1-p2