Twelve-Factor App: Construyendo Servicios

De vez en cuando la gente se reune y medita sobre las acciones que se están llevando a cabo para el desarrollo de software. Esta actividad de reflexión es muy positiva y nos proporciona estudios o manifiestos muy interesantes. En este caso quiero hablar de uno llamado The Twelve-Factor App para aplicaciones web que se ofrecen como servicio (Software as a Service, SaaS), ¿de qué se trata?

Este documento (en castellano y otros idiomas), ofrece 12 puntos (o factores) para conseguir un software que cumpla:

  • El uso de formatos declarativos para la automatización de la configuración.
  • Máxima portabilidad a través de un contrato claro con el sistema operativo.
  • Despliegue en plataformas en la nube y no depender de una máquina en concreto.
  • Despliegue contínuo minimizando las diferencias entre desarrollo y producción.
  • Escalar sin que suponga cambios significativos en las herramientas, arquitectura o prácticas.

Se puede aplicar a cualquier lenguaje de programación y a cualquier combinación de base de datos, colas, memorias cache, etc.

Dando un repaso rápido a cada uno de los factores tenemos:

1. Código base único

Un solo código base del que realizar los despliegues, sin cambios. El código base omite detalles como los ficheros de configuración que serán las únicas diferencias que deben existir entre los distintos entornos.

2. Dependencias aisladas del sistema

Declarar y aislar las dependencias. Intentar mantener todas las dependencias instaladas dentro del proyecto al realizar el despliegue. Para esto se pueden usar herramientas de vendoring en muchos de los entornos de desarrollo.

Sistemas como Java (Maven), Erlang (rebar, erlang.mk y rebar3), Elixir (mix) implementan la instalación de estas dependencias en el artefacto a ser desplegado mientras que otros como Rails o Django requieren de otras artimañas.

3. Configuraciones en el sistema

Guardar la configuración en el entorno. Como se menciona en el punto 1, las diferencias entre los entornos estarán principalmente en la configuración y mantener la configuración ligada al entorno es lo más fácil para realizar despliegues.

4. Servicios de apoyo conectables

Tratar a los backing services (servicios de apoyo como bases de datos, colas, memorias caché, servicios de email, etc.) como servicios conectables. Al no estar ligados a la máquina donde se ejecuta el código base, facilita mover estos servicios a otras máquinas cambiando únicamente la configuración.

5. Construir, distribuir, ejecutar aislados

Definimos tres etapas que deben estar completamente separadas:

  • La etapa de construcción es donde se genera la construcción trayendo todas las dependencias para generar el artefacto (o paquete que incluirá todo).

  • La etapa de distribución se mezcla el artefacto con la configuración para realizar el despliegue. Normalmente se emplea un directorio diferente al usado para la distribución anterior de modo que se mantengan ambas.

  • La etapa de ejecución (conocida como runtime) se ejecuta la aplicación en el entorno. También es ideal que se pueda ejecutar (si es posible) en otro proceso diferente para mantener la versión anterior hasta que la nueva esté completamente operativa.

Lo ideal es emplear herramientas que nos permitan generar cada paso y proporcionen incluso mecanismos para detener el proceso de despliegue si algo va mal.

6. Procesos sin estado

Ejecutar la aplicación como uno o más procesos sin estado. La motivación es no mantener información que deba ser compartida en una sola máquina porque eso nos limita a esa única máquina. Emplear el sistema de ficheros por ejemplo, nos limita a esa máquina. En su lugar es siempre preferible emplear sistemas como Amazon S3.

7. Asignación de puertos

Cada aplicación debe ser autocontenida y tener un puerto interno al que acceder diferente al del resto de aplicaciones. Esta asignación se realiza en la etapa de distribución y consiste en configurar la capa de enrutamiento que se encarga de llevar las peticiones de la IP pública a la IP interna y el puerto asignado.

8. Escalar mediante el modelo de procesos

Los procesos de las aplicaciones twelve-factor se inspiran en el modelo de procesos unix para ejecutar demonios. Lo ideal es escribir scripts de tipo SysV o systemd, dependiendo del sistema donde se despliegue la aplicación.

9. Disponibilidad

Hacer el sistema más robusto intentando conseguir inicios rápidos y finalizaciones seguras. Como continuación del punto anterior, consiste en poder iniciar o detener el sistema en cualquier momento y minimizar estos tiempos para asegurar la disponibilidad del sistema.

10. Igualdad entre desarrollo y producción

Mantener desarollo, preproducción y producción tan parecidos como sea posible. Consiste en realizar despliegues de forma continua para garantizar que el código base se mantiene siempre igual en todos los entornos y difiere el menor tiempo posible.

11. Logs como eventos

Es ideal no mantener los logs (o historiales) como ficheros locales, sino que sean enviados a sistemas centralizados donde puedan ser analizados por personas cuando suceda algún error o por sistemas automáticos que puedan generar alarmas o alertas para reaccionar antes ante los errores.

12. Tareas de gestión no permanentes

Ejecutar las tareas de gestión/administración como procesos que solo se ejecutan una vez. Lo ideal es configurar a través de cron todas las tareas que necesiten realizarse de forma periódica y evitar lo máximo posible el uso de demonios para este tipo de tareas.

Conclusiones

Como dije al inicio estas son las reflexiones a las que llegaron un conjunto de personas que trabajan en diversos lenguajes, diversas plataformas y con distintas tecnologías de virtualización para despliegue de sus productos y proyectos.

La mayoría de estos puntos los puedes encontrar más desarrollados en el sitio web 12factor.net. Desde mi punto de vista todos son muy coherentes y garantizan el despliegue fácil del código en cualquier plataforma y en cualquier tamaño elegido (número de servidores).

¿Sigues alguna de estas indicaciones? ¿no te convence alguna de ellas? ¿quieres saber más sobre cómo poder integrar esta metodología en tus sistemas? ¡Déjanos un comentario!