Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

Para comenzar, un poco de teoría. ¿Qué es La Aplicación de Doce Factores?

En términos simples, este documento está diseñado para simplificar el desarrollo de aplicaciones SaaS, ayudando a informar a los desarrolladores e ingenieros de DevOps sobre los problemas y prácticas más comunes en el desarrollo de aplicaciones modernas.

El documento fue creado por los desarrolladores de la plataforma Heroku.

La metodología de doce factores (The Twelve-Factor App) puede aplicarse a aplicaciones escritas en cualquier lenguaje de programación y que utilizan cualquier combinación de servicios externos (backing services) (bases de datos, colas de mensajes, almacenamiento en caché, etc.).

En breve sobre los propios factores en los que se basa esta metodología:

  1. Base de código – Una base de código, controlada por un sistema de control de versiones, – múltiples despliegues
  2. Dependencias – Declare y aísle explícitamente las dependencias
  3. Configuración – Almacene la configuración en el entorno de ejecución
  4. Servicios externos (Backing Services) – Considere los servicios externos (backing services) como recursos conectables
  5. Construcción, lanzamiento, ejecución – Separe estrictamente las etapas de construcción y ejecución
  6. Procesos – Ejecute la aplicación como uno o varios procesos sin estado (stateless)
  7. Vinculación de puertos (Port binding) – Exporte servicios a través de la vinculación de puertos
  8. Paralelismo – Escale la aplicación mediante procesos
  9. Desechabilidad (Disposability) – Maximice la fiabilidad mediante un inicio rápido y una correcta finalización
  10. Paridad entre el desarrollo y la operación de la aplicación – Mantenga los entornos de desarrollo, despliegue intermedio (staging) y producción lo más parecidos posible
  11. Registro (Logs) – Considere el registro como un flujo de eventos
  12. Tareas de administración – Realice tareas de administración/gestión mediante procesos únicos

Puede obtener más información sobre los 12 factores en los siguientes recursos:

¿Qué es el despliegue Blue-Green?

El despliegue Blue-Green es un método para entregar una aplicación en producción de manera que el cliente final no ve ningún cambio por su parte. En otras palabras, el despliegue de la aplicación ocurre sin un tiempo de inactividad.

El esquema clásico de BG Deploy se ve como se indica en la imagen a continuación.

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

  • Al inicio hay 2 servidores físicos con exactamente el mismo código, aplicación, proyecto, y hay un enrutador (balanceador).
  • El enrutador inicialmente dirige todas las solicitudes a uno de los servidores (verde).
  • En el momento en que se necesita volver a realizar un lanzamiento, todo el proyecto se actualiza en el otro servidor (azul), que en ese momento no está procesando ninguna solicitud.
  • Después de que el código en el servidor azul ha sido completamente actualizado, se le da una orden al enrutador de que debe cambiar del servidor verde en azul servidor.
  • Ahora todos los clientes ven el resultado del trabajo del código en el servidor azul Ejecutan ataques móviles.
  • Por un tiempo, verde el servidor sirve como copia de seguridad en caso de un despliegue fallido en azul el servidor y en caso de fallos o errores, el enrutador cambia el flujo de usuarios de nuevo al verde servidor con la versión estable anterior, y el nuevo código se envía para su desarrollo y pruebas.
  • Y al final del proceso, de la misma manera se actualiza verde el servidor. Y después de su actualización, el enrutador cambia el flujo de solicitudes de vuelta al verde servidor.

Todo esto se ve muy bien y a primera vista no debería haber problemas con ello.
Pero ya que vivimos en un mundo moderno, la opción de cambio físico como se indica en el esquema clásico no nos conviene. Fijen esta información por ahora, volveremos a ella más tarde.

Consejos buenos y malos

Descargo de responsabilidad: En los ejemplos a continuación se enumeran herramientas / metodologías que utilizo, pueden usar alternativas absolutamente cualquieras con funciones similares.

La mayor parte de los ejemplos de una manera u otra se cruzará con el desarrollo web (vaya, sorpresa), con PHP y Docker.

Los puntos a continuación ofrecen una simple descripción práctica del uso de factores en ciertos ejemplos, si desean obtener más teoría sobre este tema, consulten las fuentes arriba.

1. Base de código

Usen FTP y FileZilla para cargar archivos en los servidores uno por uno, no almacenen el código en ningún lugar excepto en el servidor de producción.

