Ejemplo práctico Cfengine: Actualización masiva de PHP

Tengo prácticamente acabado un post a modo de introducción a los sistemas de administración centralizada + automatización (Cfengine, Puppet, Spacewalk, etc..), mientras tanto iré comentado casos reales donde estos sistemas me han parecido realmente útiles e interesantes. A modo de ejemplo, empiezo explicando -a grandes rasgos- el método que utilizamos en Hostalia para actualizar PHP en la plataforma de alojamiento compartido, un cambio que afecta a más de 60.000 dominios distribuidos en unos cuantos cientos de servidores.

Ante un escenario así, donde la máxima de las leyes de Murphy siempre se cumplirá, no podemos actualizar todos los servidores en bloque y tampoco podemos actualizarlos manualmente uno por uno sin saber que pasará: necesitamos un método flexible, totalmente automatizado, que nos alerte de posibles errores antes de que lleguen al usuario, con un método sencillo de rollback para volver al estado anterior a la actualización, y por supuesto, todo ello sin cortes y totalmente transparente para los usuarios. Aquí es donde Cfengine nos ayuda día a día en este tipo de tareas ;-)

Vamos “directos al grano” y analizamos el fragmento de la configuración de Cfengine que se encarga de esta tarea:

- La definición de clases o grupos es una de las características mas potentes a la hora de trabajar con cualquier sistema de administración centralizada, permiten agrupar servidores sobre los que realizar una acción común, por ejemplo: podemos tener servidores bajo clases con nombre “PHP4″, “PHP5″, etc.. para diferenciar servidores que ejecutan diferentes versiones de PHP.

- Cfengine define internamente una serie de clases (Sistema Operativo, arquitectura, versión del kernel, distribución Linux, etc…), permitiendo además que el usuario pueda gestionar nuevos grupos y realizar operaciones sobre ellas: sumas de grupos, exclusiones, etc… por ejemplo, podemos agrupar las clases PHP4 y PHP5 bajo la clase PHP, para realizar una acción común sobre ellas, por ejemplo sincronizar el fichero de configuración php.ini en todos las máquinas que pertenezcan a este grupo. Recomiendo la lectura del documento de Jeremy Mates sobre las clases en Cfengine, una buena definición de grupos/clases será un punto clave para el éxito de cualquier sistema de administración centralizada.

- Para simplificar, en este ejemplo vamos a trabajar únicamente con dos clases: PHP5 y TESTING. El grupo “PHP5″, como podemos intuir, contiene el grupo de servidores que ejecutan la versión 5 de PHP, y la clase “TESTING” agrupa aquellas máquinas donde vamos a actualizar PHP de forma “controlada” (desde la versión 5.2.6 a la 5.2.8, nos saltamos la versión 5.2.7 ya que introducía una regresión en el tratamiento de las “magic quotes”). De la combinación de estos dos grupos nacen dos nuevos entornos: PHP5.!TESTING con servidores que seguirán ejecutando la versión 5.2.6 y PHP5.TESTING que tendrá los servidores que serán actualizados a la versión 5.2.8. En Cfengine el operador “.” suma las máquinas de una clase y “!” es el operador de negación.

- En Cfengine es posible agregar servidores a grupos de muchas formas, una de ellas es con la directiva FileExists. En el ejemplo, tras hacer un touch del fichero /etc/cfengine/testing el servidor pasará a formar parte de la clase “testing”, es decir, será un candidato a actualizar desde la versión 5.2.6 a 5.2.8 de PHP “automágicamente” ;-)

- A partir de aquí tendremos dos flujos de ejecución en Cfengine: máquinas que no se verán afectadas por la actualización y las que pasarán a actualizar PHP. En cualquier momento es posible pasar de un estado a otro, con tan solo crear o borrar el fichero /etc/cfengine/testing.

- ¿Que pasa si una máquina entra en estado “testing” Cfengine instalará la nueva versión del módulo DSO para Apache de PHP, sustituyendo para ello el fichero libphp5.so. Para mayor flexibilidad en Hostalia compilamos PHP, así no dependemos de paquetes/compilaciones de terceros, y además así podemos personalizar las funcionalidades, aplicar parches, etc.. En cualquier caso, el proceso de actualización podría ser cualquier acción: actualizar PHP con el módulo de gestión de paquetes del propio Cfengine, con independencia de si estamos sobre una Debian, CentOS, Solaris, FreeBSD, etc..

