El manifiesto “The Twelve-Factor App”

Vamos a conocer un manifiesto que contiene los puntos fundamentales que debería cumplir el desarrollo de una aplicación preparada para ser distribuida como un servicio.

1. Introducción

No cabe duda de que en el mundo del desarrollo el cambio es una constante en prácticamente todos los aspectos. Y uno de ellos es el de la distribución de aplicaciones: hemos pasado de aplicaciones que se ejecutaban en ordenadores locales a aplicaciones distribuidas en servidores Web ejecutados en ordenadores conectados a Internet; posteriormente aparecieron los servicios de hosting, que evolucionaron a la nube, que nos ofrece diferentes modelos bastante alejados ya del clásico ordenador en el que nos teníamos que montar todo, desde el sistema operativo, drivers, servidor de aplicaciones, conexiones a Internet, firewalls…

Actualmente, en el mundo del cloud computing podemos clasificar los servicios en alguna de estas tres capas incrementales:

  • IaaS (Infraestructura as a Service): se refiere a la posibilidad de hacer uso de ordenadores en la nube, bien físicos o máquinas virtuales. No dista mucho del modelo clásico de tener el control total de un ordenador donde tenemos que montar todo (aunque hay imágenes prefabricadas). Además incluyen otros elementos como firewalls, balanceadores, almacenamientos… Ejemplos: Amazon EC2, Microsoft Azure o muchos distribuidores menos conocidos: Gigas, OVH, Arsys…
  • PaaS (Platform as a Service): una capa por encima del IaaS: nos dan por ejemplo el acceso al servidor de aplicaciones, de modo que nos abstrae del sistema operativo y del resto de componentes, que ya nos dan mantenidos. De este modo nos olvidamos de mantener las máquinas, sistemas operativos y nos podemos centrar en la aplicación. Por ejemplo tenemos Amazon Lambda, Heroku o Google App Engine, donde simplemente subimos el fichero .war con nuestra aplicación. El resto de cosas ya están solucionadas.
  • SaaS (Software as a Service): lo que hacemos es comprar el uso de una aplicación bajo demanda: Office 360, Google Drive, Flickr, Gmail, Facebook… Nos olvidamos completamente de la instalación y del mantenimiento.

La llegada de la nube (cloud computing) y de estos nuevos modelos, ha provocado un cambio en la forma de desarrollar y mantener aplicaciones, o mejor dicho en su ciclo de vida. Bajo mi punto de vista estos son algunos de los puntos claves:

  • Ahora tenemos acceso a poder utilizar un gran número de máquinas.
  • La popularización de Internet hace que sea factible llegar a un gran público (viral en ocasiones), de modo que podemos utilizar el acceso a un número enorme de máquinas para cubrir las altas demandas. ¡Más vale que estemos listos para escalar!
  • La necesidad de automatizar todo. Cuando había un par de servidores era factible hacer operaciones a mano, pero con cientos es imposible. Así surge DevOps…
  • La alta competencia exige alta adaptación: las aplicaciones deben estar vivas para responder a los cambios de requisitos, por lo que deben poder desplegarse rápidamente.
  • La aparición de nuevos modelos fruto del nuevo esquema: ya no nos valen las máquinas con sus sistemas operativos, ahora se tiende a hacer containers aislados, microservicios, funciones como servicios (FaaS)…

Conclusión: como desarrolladores también tenemos que prestar mucha atención no sólo a los requisitos funcionales de la aplicación sino también al entorno en el que se va a ejecutar.

2. El Manifiesto “Twelve-Factor Apps”