El proyecto siempre debe tener una única base de código, es decir, todo el código proviene de uno solo. Git repositorios. Los servidores (producción, staging, prueba1, prueba2...) utilizan código de ramas de un repositorio común. De esta manera, logramos la consistencia del código.

2. Dependencias

Descargue todas las bibliotecas en carpetas directamente en la raíz del proyecto. Las actualizaciones se realizan simplemente trasladando el nuevo código a la carpeta de la versión actual de la biblioteca. Instale todas las utilidades directamente en el servidor de alojamiento donde funcionan otras 20 aplicaciones.

El proyecto siempre debe tener una lista de dependencias clara y comprensible (por dependencias también entiendo el entorno). Todas las dependencias deben estar claramente definidas y aisladas.
Como ejemplo tomaremos Composer y Docker.

Composer — un gestor de paquetes que permite instalar bibliotecas en PHP. Composer permite especificar versiones de manera estricta o no estricta, y definirlas explícitamente. En el servidor pueden existir 20 proyectos diferentes y cada uno tendrá su propia lista de paquetes y bibliotecas, sin depender de los demás.

Docker — una utilidad que permite definir y aislar el entorno en el que funcionará la aplicación. Por lo tanto, al igual que con Composer, pero de manera más exhaustiva, podemos definir con qué trabaja la aplicación. Seleccionar una versión específica de PHP, instalar solo los paquetes necesarios para el proyecto sin añadir nada extra. Y lo más importante, no mezclarse con los paquetes y el entorno de la máquina host y otros proyectos. Es decir, todos los proyectos en el servidor que funcionan a través de Docker pueden utilizar cualquier conjunto de paquetes y un entorno completamente diferente.

3. Configuración

Almacene las configuraciones como constantes directamente en el código. Constantes separadas para el servidor de prueba y separadas para producción. Vincule el funcionamiento de la aplicación a las dependencias del entorno directamente en la lógica empresarial del proyecto utilizando construcciones if else.

Configuraciones — es lo único que debería diferenciar los despliegues del proyecto (deployment). Idealmente, las configuraciones deberían transmitirse a través de variables de entorno (env vars).

Es decir, incluso si almacenas varios archivos de configuración .config.prod, .config.local y los renombras al momento de desplegar a .config (la configuración principal de la cual la aplicación lee los datos) — este no sería un enfoque correcto, ya que de esa manera la información de las configuraciones estará públicamente accesible para todos los desarrolladores de la aplicación y los datos del servidor de producción estarán comprometidos. Todas las configuraciones deben almacenarse directamente en el sistema de despliegue (CI/CD) y generarse para diferentes entornos con los distintos valores necesarios para cada entorno precisamente en el momento del despliegue.

4. Servicios Externos (Backing Services)

Establece una fuerte dependencia del entorno, utiliza diferentes conexiones para los mismos servicios en entornos específicos.

De hecho, este punto se superpone en gran medida con el punto sobre las configuraciones, ya que sin este punto no se pueden crear datos de configuración apropiados y la posibilidad de configurar se perdería por completo.

Todas las conexiones a servicios externos, como servidores de colas, bases de datos, y servicios de caché deben ser iguales tanto para el entorno local como para el entorno externo/producción. En otras palabras, en cualquier momento, puedo cambiar la cadena de conexión de la base #1 a la base #2 sin modificar el código de la aplicación. O adelantándome, como ejemplo, al escalar el servicio, no tendrás que especificar la conexión de un servidor de caché adicional de una manera especial.

5. Compilación, Lanzamiento, Ejecución

Ten solo la versión final del código en el servidor, sin posibilidad de revertir el lanzamiento. No hay que ocupar espacio en disco. ¡Quien piensa que puede lanzar código en producción con un error, es un mal programador!

Todas las etapas de despliegue deben estar separadas entre sí.

Ten la oportunidad de revertir. Realiza lanzamientos conservando copias antiguas de la aplicación (ya compiladas y listas para producción), para que en caso de errores puedas restaurar la versión anterior. Es decir, hay una carpeta releases y una carpeta corriente, y después de un despliegue y compilación exitosos, la carpeta corriente se enlaza con un enlace simbólico al nuevo lanzamiento que está dentro de releases con un nombre condicional del número de lanzamiento.