- Además, si está definida la clase testing se modifica la configuración de PHP para enviar los errores por syslog a una máquina remota, donde los logs están centralizados en un servidor con syslog-ng. En un escenario de shared hosting con gran volumen de dominios, es muy habitual que PHP esté constamente reportando errores, por lo que algunos patrones los ignoramos directamente (ver fragmento con las regex), para dedicar la atención a aquellos que lo necesitan y pueden llegar a ser realmente graves. Desde un único punto podemos analizar “en vivo” lo que ocurre en las máquinas en estado “testing”, dejando a un lado las máquinas estables que tienen todavía la versión anterior de PHP. Por defecto, PHP envía a syslog los mensajes con el servicio y prioridad user.notice (ver la función php_syslog en main/main.c), si la queremos modificar el parche para hardening de PHP Suhosin permite personalizar este comportamiento de logging.

- Solo si se realiza cualquiera de las dos acciones anteriores (copiar el fichero libphp5.so y/o php.ini) se define la variable restart_apache en Cfengine: el resto de servidores no se verán afectados.

- Si la variable restart_apache está definida, se hace un reinicio graceful de Apache para evitar cerrar las conexiones establecidas en ese momento. Los procesos que estén con la versión anterior de PHP una vez terminen de ejecutarse pasarán a tener la nueva versión sin corte, esto es necesario para evitar cualquier corte en el lado cliente.

Al tener los errores de PHP de la nueva plataforma centralizados en un único punto es muy sencillo detectar cualquier problema y automatizar acciones ante determinados errores, por ejemplo: si aparece la cadena “segmentation fault” en los logs de Apache, podemos forzar un rollback automático a la versión anterior de PHP, con alguna herramienta de análisis de logs tipo swatch, etc.. con tan solo borrar el fichero /etc/cfengine/testing.

Cuando consideremos el cambio lo suficientemente maduro como para aplicarlo a todos los servidores en producción, podremos llevarlo acabo con unos pequeños cambios en la configuración de Cfengine, básicamente borrando las referencias a la clase “testing”.

Conclusión: el sistema de clases/grupos de Cfengine es uno de sus puntos mas potentes, en este caso nos ha proporcionado un método de actualización + rollback sencillo para actualizar un componente en un determinado grupo de servidores, sin afectar al resto de servidores.. un método flexible, fiable y sin cortes para una operación crítica, todo ello con apenas 20 líneas de código y dedicándole unos pocos minutos de atención :-)

This entry was posted in Linux, System Automation and tagged , . Bookmark the permalink.
  • http://www.ceta-ciemat.es Francisco Rodriguez

    Al principio del post dices …

    “Tengo prácticamente acabado un post a modo de introducción a los sistemas de administración centralizada + automatización (Cfengine, Puppet, Spacewalk, etc..)”

    Vas a publicarlo pronto? :)

    Gracias y enhorabuena por el blog

    • Fernandol

      Yo tambien estoy super-interesado en esa introducción, ¿se sabe algo nuevo?

      Un saludo y mil gracias,
      Fernandol.

      • http://woop.es Santi Saez

        Fernando, tengo en el borrador un post a modo de introducción a Cfengine.. en unos días debería estar listo! Ahora mismo estoy centrado en el lanzamiento de PowerStack 0.2.

        De todas formas, si tienes cualquier duda puntual sobre Cfengine y/o en general con los sistemas para automatizar la administración de servidores Linux pregunta sin miedo por si te podemos ayudar! :)

  • http://woop.es Santi Saez

    Francisco, muchas gracias por tus comentarios! :-)

    Mi idea es preparar una serie de artículos donde explique las herramientas que existen actualmente para administrar de “forma centralizada” una infraestructura de máquinas Linux, empezando desde cero..

    Estoy esperando a la inminente salida de la versión 0.5 para hacer público el manual de instalación de Spacewalk; de todas formas si te interesa ya está preparado para la versión 0.4: Instalación de Spacewalk sobre CentOS 5.

    Luego seguiré con Cfengine + Puppet y resto de herramientas de la familia ;-)

  • Alberto Gacias

    Santi, aplaudo y te agradezco tu iniciativa de esa serie de artículos, ya que sólo empezar a entender cualquier sistema de gestión sistemas requiere bastante esfuerzo y tiempo.

    Por otro lado me gustaría conocer tambien tu opinión sobre migasfree desde la experiencia de haber manejado otros sistemas de gestión de sistemas.

    En el Ayto. de Zaragoza lo llevamos usando desde hace 1 año y estamos administrando actualmente con él unos 500 desktops GNU/Linux de funcionarios (y poco a poco subiendo).

    Cualquier crítica (o duda) será bien recibida ;)

    Aunque aún no he empezado con la documentación de migasfree sí que he terminado un “inicio rapido” (http://migasfree.org/doc/es/quick_start.pdf) para que lo puedas probar si quieres.

  • http://woop.es Santi Saez

    Hola Alberto!

    Muchas gracias por tus comentarios! Conozco migasfree y lo pobré muy por encima hace unos meses, por lo que te leo por el Twitter veo que está evolucionando, lo vuelvo a probar y te comento mis impresiones, estamos en contacto!

    Saludos!