Ahora también nos ha dado por la “serverless architecture”… y leyendo sobre ello en la página de Martin Fowler (http://martinfowler.com/articles/serverless.html) me encontré varias veces con la mención a un manifiesto sobre el desarrollo de aplicaciones SaaS que pienso que ilustra muy bien los “12 mandamientos” que deberíamos cumplir en el desarrollo de aplicaciones en la nube.

Se trata de un manifiesto algo viejo ya (de 2012), creado por desarrolladores experimentados en la creación y despliegue de aplicaciones en Heroku, y que recoge los 12 puntos claves que ellos consideran que se deberían cumplir para el desarrollo de aplicaciones en la nube. En realidad, en el manifiest indican aplicaciones SaaS, es decir, que se desarrolla para desplegar en PaaS, pero los consejos que dan yo los aplicaría a cualquier desarrollo de aplicación que vaya a ser distribuida en Internet hoy en día. Me parecen consejos generales que es fundamental cumplir.

El manifiesto es de libre acceso y está traducido a diferentes idiomas, entre ellos el castellano: http://12factor.net/es/ así que me limitaré a hacer un breve resumen.

2.1. Objetivos del manifiesto

En la introducción se indica que el objetivo es lograr:
  • Usar configuraciones automatizables y explícitas, nada manual.
  • Dependencias claras con el entorno en el que se ejecutan para máxima compatibilidad.
  • Tener en cuenta que la aplicación será desplegada en la nube.
  • Despliegue continuo, por tanto requiere coordinación de entornos (test-uat-pre-pro…).
  • Crear aplicaciones con la escalabilidad en la mente.

2.2. Los 12 factores

Como he indicado antes, el manifiesto es corto de leer, así que te recomiendo que acudas a la fuente original (http://12factor.net/es/, aunque mejor en inglés – http://12factor.net/). Haré aquí un rápido repaso (quizá con mi opinión) por cada uno de los puntos y animarte así a que profundices en estos mandamientos o factores:

  1. Código Base: el código debe estar en repositorios y es desde ahí donde se harán los despliegues a los entornos. Puede haber varios repositorios si la aplicación es compleja, pero no se puede repetir código entre repositorios (hacer un split común).

  2. Dependencias: todas las dependencias de la aplicación deben ser explícitas y existir un sistema automático que las instale si no existen. Por ejemplo, un proyecto Java bien montado con Maven o con Gradle no presupone que hay librerías instaladas en la máquina: las descarga si no las tiene. Pienso que de igual manera se tiene que aplicar al sistema operativo: apt-get para instalar curl…

  3. Configuraciones: el código no puede tener configuraciones, sino que deben ser separadas en otros recursos dependientes del entorno. Así, el código debe hacer referencia a las variables de configuración pero no a los valores. Esto permite instalar el mismo código en diferentes entornos. Ejemplos: URL de servicios, claves de bases de datos, variables de entorno…

  4. Backing services: son recursos conectables a la aplicación, independientemente de si son locales o de terceros. Si la aplicacion necesita una base de datos, será tratada como un recurso independiente, con su URL y su instalación, que deben ser proporcionados a la aplicación. Si un servidor de bases de datos proporciona 2 esquemas diferentes, serán tratados como si estuvieran en servidores diferentes (aunque luego sus URL y credenciales coincidan).

  5. Construir, distribuir y ejecutar: son las 3 etapas que se deben pasar para transformar el código fuente en un producto utilizable. Deben ser tratadas de forma independiente y con un control de las versiones que se van distribuyendo acorde a un sistema preestablecido. Nada de darle al botón build del eclipse sobre el servidor de producción :-).

  6. Procesos sin estado (stateless): la aplicación se ejecuta en el destino como un proceso (o varios) en la máquina anfitriona pero la información que existe en su espacio de memoria sólo tiene lo necesario para hacer las transacciones que lleva a cabo en ese momento, no para atender a transacciones futuras: puede reiniciarse la máquina, aparecer otro proceso… La información que sea necesario almacenar para el futuro se hará en un Backing Service como Redis, Memcache… Olvídate del “Sticky Session”… esto es ¡escalable!

  7. Asignacion de puertos: el código no puede considerar a priori la asignación de los puertos. Simplemente sabe que es un proceso que escucha en un puerto arbitrario. Será la configuración la que establezca los puertos de cada componente. Esto es similar a lo que sucede con los microservicios y/o con Docker: en una misma máquina hay diferentes procesos escuchando en puertos configurados, y que incluso unos procesos actúan como Backing services de otros.

  8. Concurrencia: las aplicaciones deben estar desarrolladas teniendo en mente la concurrencia, bien de hilos o bien de procesos. La razón principal es la naturaleza distribuida y la capacidad para escalar levantando nuevas máquinas. Los procesos nunca deberían ser de tipo demonio, sino delegar en el sistema operativo y los mecanismos que dispone.

  9. Disponibilidad: las aplicaciones deben ser capaces de iniciar sus procesos rápidamente y de respoder de forma controlada a la finalización, aunque esta sea inesperada. Cuando hablamos de escalado, nos referimos al inicio o parada en caliente de nuevas máquinas o al traslado a diferentes máquinas de los procesos.

  10. Paridad en el desarrollo y producción: se refiere a tener los diferentes entornos (des-pre como mínimo) lo más similares posibles, tanto de versiones de código desplegado, como de entornos y servicios. Esto se hace con despliegues continuos, lo que implica automatizar los despliegues lo máximo posible, que el personal de desarrollo sea mucho más consciente del entorno de producción y que incluso se compartan modos de trabajo entre entornos aunque no sea lo más evidente a primera vista: puppet, chef, ansible…

  11. Historiales: o más conocidos como “Logs”. Las aplicaciones no se preocupan del direccionamiento y almacenamiento de sus datos de logs. Para eso existen sistemas específicos en cada entorno. Incluso actualmente es posible disponer de sistema de procesamiento en tiempo real como Splunk o ELK, que permiten estar al tanto de una manera más sencilla del comportamiento de la aplicación.

  12. Administrador de procesos: además de los procesos propios de la ejecución de la aplicación, existirán procesos de tareas de administración y mantenimiento que suelen ejecutarse una única vez. Estos procesos, aunque puedan parecer secundarios, se ejecutarán con igual importancia que el resto de los procesos de la aplicación. Además, se recomienda el uso de consolas REPL si el entorno dispone de ellas (en Java 9 habrá una).

Parece que tiene sentido, ¿no? Quizá sea una buena idea que evalúes cuántos puntos de este dodecálogo estás cumpliendo :).

3. Conclusiones

Las nuevas opciones para la distribución de las aplicaciones en Internet afectan a la forma de desarrollarlas y en general a su ciclo de vida: la necesidad de adaptarse a la demanda, tanto en número como nuevas capacidades, y hacerlo con una demora cada vez menor, nos fuerza a adoptar nuevos enfoques.

En este tutorial hemos hecho un repaso al manifiesto “Twelve-Factor app” para el desarrollo de aplicaciones en la nube, un dodecálogo cargado de experiencia y sentido común que es muy conveniente tener en cuenta en nuestros desarrollos.