Aquí es donde recordamos el despliegue Blue-Green, que no solo permite cambiar entre el código, sino también entre todos los recursos e incluso entornos, con la posibilidad de revertir todo.

6. Procesos

Guarde los datos del estado de la aplicación directamente en la propia aplicación. Utilice sesiones en la memoria del propio aplicativo. Utilice tanto como sea posible recursos compartidos entre servicios externos. Sujete la idea de que la aplicación solo puede tener un proceso y evite la posibilidad de escalar.

En cuanto a las sesiones, almacene los datos únicamente en cachés controladas por servicios externos (memcached, redis), de esta manera, incluso si tiene 20 procesos de la aplicación en ejecución, cualquiera de ellos, al acceder a la caché, podrá continuar trabajando con el cliente en el mismo estado en que el usuario estaba interactuando con la aplicación en otro proceso. Con este enfoque, no importa cuántas copias de servicios externos esté utilizando, todo funcionará normalmente sin problemas de acceso a los datos.

7. Vinculación de puertos (Port binding)

El único que debe saber cómo trabajar con servicios externos es el servidor web. Mejor aún, levante los servicios externos directamente dentro del servidor web. Por ejemplo, como un módulo PHP en Apache.
Todos sus servicios deben ser accesibles entre sí a través de un determinado dirección y puerto (localgost:5432, localhost:3000, nginx:80, php-fpm:9000), es decir, desde nginx puedo acceder tanto a php-fpm como a postgres, y desde php-fpm hacia postgres y nginx; y, de hecho, desde cada servicio puedo acceder a otro servicio. Así, la viabilidad de un servicio no depende de la viabilidad de otro servicio.

8. Paralelismo

Trabaje con un solo proceso, porque si no, puede que varios procesos no se lleven bien entre sí.

Deje abierta la posibilidad de escalar. Docker Swarm es ideal para esto.
Docker Swarm es una herramienta para crear y gestionar clústeres de contenedores, tanto entre diferentes máquinas como en un gran número de contenedores en una sola máquina.

Usando swarm, puedo determinar cuántos recursos asignaré a cada proceso y cuántos procesos del mismo servicio iniciaré, y el balanceador interno, al recibir datos en un puerto designado, los proxeará automáticamente a los procesos. De esta manera, al ver que la carga en el servidor ha aumentado, puedo agregar más procesos, reduciendo así la carga en ciertos procesos.

9. Descartabilidad (Disposability)

No utilice colas para trabajar con procesos y datos. La terminación de un proceso debe afectar el funcionamiento de toda la aplicación. Si un servicio cae, todo cae.

Cada proceso y servicio puede ser apagado en cualquier momento y eso no debe afectar a otros servicios (no me refiero a que un servicio no esté disponible para otro servicio, sino a que otro servicio no se apague junto con este). Todos los procesos deben finalizarse suavemente, de manera que al terminar no se comprometan los datos y, al reiniciarse, el sistema funcione correctamente. Es decir, incluso en caso de un cierre inesperado, los datos no deben verse afectados (aquí es donde entra el mecanismo de transacciones; las consultas a la base de datos solo funcionan en grupos, y si al menos una consulta del grupo falla o se ejecuta con error, entonces ninguna otra consulta del grupo se ejecuta realmente).

10. Paridad entre desarrollo/operaciones de aplicación

La versión de producción, la de staging y la local de la aplicación deben ser diferentes. En producción tenemos el framework Yii Lite, mientras que localmente usamos Yii, ¡para que en producción funcione más rápido!

De hecho, todos los despliegues y el trabajo con el código deben estar en un entorno casi idéntico (no se refiere al hardware físico). Además, cualquier miembro del equipo de desarrollo debe ser capaz de desplegar el código en producción, no solo un departamento de devops entrenado especialmente, que solo puede levantar la aplicación en producción gracias a un poder especial.

Esto también es facilitado por Docker. Al seguir todos los puntos anteriores, el uso de Docker hará que el proceso de despliegue del entorno, tanto en producción como en la máquina local, se reduzca a ingresar uno o dos comandos.

11. Registro (Logs)

¡Escribimos logs en archivos y en la base de datos! No limpiamos archivos ni la base de datos de logs. Simplemente compraremos un disco duro de 9000 petabytes y listo.

