Servidor MySQL persistente sobre EC2 y EBS

Uno de los grandes "problemas" que tiene EC2 de Amazon, es que sus unidades de almacenamiento no son persistentes. Esto quiere decir que en cuanto apaguemos nuestra(s) instancia(s), todos los datos almacenados se volatilizarán.
La primera solución que se nos puede venir a la cabeza, podría ser apoyarnos en el servicio S3 para ir haciendo backup de nuestros datos continuamente y así, al apagar nuestra instancia, podríamos recuperar todos nuestros datos. Por supesto, esta solución es poco fiable si nuestros datos varían continuamente (como una Base de Datos), ya que si apagamos nuestra instancia o esta falla en el lapso de tiempo entra backup y backup, seguiríamos perdiendo los últimos cambios.

Afortunadamente, Amazon lanzó EBS (Elastic Block Store), un servicio de almacenamiento persistente que nos permite montar un volumen de datos como unidad de almacenamiento sobre EC2.

Vamos a ver cómo aprovechar EBS para configurar una máquina en EC2 como servidor MySQL con almacenamiento persistente.

1. Reservar un volumen EBS

Lo primero de todo, es solicitar un nuevo volumen EBS para poder montarlo en nuestra instancia EC2.
Para ello, abrimos Elasticfox (que vimos en una entrada anterior) y accedemos a la sección "Volumes and Snapshots". La primera sección corresponde a los volúmenes (EBS) que tenemos reservados, y la segunda a los backups de esos volúmenes. Cada snapshot (backup) nos servirá para lanzar un nuevo volumen que incluya nuestros datos previamente salvados.
El procedimiento es de lo más sencillo. Simplemente hacemos click en el botón verde (+) de la sección "Volumes" y nos aparecerá un pequeño formulario para configurar nuestro nuevo volumen.

ebs2

Definir el tamaño en GB del volumen: Esa será la cantidad máxima de datos que podrá almacenar nuestro nuevo volumen, por lo que es recomendable tener una idea de para qué vamos a utilizarlo antes de crearlo y así poder estimar el espacio que necesitaremos.
Elegir el snapshot a partir del cual queremos iniciar nuestro nuevo volumen: Para un nuevo volumen, simplemente dejamos este campo por defecto en "<none>"
Zona de disponibilidad: Este es uno de los puntos más importantes a la hora de crear nuestro volumen, ya que un volumen sólo puede ser accesible desde una instancia EC2 en la misma zona de disponibilidad. En caso de equivocarnos, o querer adjuntarlo a una nueva instancia en otra zona, podremos crear un snapshot, y a partir de él lanzar un nuevo volumen en otra zona.
Tag: Este campo es totalmente opcional y sirve para etiquetar nuestro nuevo volumen. Es bastante útil a la hora de manejar muchos volúmenes distintos y automatizar su gestión.

2. Adjuntar el volumen a una intancia

Ningún misterio. Simplemente hacemos click en el botón verde en forma de "tick" (o click derecho sobre el volumen y elegimos "Attach this volume"), y accederemos a un nuevo formulario en el que podremos elegir una de nuestras instancias disponibles en nuestra zona, y un campo donde definiremos el dispositivo desde el que queremos hacer disponible nuestro volumen. Como véis, Elasticfox nos avisa de que, para una máquina Linux, tenemos disponible cualquier dispositivo desde /dev/sda hasta /dev/sdp. Para este tutorial yo he elegido /dev/sdh. Por supuesto, podéis usar el que queráis (pero tenedlo en cuenta en los comandos y scripts que veamos).

ebs1

3. Formatear y montar nuestra unidad

Una vez adjuntado el volumen a nuestra instancia a través del dispositivo /dev/sdh, lo formatearemos en ext3 para tener acceso a él como unidad de almacenamiento (vosotros lo formateáis con el sistema de archivos que más os guste ). Para ello ejecutamos

CODE:
  1. mkfs.ext3 /dev/sdh

Creamos un nuevo directorio

CODE:
  1. mkdir /mnt/ebs

Y montamos la unidad en él

CODE:
  1. mount -t ext3 /dev/sdh /mnt/ebs

4. Llevar MySQL a nuestro EBS

No voy a explicar cómo instalar MySQL en vuestra máquina, porque presuponemos que ese paso ya está superado. Aún así, si no sabes cómo, seguro que fácilmente encontrarás algún tutorial de cómo instalar MySQL en vuestra distro preferida (como éste para Ubuntu).
El procedimiento para mover MySQL a EBS es sencillo. Simplemente moveremos el directorio mysql a nuestra nueva unidad, y crearemos un enlace simbólico desde su directorio original. De ésta manera, los datos estarán físicamente en EBS y virtualmente en el directorio original de mysql.

