METODOLOGÍA TWELVE FACTOR
I.
CÓDIGO BASE (CODEBASE)
El código base es
cualquier repositorio, o cualquier conjunto de repositorios que comparten un
commit raíz, como Git, Mercuarial o subversión que son sistema de control de versiones.
Hay una relación entre la aplicación y el código base:
Si hay más de un código
base, no se consideraría una aplicación sería más un sistema distribuido, en
este cada componente es una aplicación
Si se comparte el
código con varias aplicaciones, irrumpiría con las reglas de la metodología de
Twelve factor por ende no se consideraría como tal. Para evitar este problema
se tendría que separar el código en librerías y que se enlace por medio de un
gestor de dependencia
Para trabajar en la app, descarga el código en tu entorno de desarrollo local. El almacenamiento del código en un sistema de control de versiones le permite a tu equipo trabajar en conjunto y proporciona un registro de auditoría de cambios en el código, una forma sistemática de resolver conflictos de fusión y la capacidad de revertir el código a una versión anterior. También proporciona un lugar desde el cual realizar la integración continua (IC) y la implementación continua (CD).
![]() |
II.
DEPENDENCIAS
La mayoría de los
lenguajes de programación tienen un sistema de gestión de paquetes para
distribuir sus librerías, como CPAN en Perl o Rubygems en Ruby. Las librerías
instaladas a través de estos sistemas se pueden instalar en el sistema (también
conocido como “site packages”) o limitarse al directorio que contiene la
aplicación (también conocido como “vendoring” o “bundling”).
En este caso hay dos consideraciones: declaración de dependencia y aislamiento de dependencia. Declarar dependencias explícitamente y aislarlas. La aplicación declara sus dependencias bibliotecas, componentes externos— de forma explícita y precisa por medio de un manifiesto o especificación. Adicionalmente, se debe utilizar una herramienta para aislar dependencias y de esta forma evitar que se “cuelen” dependencias implícitas provenientes del ambiente de ejecución.
Por ejemplo, en Ruby se puede usar Gem Bundler para declarar dependencias y bundle exec para aislar dependencias. En Python se usa Pip para declaración y Virtualenv para aislamiento. Incluso en C se puede usar Autoconf para declaración y enlaces estáticos (static linking) para aislamiento. No importa cuáles sean las herramientas, la declaración de dependencias siempre se debe usar en conjunto con un mecanismo de aislamiento.
![]() |
III.
CONFIGURACIONES
Guardar la configuración en el entorno. La configuración de una aplicación está relacionada con aquellos parámetros que pueden variar dependiendo del ambiente (producción, pruebas, desarrollo). Esto incluye: urls a otros servicios, contraseñas de base de datos, valores que varían en cada instancia.
Guardar estos valores como constantes en el código es una práctica no segura y que viola los 12 factores. La configuración puede variar entre instancias, pero el código no debe variar. La práctica recomendada consiste en que la configuración se haga disponible a la aplicación por medio de variables de entorno (env vars).
IV.
BACKING SERVICES
Se debe acceder como un servicio a todos los servicios que la app consume como parte de su funcionamiento normal, como los sistemas de archivos, las bases de datos, los sistemas de almacenamiento en caché y las colas de mensajes, y externalizarse en la configuración. Debes pensar en estos servicios de copia de seguridad como abstracciones para el recurso subyacente. Por ejemplo, cuando la app escribe datos a fin de almacenarlos, si tratas el almacenamiento como un servicio de copia de seguridad, podrás cambiar sin problemas el tipo de almacenamiento subyacente, ya que está separado de la app. Luego, puedes realizar un cambio, como cambiar de una base de datos local de PostgreSQL a Cloud SQL para PostgreSQL sin cambiar el código de la app.
V.
CONSTRUIR, DESPLEGAR, EJECUTAR
El código base se transforma en un despliegue (que no es de desarrollo) al completar las siguientes tres etapas:
a. La etapa de construcción(build)
es una transformación que convierte un repositorio de código en un paquete
ejecutable. se genera un paquete ejecutable a partir de la base de código. El
paquete ejecutable puede contener dependencias (bibliotecas), código ejecutable
(ya sea binario o interpretado) y activos (ej. Imágenes, hojas de estilo).
b. En la fase de distribución (release)
toma el paquete ejecutable y lo combina con una configuración de despliegue. El
paquete resultante contiene tanto el build como la configuración y está
listo para ejecutarse
c. La fase de ejecución (runtime)
ejecuta la aplicación en el entorno de ejecución, lanzando un conjunto de
procesos de una distribución concreta de la aplicación.
Separar completamente las fases de construcción, de distribución y de ejecución. En la construcción se traen todas las dependencias y se compilan los binarios para generar un artifact. En la distribución se usa esta construcción y se combina con la configuración. Finalmente, en la ejecución, se lanza la aplicación como un conjunto de procesos.
VI.
PROCESOS
La aplicación se ejecuta en forma de procesos sin estado.
En el escenario más simple, una aplicación consiste de un solo script y el ambiente de ejecución es una computadora personal con el runtime, y el proceso es lanzado por medio de línea de comandos (por ejemplo, python mi_script.py).
La aplicación opera como procesos independientes que no comparten nada entre sí. Cualquier dato que requiera guardarse debe ser almacenado en un servicio externo de persistencia, típicamente una base de datos. El espacio en memoria o sistema de archivos se puede usar como caché temporal para transacciones individuales, pero nada más. La aplicación nunca puede asumir que algo cacheado en memoria o disco estará disponible para una petición futura, ya que no hay ninguna garantía de que una petición futura sea atendida por el mismo proceso. Incluso cuando la aplicación se ejecute en un proceso único en un solo nodo de cómputo, este puede ser reiniciado en cualquier momento. Algunas aplicaciones web utilizan “sesiones pegajosas” (sticky sessions) —es decir, almacenar el estado de la sesión del usuario en memoria del proceso y esperar que las peticiones futuras sean ruteadas al mismo proceso. Esto es una violación de los 12 factores. Para guardar el estado de la sesión del usuario se puede usar un almacén con expiración de tiempo, como Redis o Memcached.
VII.
ASIGNACIÓN DE PUERTOS
En entornos que no están en la nube, las aplicaciones web a menudo se escriben para ejecutarse en contenedores de app como GlassFish, Apache Tomcat y Apache HTTP Server. En cambio, las apps de doce factores no dependen de los contenedores de apps externos.
Una práctica recomendada de arquitectura para los servicios es exponer un número de puerto, especificado por la variable de entorno PORT
Las aplicaciones cloud-native están completamente autocontenidas y no dependen de un servidor web. La aplicación exporta HTTP como un servicio, siento todo parte de la aplicación y solamente se expone el puerto para atender peticiones.
VIII.
CONCURRENCIA
Debes
descomponer tu app en procesos independientes basados en tipos de procesos,
como procesos en segundo plano, web y trabajadores. Esto permite que tu app
escale verticalmente o se reduzca según los requisitos de carga de trabajo
individuales. La mayoría de las aplicaciones nativas de la nube te permiten
escalar a pedido. Debes diseñar la app como múltiples procesos distribuidos que
puedan ejecutar bloques de trabajo de forma independiente y escalar horizontalmente
mediante el agregado de procesos.
Por ejemplo, las peticiones HTTP pueden manejarse por un proceso “web” mientras que las tareas de larga duración pueden ser manejadas por otro proceso “worker” que tiene diferente prioridad
IX.
DESECHABILIDAD
Los procesos de las aplicaciones “twelve-factor” son desechables, lo que significa que pueden iniciarse o finalizarse en el momento que sea necesario. Esto permite un escalado rápido y flexible, un despliegue rápido del código y de los cambios de las configuraciones, y despliegues más robustos en producción.
Hacer el sistema más robusto por medio de arranque rápido y apagado gentil. Los procesos de la aplicación son desechables, es decir que pueden ser iniciados y terminados en cualquier momento. Esto facilita la escalabilidad y el despliegue de cambios en el código o la configuración.
“Apagado gentil” es la traducción más cercana que se nos ocurre de graceful shutdown. En este caso se refiere a que cuando un proceso recibe una señal de finalización (SIGTERM) por parte del administrador de procesos debe: 1) dejar de escuchar el puerto de servicio, 2) finalizar las peticiones pendientes (o regresarlas a una cola de trabajo) y 3) terminar su ejecución.
X.
PARIDAD EN DESARROLLO Y PRODUCCIÓN
Históricamente, han existido dos
tipos de entorno muy diferenciados: desarrollo y producción. Estas diferencias
se pueden clasificar en tres tipos:
- Diferencias
de tiempo: Un desarrollador puede estar trabajando en un código durante días,
semanas o incluso meses antes de que llegue a producción.
- Diferencias de personal: Los desarrolladores escriben el código y los ingenieros de operaciones lo despliegan.
- Diferencias de herramientas: Los desarrolladores pueden usar una pila como Nginx, SQLite y OS X, mientras que en producción se usa Apache, MySQL y Linux.
En contraste, una aplicación
twelve-factor está diseñada para entrega continua y para lograrlo reduce las
brechas que se mencionaron anteriormente.
- Reducir la brecha de tiempo entre liberaciones, haciendo varias liberaciones a la semana o incluso al día.
- Reducir la brecha en personal involucrando a los desarrolladores en el despliegue y monitoreo de la aplicación en producción.
- Reducir la brecha en herramientas manteniendo los ambientes de desarrollo y producción lo más parecidos posible.
XI.
HISTORIALES
Los registros te proporcionan conocimiento del estado de tus apps. Es importante separar la recopilación, el procesamiento y el análisis de registros de la lógica central de tus apps. El registro de separación es útil, en especial, cuando tus apps requieren escalamiento dinámico y se ejecutan en nubes públicas, ya que quita la sobrecarga de administrar la ubicación de almacenamiento para registros y la agregación de VM distribuidas
Una aplicación “twelve-factor” nunca se preocupa del direccionamiento o el almacenamiento de sus transmisiones de salida. No debería intentar escribir o gestionar ficheros de historial. En su lugar, cada proceso en ejecución escribe sus eventos a la salida estándar (o stdout). Durante el desarrollo, los desarrolladores verán el flujo en su terminal para observar el comportamiento de la aplicación.
XII. ADMINISTRACIÓN DE PROCESOS
Ejecutar las tareas administrativas como procesos de la aplicación. Es común tener que realizar tareas administrativas o de mantenimiento en una aplicación, tales como ejecutar scripts para limpiar datos, exportar datos, o disparar una consola para ejecutar algún código arbitrario.
Este tipo
de procesos administrativos se deberían manejar en un ambiente idéntico al de
los procesos normales de la aplicación. Es decir, son parte del código base de
la aplicación y se ejecutan en el contexto de una aplicación liberada, con la
misma configuración. También se debe utilizar la misma técnica de aislamiento
de dependencias (ej. bundle exec o Virtualenv) que se haya usado con los
procesos normales de la aplicación.


Comentarios
Publicar un comentario