¿Por qué no usar CloudFormation para Bases de Datos?

Dedique varias semanas en investigar como implementar CloudFormation de Amazon para montar un entorno de pruebas de Percona XtraDB Cluster con cuatro nodos, dos HAProxy, un servidor con Nagios, y una VIP, adicionalmente usando Puppet, la idea que me atrajo de usar CloudFormation fue la practicidad de definir toda una infraestructura de maquinas virtuales usando un JSON como template, el tener un formulario para definir variables, y luego tener la ventaja de poder crear y destruir cualquier cantidad de veces el cluster de forma automatizada.

Al final me di cuenta que no es seguro usar CloudFormation por varios motivos:

  • CloudFormation se asegura de mantener toda la infraestructura al 100% como está definida en el JSON. Si no hay algo que no encaja, crea una nueva maquina y destruye la anterior, al tener una Base de Datos con datos de producción los podemos perder muy fácilmente. Esto me paso al cambiar la versión de la AMI, note como se creaban nuevas maquinas, y luego cuando estaban listas, fueron remplazadas por las viejas y se perdieron todos los datos.
  • Se tendría que parametrizar mucho para reducir las probabilidades de destruir una maquina de forma accidentada. Esto le añade más complejidad en el flujo de trabajo y deja de ser intuitivo para cualquiera.
  • Contemplar todos los casos de administración de cada uno de los nodos de un cluster es complejo, por ejemplo, debemos contemplar la ampliación del disco sin perder los datos, cambiar el tipo de instancia, y cambiar las políticas de seguridad. Quien sabe que más puede pasar.

Poder superar todas las desventajas mencionadas requiere muchas horas de investigación y pruebas hasta lograr dominar todo, puede que nos demos cuenta que faltan más reglas por parte del CloudFormation, pienso que esto no fue echo para Bases de Datos, sino para servidores de API y WEB, donde los grandes volúmenes de datos no son un problema.

También pienso que usar CloudFormation en un caso de Bases de Datos está bastante bien para hacer una demo, o crear entornos para un sandbox por ejemplo, pero para producción lo veo muy peligroso.

Mi recomendación es irnos por lo clásico, crear tus propios scrips que hacen llamadas a la API de Amazon, así creas toda la infraestructura, defines tú el flujo de trabajo, y llevas el control, si yo habría echo así desde un principio, habría ahorrado mucho tiempo. De todo esto se obtiene una lección aprendida, y aquí la comparto.

MySQL y HAProxy es una Arquitectura de Balanceo de Carga & Failover

La Base de Datos es un servicio muy importante que debe estar operativo el 99.99%, hay muchas arquitecturas para lograr esto, todo depende de las necesidades, hoy les explico la más básica usando un Master y dos Slaves con AWS y HAProxy.

Los Slaves se usan para las lecturas, todo el tráfico que es de disposición NO inmediata (<1s) debe ser accedido desde los Slaves, la idea es hacer un balanceo de carga, le quitamos peso al Master y se lo delegamos a los Slaves.

Como podemos imaginar, usar Slaves no son muy seguros, de vez en cuando se rompe por una serie de motivos, o necesitamos hacer mantenimiento y no debemos detener el servicio, entonces creamos una arquitectura tolerante a fallos como se muestra en la siguiente imagen:

MySQL Arquitectura Failover

Podemos observar que todo lo que está susceptible a fallos está duplicado. Hago una breve descripción de cada elemento que interviene en el diagrama:

  • APPS: Las aplicaciones con una configuración especial saben dirigir el tráfico de lectura o de escritura.
  • Master: Usamos un RDS Multi A-Z, esto permite una redundancia de servidores en multiples zonas, y entra en acción una zona u otra si una de ellas falla. Si no usamos RDS recomiendo tener una configuración Multi Master, hay una solución muy buena llamada Percona.
  • DNS: Cada servidor se le crea un CNAME, pero uno de ellos, está definido con dos IP’s, que es para los HAProxy, así tenemos redundancia, Route 53 de AWS permite hacer esto (Como los de Amazon nos quitan trabajo).
  • Slave: Las instancias de MySQL, no requiere ninguna configuración especial.
  • HAProxy: Éste servicio debe usar la versión 1.5 que tiene soporte para MySQL. Depende como lo configuremos, pero balancea las conexiones en Round Robin por ejemplo, también podemos definir el número máximo de conexiones, como una conexión de backup que valla contra el Master en caso de que todos los Slaves fallen.

Cronología de un desastre:

Vamos a ver en orden que pasa si algo falla y como se resuelve:

  • Si el DNS detecta que uno de los HAProxy falla, el DNS le pasa la conexión a otro HAProxy.
  • Si el HAProxy detecta que un slave no responde, le pasa la conexión a otro Slave.
  • Si todos los Slaves no responden, el HAProxy redirige la conexión al Master.

Para que todos los pasos anteriores sean transparentes para la aplicación, está debe tener una tolerancia a fallos de conexiones. Lo que quiero decir, es: que si una conexión es interrumpida, la vuelve a reanudar sin mostrar mensajes de error.

Es muy importante tener algún sistema de monitoring de cada cosa que está involucrado en el diagrama, sino no podemos entrar en acción rápido para prevenir algún desastre. También debe tener bien calculado y configurado el número de conexiones soportadas por cada instancia de MySQL.