Primero movemos los datos ejecutando (Es importante haber apagado el servicio de mysql antes de proceder)

CODE:
  1. mv /var/lib/mysql /mnt/ebs/mysql

Y creamos el enlace

CODE:
  1. ln -s /mnt/ebs/mysql /var/lib

(si vuestro mysql no está instalado en /var/lib/mysql, usais vuestro directorio)

Ya sólo nos queda volver a arrancar el servicio de mysql y volver a generar nuestro AMI para no perder los cambios.

5. Automatizar el montaje de nuestra unidad EBS

Como os imaginaréis, si lanzamos una nueva instancia de nuestra AMI, aunque tendrá creado el enlace simbólico en /var/lib, nuestro volumen EBS no estará montado en /mnt/ebs.
Para facilitaros un poco el trabajo, he creado un pequeño script de bash que "escucha" hasta que está disponible el dispositivo /dev/sdh , para crear el directorio /mnt/ebs y montar en él el dispositivo. Como es evidente, este script nos "obliga" a adjuntar siempre el volumen en /dev/sdh.

Para que el script se ejecute nada más encender nuestra instancia, podemos editar nuestro archivo /etc/rc.local y añadir el siguiente comando

CODE:
  1. ./root/ebsmount.sh &

Esto ejecutará el script en background en el momento de arrancar la máquina.

Después de esto, ya simplemente tendremos que levantar una nueva instancia y adjuntarle el volumen EBS que hemos creado, y tendremos nuestra máquina EC2 con servicio MySQL con almacenamiento de datos persistente.

Por supuesto, se podría automatizar el proceso de adjuntar el volumen a la nueva instancia, de manera que sólo tuviéramos que levantar una nueva instancia y listo. Pero para ello habría que trabajar con la API de EBS y eso es otra guerra. Quizás en un futuro hable de ello.

Espero que, aún así, lo visto en esta entrada os sea útil.

Un saludo !!

