Sincronizar máquinas

Hace no mucho un amigo que trabaja en una conocida página web me contaba cómo sincronizaban las máquinas de producción cuando sacaban una nueva versión de su software. Utilizaban un shellscript con un bucle for que mediante scp actualizaba cada equipo. Desde luego funcionar funciona, ¿pero es la mejor manera? Voy a analizar las alternativas que se me ocurren. Como siempre, todo el que me lea está invitado a ponerme a caldo ;)

Opción 0 – cliente ftp a mano

Bueno, meto en esta lista esta opción porque sigue siendo hoy por hoy la más utilizada, en muchos casos porque no queda otra alternativa. ¿Inconvenientes? Es un trabajo “artesanal”, y muy sensible a errores. Por ejemplo, si el sitio es muy pesado, y decidimos únicamente subir los ficheros actualizados, será muy probable que se nos olvide algo. Además, si lo hacemos a mano, en la mayoría de los casos implica realizarlo desde una conexión con poco ancho de banda de subida. Subir mil ficheros por ftp desde una de esas conexiones puede agotar la paciencia a cualquiera.

  • Velocidad – baja
  • Tolerancia a fallos – muy baja
  • Escalabilidad – muy baja

Opción 1 – scp

Este método es aparentemente el más sencillo (Dentro de los no artesanales). Por ejemplo, podemos tener una máquina que automáticamente actualice cada uno de los equipos de nuestro cluster.

#!/bin/bash
for i in `seq 2 10`;
do
   ip=82.98.140.$i
   scp -r /var/www/ www-data@$ip:/var/www/
done

¿Qué ocurre si alguna máquina está caída? Tendríamos que mejorar el script para detectar cuándo ha habido éxito, para así llevar a cabo las actualizaciones pertinentes. De ese modo nuestra solución sencilla ya no lo sería tanto. Con todo y con esto, se trata de un pequeño obstaculo ¿Cuánto tiempo llevará cada actualización? Sería necesario copiar todos y cada uno de los ficheros cada vez y sin comprimir. ¿Escalaría esta solución? Es fácilmente escalable, pero incomodo de mantener en mi opinión.

  • Velocidad – media
  • Tolerancia a fallos – alta
  • Escalabilidad – media

Opción 2 – svn

Esto se pone interesante :) Cualquier proyecto debe tener un sistema de control de versiones (A mi personalmente me ha costado aprender la lección, pero ya no olvido). Gracias a ello podremos evitar innumerables desastres, podremos trabajar cómodamente en paralelo varias personas, y quedará todo perfectamente organizado. Además, es un método estupendo para sincronizar máquinas. Puede automatizarse todo el proceso, por ejemplo, con un branch stable, y una tarea en cron que, cada noche compruebe si hay actualizaciones. La velocidad sería alta, ya que sólo se descargaría lo imprescindible. Es muy escalable, ya que se pueden sumar nuevos servidores “en caliente” (No estamos teniendo en cuenta otros factores mas que la sincronía)

  • Velocidad – alta
  • Tolerancia a fallos – alta
  • Escalabilidad – muy alta

Opción 3 – empaquetar

Es posible que todas nuestas máquinas no sean iguales. Por ejemplo, puede haber binarios y bibliotecas que no sean las mismas versiones en todas las máquinas. La máquina A podría tener PHP 5.2.6 y la máquina B tener PHP 5.2.0 (Estas son las versiones de PHP que hay ahora mismo funcionando en las versiones estables de Ubuntu y de Debian respectivamente). A menudo, estas diferencias de versiones implican cambios en determinados métodos y funciones a los que accedemos. Estos cambios pueden implicar que nuestra aplicación no funcione en todas las máquinas. ¿La solución? Tener un repositorio común con todas las dependencias de nuestro software acompasadas (Sí, es costoso… pero no estamos hablando de proyectos pequeños!).

Y ya que tenemos un repositorio, ¿por qué no empaquetar nuestra aplicación? De este modo cada vez que publiquemos una nueva release de nuestro software, todas las máquinas podrían actualizarse automáticamente. Además, añadir nuevos servidores sería tan sencillo como notificarles el respositorio común.

  • Velocidad – muy alta
  • Tolerancia a fallos – muy alta
  • Escalabilidad – muy alta

Otras opciones

Por supuesto no he dicho todas las que son, ni son todas las que están :) También se me ocurren estos otros métodos:

  • Sistema de ficheros en red – NFS: Mediante este método podemos tener una sola copia de la aplicación montada en todos los servidores. Puede ser un cuello de botella desastroso.
  • Sincronización mediante rsync: Gracias a esto, las actualizaciones serían muy livianas (comprimidas e incrementales), además de seguras.
  • NFS + rsync: Esta idea, que leí no recuerdo dónde, consiste en tener montada la copia remota mediante NFS para luego sincronizar en local mediante rsync, preferiblemente algún sistema de ficheros no persistente cargado en RAM como tmpfs.
  • tar + scp: Distribuir el contenido comprimido por ejemplo en tar+gzip mediante scp, de modo que toda la transferencia se lleve a cabo en una sola transacción.


2 comentarios a “Sincronizar máquinas”

  1. Wyrm  on Diciembre 12th, 2008

    Doy fe de que SVN hace la vida más facil y los rollbacks ante un kernel panic de los que te hacen la pascua un fin de semana.
    Buen post Chuso! Escalabilidad! Escalabilidad! Escalabilidad!

  2. Crisito  on Diciembre 15th, 2008

    Eres un pelota Wyrm!!!!
    Hola Chusete, mola el template :P


Deja un comentario