Archive of July 2010
Arrancando nuestro primer cluster
Una vez que conocemos la teoría, vamos a poner en marcha nuestro primer Cluster. Estará compuesto únicamente por 3 ordenadores.
Nodo 1 (192.168.1.106):
- ndb_mgmd
- mysqld
Nodo 2 (192.168.1.104):
- ndbd
Nodo 3 (192.168.1.105):
- ndbd
Esto es, el nodo 1 será un Management Node + API Node y los dos restantes Data Nodes.
Lo primero de todo es descargarnos MySQL Cluster de http://dev.mysql.com/downloads/cluster/
La instalación es tan sencilla como descomprimir el fichero y copiar a nuestro PATH los ejecutables que necesitemos. Por lo tanto, llevaremos a /usr/bin/ los ejecutables ndbd, ndb_mgmd, ndb_mgm, mysqld, mysqld_safe.
Para tener un poco ordenadas las cosas, creamos la carpeta /etc/mysql-cluster/ donde alojaremos el fichero de configuración del cluster config.ini.
# cat /etc/mysql-cluster/config.ini [ndbd default] NoOfReplicas=2 DataDir=/var/lib/mysql-cluster DataMemory=512M IndexMemory=128M TransactionDeadlockDetectionTimeout=5000 MaxNoOfConcurrentOperations=100000 MaxNoOfLocalOperations=110000 [ndb_mgmd] Id=1 HostName=192.168.1.106 [ndbd] Id=5 HostName=192.168.1.104 [ndbd] Id=6 HostName=192.168.1.105 [mysqld] Id=7
Como vemos, en primer lugar indicamos los valores por defecto para todos los Data Nodes (ndbd). Por ejemplo se indican el número de replicas, donde se almacenarán los datos, la cantidad de memoria usada para almacenar datos e índices, número de operaciones concurrentes, etc. Estos valores no están ni calculados ni ajustados a la realidad, solamente son funcionales para este ejemplo y para trabajar con la base de datos employees. Cada caso y cada base de datos necesitará distintos valores que se deberán ajustar en función de la carga y cantidad de datos a almacenar.
El Management Node será el número 1 con la IP indicada, mientras que los Data Nodes serán los ID 5 y 6 con sus respectivas IPs. El API node (o en este caso más concreto Mysql Node) no tiene una ip asignada, por lo que se podría conectar desde cualquier equipo de la red.
Una vez que tenemos el fichero procedemos a arrancar el Management Node:
# ndb_mgmd -f /etc/mysql-cluster/config.ini 2010-07-25 19:30:06 [MgmtSrvr] INFO -- NDB Cluster Management Server. mysql-5.1.44 ndb-7.1.4b 2010-07-25 19:30:06 [MgmtSrvr] INFO -- Reading cluster configuration from '/etc/mysql-cluster/config.ini'
Arrancamos la consola y vemos que nodos tenemos arrancados:
# ndb_mgm -- NDB Cluster -- Management Client -- ndb_mgm> show Connected to Management Server at: localhost:1186 Cluster Configuration \--------------------- [ndbd(NDB)] 2 node(s) id=5 (not connected, accepting connect from 192.168.1.104) id=6 (not connected, accepting connect from 192.168.1.105) [ndb_mgmd(MGM)] 1 node(s) id=1 @192.168.1.106 (mysql-5.1.44 ndb-7.1.4) [mysqld(API)] 1 node(s) id=7 (not connected, accepting connect from any host)
Solo tenemos el Management Node en marcha. Vamos a proceder a arrancar los Data Nodes. Nos conectamos a cada nodo y ejecutamos:
# ndbd --connect-string=192.168.1.106 --initial -n 2010-07-25 19:31:38 [ndbd] INFO -- Configuration fetched from '192.168.1.106:1186', generation: 1
La opción --initial se usa cuando iniciamos por primera vez el Cluster para arrancar con el sistema de ficheros limpio. -n indica que el nodo no se autoarranque y --connect-string indica la IP del Management Node al que nos conectaremos.
Una vez que Data Node se conecta al Management Node, este último les entrega el fichero de configuración con los parametros necesarios para que se configuren. Ahora, desde la consola de administración podremos arrancar los dos Data Nodes:
ndb_mgm> 5 start Database node 5 is being started. ndb_mgm> Node 5: Start initiated (version 7.1.4) ndb_mgm> 6 start Database node 6 is being started. ndb_mgm> Node 6: Start initiated (version 7.1.4) ndb_mgm> show Cluster Configuration \--------------------- [ndbd(NDB)] 2 node(s) id=5 @192.168.1.104 (mysql-5.1.44 ndb-7.1.4, Nodegroup: 0, Master) id=6 @192.168.1.105 (mysql-5.1.44 ndb-7.1.4, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @192.168.1.106 (mysql-5.1.44 ndb-7.1.4) [mysqld(API)] 1 node(s) id=7 @192.168.1.106 (mysql-5.1.44 ndb-7.1.4)
Ya tenemos los Data Nodes en marcha.
Para arrancar el Api Node únicamente hay que ejecutar el demonio mysqld:
# mysqld_safe --ndbcluster &
No es necesario indicarle la IP del Management Node ya que se encuentran en la misma máquina.
Listo! Si ahora nos conectamos con el cliente mysql a localhost y creamos una base de datos usando tablas ndbcluster, estas se almacenarán en nuestro recién creado Cluster :)
Introducción a MySQL Cluster
MySQL Cluster es una base de datos que como su nombre indica funciona en un Cluster de servidores. Mucha gente confunde terminos y define un conjunto de servidores con replicación como un MySQL Cluster, pero hay que tener en cuenta que son dos conceptos totalmente distintos. MySQL Cluster nos ofrece:
- Alta disponibilidad
- Escalabilidad
- Failover automático
- Redundancia
- Alto throughput
La versión actual es la 7.1 y puede descargarse de http://www.mysql.com/products/database/cluster/
Componentes
Un Cluster MySQL está compuesto por los siguientes componentes:
Manager (ndb_mgmd): es un servicio encargado de poner en marcha el cluster, conectar nuevos servidores y ejecutar distintos comandos de administración mediante el CLI ndb_mgm. Una vez que hemos levantado el cluster no es necesario ni un requisito indispensable que esté levantado.
Data Nodes (ndbd): son nodos encargados del almacenamiento de los datos. Se recomiendan al menos dos para disponer de redundancia y alta disponibilidad. Estas serán las máquinas más potentes del cluster, almacenarán los índices en memoria y los datos en memoria o disco. Todos los Data Nodes deben tener el mismo hardware para evitar crear cuellos de botella.
API nodes (mysqld): aunque el más usado sea mysqld, un API node puede ser cualquier aplicación que haciendo uso de la API acceda al cluster. El típico, también conocido como SQL Node, es el demonio mysqld típico (compilado con soporte nbdcluster). De esta forma podremos escribir o leer datos de nuestra BBDD como hemos hecho hasta ahora, mediante comandos SQL.
Se recomienda que cada componente esté instalado en una máquina física distinta.
Funcionamiento interno
Internamente, el funcionamiento del cluster se basa en dos conceptos básicos. Replicación interna síncrona y auto particionado de datos. La primera nos ofrece la redundancia y el segundo nos da la escalabilidad. Importante diferenciarlo de la replicación típica de MySQL (asíncrona). En este caso, hasta que los datos no han sido replicados en los nodos seleccionados no se devuelve el control al usuario, obteniendo de esta forma la consistencia que no tenemos en la replicación asíncrona.
El particionado (PARTITION BY KEY) es también totalmente automático. El cluster se encarga de dividir las tablas en distintas particiones y dividir los datos entre los distintos Data Nodes. Aunque es posible que definamos nuestro propio particionado, no se recomienda. Añades complejidad y posiblemente el rendimiento no sea el esperado.
Replicas
A la hora de configurar nuestro cluster, una de los valores más importantes a tener en cuenta es decidir el número de replicas que tendremos de nuestros datos. No podemos decidir cualquier número, si no que tendremos que seguir unas sencillas reglas. Pongamos por ejemplo que tenemos 4 Data Nodes. En este caso podremos tener 1, 2 y 4 replicas. Esto es, el número de nodos debe poder ser divisible por el numero de replicas. Aún así, no se debería tener una única replica, ya que eso no nos da ningún tipo de alta disponibilidad ya que al caerse un solo nodo perderíamos el acceso a los datos.
Node Groups
MySQL Cluster agrupa automáticamente los Data Nodes en grupos. Esto no está bajo nuestro control ni podemos decidir que nodo está en que grupo, será trabajo del cluster hacer estas agrupaciones. Siguiendo el ejemplo anterior, si tenemos 4 Data Nodes y 2 réplicas, MySQL Cluster nos generará dos Node Groups (4/2=2). Además hay que tener en cuenta que el número de particiones que se harán de nuestros datos siempre será igual al número de Data Nodes.
Por lo tanto, imaginemos que tenemos el N1 y N2 en el grupo 1 (G1) y N3 y N4 en el grupo 2 (G2). A la hora de particionar y repartir los datos es necesario pensar en la alta disponibilidad, por lo que el particionado se hará de la siguiente forma:
G1 N1 = P1 y P2' N2 = P2 y P1' G2 N3 = P3 y P4' N4 = P4 y P3'
Siendo PX el número de la partición y PX' una copia de la partición de Backup.
Sabiendo esto, podemos imaginar cuando dispondremos de alta disponibilidad. Mientras al menos uno de los nodos de un grupo esté levantado, el cluster estará online. Por ejemplo se podrían caer N1 y N4 o N3 y N2 y todo seguiría funcionando. Pero una caida de N1 y N2 dejaría el cluster completamente caido.
A mayor número de replicas menos posibilidades de fallo, más escalabe y más throughput :)
Próximamente extenderé el tema de MySQL Cluster con más entradas según vaya profundizando en el estudio de la certificación. La intención será termianr teniendo un mini manual para andar por casa que nos permita dar los primeros pasos.
Postfix TLS con múltiples certificados
Cuando hablamos de TLS o SSL siempre nos encontramos con el mismo problema, el certificado. Este debe ser único por puerto e IP, de forma que dependiendo de a donde se conecte el cliente le entregamos un certificado u otro acorde a su dominio. Esto es algo con lo que tenemos que pelear constantemente en Apache, creando un VirtualHost por cada IP y asignándole un certificado.
Postfix no se libra y también necesitamos una IP por certificado, de forma que a cada cliente le muestre el certificado de su dominio y nos evitemos los famosos warning. Para hacerlo en primer lugar es necesario tener una IP por cada dominio. Una vez completado ese simple requisito pasamos a configurar Postfix. Primero ponemos TLS a nivel global en Postfix dentro del main.cf:
#TLS smtpd_use_tls = yes smtpd_tls_key_file = /etc/ssl/dominio1.com.key smtpd_tls_cert_file = /etc/ssl/dominio1.com.crt smtpd_tls_received_header = yes smtpd_tls_session_cache_timeout = 3600s tls_random_source = dev:/dev/urandom
Ahora tenemos que hacer que Postfix arranque un proceso smtpd por cada una de las IPs/Dominios. Esto lo hacemos en el master.cf. Al mismo tiempo que indicamos la IP, también le indicamos el certificado que usará:
\#========================================================================== \# service type private unpriv chroot wakeup maxproc command + args \# (yes) (yes) (yes) (never) (100) \#========================================================================== 10.10.10.1:smtp inet n - - - - smtpd 127.0.0.1:smtp inet n - - - - smtpd 10.10.20.1:smtp inet n - - - - smtpd -o smtpd_tls_cert_file=/etc/ssl/dominio2.com.crt 10.10.30.1:smtp inet n - - - - smtpd -o smtpd_tls_cert_file=/etc/ssl/dominio3.com.crt 10.10.40.1:smtp inet n - - - - smtpd -o smtpd_tls_cert_file=/etc/ssl/dominio4.com.crt
Listo, en cada IP entregará un certificado :)