20 Comentarios

  1. saasmania says:

    Gracias por la información.
    Saludos.

  2. Juan says:

    Una vez más, grandísimo artículo crack!, aún estoy ansioso esperando el que me prometistes de Elastic IP jejejeje

    Tengo un par de preguntillas, por ejemplo, si quiero hacer que varias instancias corran mysql pero todas con el mismo contenido en la base de datos (para que no mandar todas las peticiones a una sola y sobrecargarla demasiado), podría montar el mismo EBS en distintas instancias? supongo que no verdad? Cúal podría ser la solución? exportar el directorio por NFS y montarlo por esa vía en las otras instancias?

    Y la otra es que he leído que el EBS debe desmontarse en condiciones antes de volver a montarlo, pero y si la instancia se cuelga por ejemplo? supongo que no habrá problema no?

  3. Juan says:

    Perdón, cuando al final dije desmontar el volumen EBS en condiciones, me refería a que he leído que hay que hacer un ‘detach’ del volumen en la instancia, y luego ya se podría volver a hacer el ‘attach’. El problema es que por lo visto el ‘detach’ se debe hacer con el volumen desmontado en condiciones, y si la instancia se cuelga, eso no se cumpliría. Por tanto, podríamos hacer el ‘detach’ del volumen en ese caso sin correr riesgo de perder datos?

    Espero que se me haya entendido jejejeje

  4. fillito says:

    Hola de nuevo Juan !

    Jejeje, es cierto que te debo uno sobre Elastic IP … pero como es tan sencillo y simple, siempre se me pasa. Voy a ver si investigo un poco sobre la API de Elastic IP, y escribo sobre cómo hacer algo chulo con ella. Porque usar Elastic IP a mano es tan sencillo como reservar una IP desde Elasticfox y “attachearla” a una instancia que ya esté corriendo.

    En cuanto a tus preguntas…
    En ningún caso se puede adjuntar el mismo EBS a más de una instancia a la vez, por lo que como solución a lo que propones, sólo se me ocurren 2.
    1. Montar una intancia Servidor MySQL bastante potente, a la que ataquen el resto de instancias.
    2. Montar el clasico Master-Slave con una instancia Servidor MySQL configurada como Master, para escrituras, y luego varias instancias más como Slave para lecturas. Y así distribuir la carga.

    En cuanto a lo de “deattachear” (me van a dar un premio algún día por este tipo de palabras…), un EBS sin desmontarlo en el OS, he hecho mis pequeños tests de stress. Precisamente para comprobar qué pasaría en el caso que expones de cuelgue o similar …
    He “deattacheado” el bloque “en caliente” de la instancia, y luego lo he montado en otra distinta, repetidas veces, para comprobar si cascaba, y en ningún momento ocurrió nada. Como es evidente, si haces esto o se cuelga la instancia justo en medio de una transacción, pueden perderse datos, o quedar dañada la estructura de datos. Pero nada que no ocurriese al cascar o desconectar un disco duro. Por lo que he podido comprobar, no se corrompe el bloque EBS si le haces el “deattach” sin haber desmontado el sistema de ficheros.

    Bueno, espero que haya contestado tus dudas :P . Cualquier cosa, ya sabes que estamos por aquí siempre dispuestos. Y no se me olvida el de Elastic IP ;)

    Un saludo !!!

  5. Juan says:

    Gracias crack por responder y tan rápido jejeje! Lo del Master y Slave no lo entiendo muy bien pero buscaré info por Internet que seguro que hay tutoriales que lo explican paso a paso.

  6. fillito says:

    Hola Juan !

    Lo de Master y Slave es una forma de configurar los servidores de bases de datos. Estableces una máquina como servidor Master, y luego todas las máquinas que quieras como Slave. La idea es que todas las escrituras que haga la aplicación a base de datos, lo haga sobre el servidor Master, y todas las lecturas se hagan sobre el servidor Slave.
    Usando esta configuración, la base de datos se replica en los servidores Slave cada X tiempo (es configurable). De ésta manera, ninguna máquina tiene que hacer lecturas y escrituras a la vez. Es muy muy útil en aplicaciones que requieran muchísimas lecturas (el ejemplo más claro es la web, donde el nº de lecturas supera con creces el de escrituras). Además es cómodamente escalable, ya que simplemente tendremos que añadir un nuevo Slave más y listo :P .
    El contrapunto, como habrás imaginado … está en que los datos escritos no están disponibles inmediatamente para lectura, sino que hay que esperar a que la base de datos se vuelva a sincronizar en todos los esclavos. Aquí es donde entra el tunning de los tiempos de actualización.

    De todas formas, si te interesa el tema, seguro que encuentras muchos tutoriales que lo explicarán mejor que yo. Pero ésto puede que te haya dado una idea. En cuanto a configurar ésta arquitectura… MySQL lo hace casi todo él solo. No es nada complicado montarlo ;)

    Un saludo !!

  7. Eduardo says:

    El tuto está genial, eso vaya por delante. En amazon hay un enfoque parecido, pero usa el fstab para automatizar le montaje del EBS (o eso me ha parecido entender) y usa el sistema de ficheros XFS que se supone bueno y muy compatible con los snapshots.
    http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1663&categoryID=174
    Mi duda (perdón, soy nuevo) ¿en lo de amazon se monta el EBS de manera automática o sigue haciendo falta automatizar algo con un script como el que facilitas?

  8. fillito says:

    Hola Eduardo

    EBS es necesario montarlo a mano en EC2. Hay una API a la que puedes hacer llamadas para adjuntar los bloques en EC2, y la verdad es la mejor manera. Los usos que se le puedan dar EBS son muy variados, y depende mucho de las necesidades del cliente o del proyecto, por lo que la mejor manera de automatizarlo es creando algún script ajustado a tus necesidades. Una vez adjuntado, también tendrás que montarlo como sistema de ficheros de forma manual o con scripts.

    Un saludo !!

  9. Eduardo says:

    Gracias por la información. He creado un pequeño script que precisamente monta el EBS. En teoría debería ser automático, pero me encuentro con que en mi Ubuntu Server 8.04 de alestic, a pesar de meter la llamada a mi script en el bootmisc.sh, no se lanza de manera automática, simplemente lo ignora. Si lanzo el script desde línea de comandos va perfecto, pero cuando la máquina arranca no hace lo que debería.
    A ver si alguien me ayuda, porque en Ubuntu el rc.local no tiene mucho uso (ya lo he probado de todos modos y tampoco va).
    Un saludo y gracias
    P.D. Cuando consiga que funcione os lo pego por si os puede ser útil y hacer un mix con lo que propones tu.

  10. Konum says:

    Geniales tus tutoriales sobre AWS. Gracias ^^

  11. fillito says:

    @Konum: Gracias a tí ! me alegro de que te sean útiles ;)

  12. Angel says:

    Hola Fillito. La verdad que tu trabajo aquí es estupendo. Has resumido varias horas de lectura en unos post más que interesantes y que van a foco de la cuestión.
    Estoy experimentando en este momento con EC2 + EBS + S3, a ver que sale.
    Te hago una consulta, a tu criterio, la configuración de sitios de apache, debería también estar en la EBS? Y si es asi, imagino que apuntando con links simbólicos lo que está en /etc/apache2 al volumen EBS (ln -s /mnt/ebs/apache2 /etc). Correcto?

  13. fillito says:

    Hola Ángel, disculpa el retraso en contestarte… pero estos últimos días han sido mortales de curro.

    En cuanto a tu pregunta: Yo no metería apache en EBS. A mi me gusta EBS para usarlo como almacen de datos que varíen continuamente (como la base de datos), pero los ficheros estáticos los seguiría dejando en la propia instancia EC2 para que quede siempre dentro de nuestro AMI.
    Piensa que así, cuando necesites escalar el proyecto, podrías simplemente levantar nuevas instancias donde ya estaría todo tu código de apache y las aplicaciones instaladas.
    Como no puedes compartir EBS entre varias instancias, lo que metas en EBS no podrá ser usado sino por una única instancia. Sin embargo, si sólo metes los datos de la base de datos, siempre puedes configurar ésta para permitir acceso remoto y que las nuevas instancias puedan acceder a la base de datos.

    De todas formas, independientemente de mi observación personal, la forma que describes es correcta para tener instalado apache en EBS y enlazado con /etc

    Espero haber respondido tu pregunta. Cualquier cosa ya sabes dónde estoy ;)

  14. Seba says:

    Hola Fillito! Te comento que ya tengo una instancia levanta y cree un ebs donde metí mysql. Haciendo pruebas cree una base de datos en el mysql (quedó en el EBS) y luego terminé la instancia. Volví a levantar una nueva instancia utilizando la misma AMI y volví a enlazarla con el ebs. El tema es que cuando en MySql pongo show databases no veo la base que había creado anteriormente. Sin embargo voy por WinSCP y veo la carpeta de la base. O sea la base no se borró, quedo en el EBS pero no la puedo ver través del MySql. Tienes alguna idea de que pasa? Ya que esto es vital para saber si en mi trabajo utilizaremos estos servicios o no.

  15. fillito says:

    Hola Seba.

    Con los datos que me das, yo apostaría porque el archivo de configuración de tu mysql no tiene seteado correctamente la ruta del directorio de datos. Puede pasar si montas el ebs en un directorio diferente al que se debería, o algo así …

    A ver si es eso, si no, dame más datos a ver si se me ocurre algo y localizamos el problema. Poderse, se puede seguro, porque yo lo uso a diario precisamente en mi trabajo, y para nosotros también es vital :)

    Suerte !

  16. Seba says:

    Si algo de eso es. Te cuento que ya puedo ver las bases anteriores pero aun ando con algunos problemas jeje.
    Mi prueba fue realizar lo siguiente: realicé todo el tutorial al pie de la letra, y luego creé una base. A través del WinSCP vi que estaba en el volumen que había montado en el /mnt/ebs.
    Entonces lo que hice fue terminar la instancia. Volver a levantar una igual, instalarle el mysql, montar la unidad y todo eso. Pero en lugar de mover la carpeta mysql a la unidad montada, la borré. Ya que en la unidad montada tenía ya una carpeta MySql con las bases. Por lo tanto borré la carpeta y creé el enlace. El tema es que si bien veo las bases ando con unos problemas a la hora de reiniciar el servicio MySql, ya que parece que hay error de permisos. Se ve que lo que hice no está muy bien jeje.
    Bueno sequiré investigando.
    Saludos, y gracias por la respuesta!!!

  17. Seba says:

    Bueno finalmente te digo que encontré la solución. La cuento por si alguno le pasa lo mismo. Lo que hago es lo siguiente. Tenemos la carpeta mysql en el ebs. Si tenemos que levanar una nueva instancia, lo que hacemos es salvar las carpetas dentro de MySql de nuestras bases. O sea si creamos la base prueba, dentro de la carpeta MySql habrá una carpeta con nombre prueba. Por lo tanto movemos esas carpetas a cualquier otro directorio y borramos la carpeta MySql. Al levantar hacemos todo lo mismo que la vez anterior y al final volvemos a mover las carpetas de las bases a la nueva carpeta MySql en el EBS. Quizás para muchos fuera obvio esto, pero a otros que recién comienzan como yo les puede ser útil

  18. Julian says:

    Gracias Dani.. muy util.. estabamos investigando esta ahora :)

Deja un Comentario