Todos los registros deben considerarse como un flujo de eventos. La aplicación misma no debe encargarse de procesar los registros. Los registros deben enviarse ya sea a stdout, o enviarse a través de un protocolo como udp, de modo que el trabajo de la aplicación con los registros no cree ningún problema. Graylog es una buena opción para esto. Graylog, al recibir todos los registros por udp (con este protocolo no se requiere esperar una respuesta de confirmación de recepción del paquete) no interfiere con la aplicación de ninguna manera y se encarga únicamente de estructurar y procesar los registros. La lógica de la aplicación no cambia para trabajar con este tipo de enfoques.

12. Tareas de administración

Para actualizar datos, bases de datos, etc., utilice un endpoint creado por separado en la API, cuya ejecución dos veces seguidas puede causar que todo se duplique. Pero ustedes no son tontos, no harán clic dos veces, y las migraciones no son necesarias.

Todas las tareas de administración deben realizarse en el mismo entorno que todo el código, a nivel de lanzamientos. Es decir, si necesitamos cambiar la estructura de la base de datos, no lo haremos manualmente, cambiando el nombre de las columnas y agregando nuevas a través de herramientas visuales de gestión de bases de datos. Para tales cosas, creamos scripts separados — migraciones, que se ejecutan en todos los entornos de la misma manera y con un resultado claro y comprensible. Para todas las demás tareas, como llenar el proyecto con datos, deben aplicarse metodologías similares.

Ejemplo de implementación en PHP, Laravel, Laradock, Docker-Compose

P.D. Todos los ejemplos se hicieron en MacOS. La mayor parte también es aplicable a Linux. Usuarios de Windows, lo siento, pero no he trabajado con Windows desde hace tiempo.

Imaginemos que en nuestra PC no está instalada ninguna versión de PHP y, de hecho, no hay nada.
Instalamos las últimas versiones de docker y docker-compose. (esto se puede encontrar en Internet)

docker -v && 
docker-compose -v

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

1. Instalamos Laradock

git clone https://github.com/Laradock/laradock.git && 
ls

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

Sobre Laradock, diré que es una herramienta excelente, que incluye muchos contenedores y utilidades. Pero no recomendaría usar Laradock tal cual en producción debido a su sobrecarga. Es mejor crear sus propios contenedores basándose en los ejemplos de Laradock, ya que así habrá más espacio para optimizar, porque a nadie le sirve tener todo lo que hay allí al mismo tiempo.

2. Configuramos Laradock para que trabaje con nuestra aplicación.

cd laradock && 
cp env-example .env

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

2.1. Abrimos el directorio habr (la carpeta principal donde se clonó laradock) en cualquier editor. (En mi caso, PHPStorm)

En esta etapa, solo asignamos un nombre al proyecto.

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

2.2. Iniciamos la imagen del workspace. (En su caso, las imágenes estarán construyéndose por un tiempo)
Workspace es una imagen especialmente preparada para trabajar con el framework como desarrollador.

Entramos en el contenedor usando

docker-compose up -d workspace && 
docker-compose exec workspace bash

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

2.3. Instalamos Laravel

composer create-project --prefer-dist laravel/laravel application

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

2.4. Después de la instalación, verificamos si se ha creado el directorio del proyecto y detenemos el compose.

ls
exit
docker-compose down

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

2.5. Regresamos a PHPStorm y establecemos la ruta correcta a nuestra aplicación Laravel en el archivo .env.

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

3. Agregamos todo el código a Git.

Para ello, creamos un repositorio en GitHub (o en cualquier otro lugar). Vamos a la terminal, al directorio habr, y ejecutamos el siguiente código.

echo "# habr-12factor" >> README.md
git init
git add README.md
git commit -m "primer commit"
git remote add origin git@github.com:nzulfigarov/habr-12factor.git # aquí estará el enlace a tu repo
git push -u origin master
git status

Verificamos que todo esté en orden.

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

Para mayor comodidad, recomiendo usar alguna interfaz visual para Git, en mi caso es GitKraken. (aquí está el enlace de referencia)

4. ¡Arrancamos!

Antes de iniciar, asegúrese de que no haya nada ocupado en los puertos 80 y 443.

docker-compose up -d nginx php-fpm

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

De este modo, nuestro proyecto consta de 3 servicios separados:

  • nginx — servidor web
  • php-fpm — php para procesar peticiones desde el servidor web
  • workspace — php para el desarrollador

Hasta ahora hemos logrado crear una aplicación que cumple con los 4 puntos de los 12, a saber:

1. Base de código — todo el código está en un único repositorio (una pequeña observación: posiblemente sería correcto incluir docker dentro del proyecto laravel, pero no es esencial).

2. Dependencias — Todas nuestras dependencias están claramente especificadas en application/composer.json y en cada Dockerfile de cada contenedor.

3. Servicios externos (Backing Services) — Cada uno de los servicios (php-fpm, nginx, workspace) vive su propia vida y está conectado externamente, por lo que al trabajar con un servicio, otro no será afectado.

4. Procesos — cada servicio es un proceso único. Ninguno de los servicios guarda estado interno.

5. Vinculación de puertos (Port binding)

docker ps

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

Como vemos, cada servicio está corriendo en su propio puerto y es accesible para todos los demás servicios.

6. Paralelismo

Docker nos permite levantar múltiples procesos de los mismos servicios con balanceo de carga automática entre ellos.

Detendremos los contenedores y los reiniciaremos con el flag --scale

docker-compose down && 
docker-compose up -d --scale php-fpm=3 nginx php-fpm

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

Como podemos ver, se han creado copias del contenedor php-fpm. No necesitamos cambiar nada en el trabajo con este contenedor. Continuamos accediendo a él a través del puerto 9000, y Docker gestiona la carga entre los contenedores por nosotros.

7. Desechabilidad (Disposability) — se puede eliminar cada contenedor sin afectar a los demás. Detener o reiniciar un contenedor no impactará en el funcionamiento de la aplicación en ejecuciones posteriores. Cada contenedor también se puede levantar en cualquier momento.

8. Paridad entre el desarrollo y la operación de la aplicación — todos nuestros entornos son idénticos. Al ejecutar el sistema en el servidor de producción, no tendrás que cambiar nada en tus comandos. Todo estará basado exactamente igual en Docker.

9. Registro (Logs) — todos los logs en estos contenedores se envían a un flujo y son visibles en la consola de Docker. (en este caso, en realidad, con otros contenedores personalizados, puede que no sea así si no te ocupas de ello)

 docker-compose logs -f

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

Sin embargo, hay un inconveniente: los valores predeterminados en PHP y Nginx también registran logs en un archivo. Para cumplir con los 12 factores, es necesario desactivar registrar logs en archivos en la configuración de cada contenedor por separado.

Docker también ofrece la posibilidad de dirigir logs no solo a stdout, sino también a herramientas como graylog de las que hablé anteriormente. Dentro de graylog, podemos manejar los logs como queramos y nuestra aplicación no se verá afectada por eso.

10. Tareas de administración — todas las tareas de administración se resuelven en Laravel gracias a la herramienta artisan tal como lo habrían deseado los creadores de la aplicación de 12 factores.

Como ejemplo, mostraré cómo se ejecutan algunos comandos.
Entramos en el contenedor.

 
docker-compose exec workspace bash
php artisan list

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

Ahora podemos usar cualquier comando. (ten en cuenta que no configuramos la base de datos y la caché, por lo que la mitad de los comandos no se ejecutarán correctamente, ya que están destinados a trabajar con caché y bdd).

Desarrollo de aplicaciones y Blue-Green deployment, basado en la metodología The Twelve-Factor App con ejemplos en php y docker

11. Configuraciones y 12. Construcción, lanzamiento, ejecución

Esta parte quería dedicarla al Blue-Green Deployment, pero resultó ser demasiado extensa para este artículo. Escribiré un artículo separado sobre ello.

En pocas palabras, el concepto se basa en sistemas de CI/CD como Jenkins y Gitlab CI. En ambos se pueden definir variables de entorno relacionadas con el entorno específico. Por lo tanto, en tal disposición se cumplirá el punto sobre Configuraciones.

Y el punto sobre Construcción, lanzamiento, ejecución se resuelve con funciones integradas en ambas herramientas llamadas Pipeline.

Pipeline permite dividir el proceso de despliegue en múltiples etapas, destacando las fases de construcción, lanzamiento y ejecución. También en el Pipeline, podrá crear copias de seguridad, y en general, cualquier cosa. Esta herramienta tiene un potencial ilimitado.

El código de la aplicación se encuentra en Github.
No olvide inicializar el submódulo al clonar este repositorio.

P.D.: Todos estos enfoques se pueden utilizar con cualquier otra herramienta y lenguajes de programación. Lo importante es que la esencia no cambie.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster