Nuestra implementación de Despliegue Continuo en la plataforma del cliente

En True Engineering hemos establecido un proceso para la entrega continua de actualizaciones a los servidores de los clientes y queremos compartir esta experiencia.

Para empezar, desarrollamos un sistema en línea para el cliente y lo implementamos en nuestro propio clúster de Kubernetes. Ahora nuestra solución de alta carga se ha trasladado a la plataforma del cliente, para lo cual hemos configurado un proceso de implementación continua totalmente automático. Gracias a esto, aceleramos el tiempo de comercialización: la implementación de cambios en el entorno del producto.

En este artículo hablaremos de todas las etapas del proceso de Despliegue Continuo (CD) o entrega de actualizaciones a la plataforma del cliente:

  1. ¿Cómo comienza este proceso?
  2. sincronización con el repositorio Git del cliente,
  3. montaje de backend y frontend,
  4. implementación automática de aplicaciones en un entorno de prueba,
  5. implementación automática a Prod.

Compartiremos los detalles de configuración a lo largo del camino.

Nuestra implementación de Despliegue Continuo en la plataforma del cliente

1. Iniciar CD

La implementación continua comienza cuando el desarrollador envía cambios a la rama de lanzamiento de nuestro repositorio Git.

Nuestra aplicación se ejecuta en una arquitectura de microservicio y todos sus componentes se almacenan en un repositorio. Gracias a esto, se recopilan e instalan todos los microservicios, incluso si uno de ellos ha cambiado.

Organizamos el trabajo a través de un repositorio por varias razones:

  • Facilidad de desarrollo: la aplicación se desarrolla activamente, por lo que puede trabajar con todo el código a la vez.
  • Un único canal de CI/CD que garantiza que la aplicación como un único sistema pase todas las pruebas y se entregue al entorno de producción del cliente.
  • Eliminamos la confusión en las versiones: no tenemos que almacenar un mapa de versiones de microservicios ni describir su configuración para cada microservicio en scripts de Helm.

2. Sincronización con el repositorio Git del código fuente del cliente

Los cambios realizados se sincronizan automáticamente con el repositorio Git del cliente. Allí se configura el ensamblaje de la aplicación, que se inicia después de actualizar la rama y se implementa en la continuación. Ambos procesos se originan en su entorno desde un repositorio Git.

No podemos trabajar directamente con el repositorio del cliente porque necesitamos nuestros propios entornos para el desarrollo y las pruebas. Usamos nuestro repositorio Git para estos fines; está sincronizado con su repositorio Git. Tan pronto como un desarrollador publica cambios en la rama correspondiente de nuestro repositorio, GitLab envía inmediatamente estos cambios al cliente.

Nuestra implementación de Despliegue Continuo en la plataforma del cliente

Después de esto necesitas hacer el montaje. Consta de varias etapas: montaje backend y frontend, pruebas y entrega a producción.

3. Ensamblando el backend y el frontend

La construcción del backend y del frontend son dos tareas paralelas que se realizan en el sistema GitLab Runner. Su configuración de ensamblaje original se encuentra en el mismo repositorio.

Tutorial para escribir un script YAML para construir en GitLab.

GitLab Runner toma el código del repositorio requerido, lo ensambla con el comando de compilación de la aplicación Java y lo envía al registro de Docker. Aquí ensamblamos el backend y el frontend, obtenemos imágenes de Docker, que colocamos en un repositorio del lado del cliente. Para gestionar las imágenes de Docker utilizamos Complemento de Gradle.

Sincronizamos las versiones de nuestras imágenes con la versión de lanzamiento que se publicará en Docker. Para un funcionamiento fluido hemos realizado varios ajustes:

1. Los contenedores no se reconstruyen entre el entorno de prueba y el entorno de producción. Realizamos parametrizaciones para que un mismo contenedor pudiera funcionar con todas las configuraciones, variables de entorno y servicios tanto en el entorno de prueba como en producción sin necesidad de reconstruir.

2. Para actualizar una aplicación a través de Helm, debe especificar su versión. Creamos el backend, el frontend y actualizamos la aplicación: estas son tres tareas diferentes, por lo que es importante utilizar la misma versión de la aplicación en todas partes. Para esta tarea, utilizamos datos del historial de Git, ya que nuestra configuración y aplicaciones del clúster K8S están en el mismo repositorio de Git.

Obtenemos la versión de la aplicación a partir de los resultados de la ejecución del comando.
git describe --tags --abbrev=7.

4. Implementación automática de todos los cambios en el entorno de prueba (UAT)

El siguiente paso en este script de compilación es actualizar automáticamente el clúster K8S. Esto ocurre siempre que se haya creado toda la aplicación y todos los artefactos se hayan publicado en Docker Registry. Después de esto, comienza la actualización del entorno de prueba.

La actualización del clúster se inicia utilizando Actualización del timón. Si, como resultado, algo no salió según lo planeado, Helm revertirá automática e independientemente todos sus cambios. Su trabajo no necesita ser controlado.

Suministramos la configuración del clúster K8S junto con el ensamblaje. Por tanto, el siguiente paso es actualizarlo: configMaps, despliegues, servicios, secretos y cualquier otra configuración de K8S que hayamos cambiado.

Luego, Helm ejecuta una actualización RollOut de la aplicación en el entorno de prueba. Antes de que la aplicación se implemente en producción. Esto se hace para que los usuarios puedan probar manualmente las funciones comerciales que colocamos en el entorno de prueba.

5. Implementación automática de todos los cambios en Prod.

Para implementar una actualización en el entorno de producción, solo necesita hacer clic en un botón en GitLab y los contenedores se entregarán inmediatamente al entorno de producción.

La misma aplicación puede funcionar en diferentes entornos (prueba y producción) sin necesidad de reconstruirla. Usamos los mismos artefactos sin cambiar nada en la aplicación y configuramos los parámetros externamente.

La parametrización flexible de la configuración de la aplicación depende del entorno en el que se ejecutará la aplicación. Hemos movido todas las configuraciones del entorno externamente: todo está parametrizado a través de la configuración de K8S y los parámetros de Helm. Cuando Helm implementa un ensamblaje en el entorno de prueba, se le aplican la configuración de prueba y la configuración del producto se aplica al entorno de producción.

Lo más difícil fue parametrizar todos los servicios y variables utilizados que dependen del entorno y traducirlos en variables de entorno y descripciones-configuraciones de parámetros de entorno para Helm.

La configuración de la aplicación utiliza variables de entorno. Sus valores se establecen en contenedores utilizando el mapa de configuración K8S, que se crea mediante plantillas de Go. Por ejemplo, configurar una variable de entorno para el nombre de dominio se puede hacer así:

APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }}

.Valores.global.env – esta variable almacena el nombre del entorno (prod, etapa, UAT).
.Values.app.properties.app_external_domain – en esta variable configuramos el dominio deseado en el archivo .Values.yaml

Al actualizar una aplicación, Helm crea un archivo configmap.yaml a partir de plantillas y completa el valor APP_EXTERNAL_DOMAIN con el valor deseado según el entorno en el que comienza la actualización de la aplicación. Esta variable ya está configurada en el contenedor. Se puede acceder desde la aplicación, por lo que cada entorno de aplicación tendrá un valor diferente para esta variable.

Hace relativamente poco tiempo, apareció la compatibilidad con K8S en Spring Cloud, incluido el trabajo con configMaps: Nube de primavera Kubernetes. Si bien el proyecto se está desarrollando activamente y cambiando radicalmente, no podemos utilizarlo en producción. Pero monitoreamos activamente su condición y lo usamos en configuraciones DEV. Tan pronto como se estabilice, dejaremos de usar variables de entorno.

En total

Entonces, la implementación continua está configurada y funcionando. Todas las actualizaciones se realizan con solo presionar una tecla. La entrega de cambios al entorno del producto es automática. Y, lo que es más importante, las actualizaciones no detienen el sistema.

Nuestra implementación de Despliegue Continuo en la plataforma del cliente

Planes futuros: migración automática de bases de datos

Pensamos en actualizar la base de datos y la posibilidad de revertir estos cambios. Después de todo, se ejecutan dos versiones diferentes de la aplicación al mismo tiempo: la anterior se está ejecutando y la nueva está activa. Y apagaremos la antigua sólo cuando estemos seguros de que la nueva versión funciona. La migración de la base de datos debería permitirle trabajar con ambas versiones de la aplicación.

Por lo tanto, no podemos simplemente cambiar el nombre de la columna u otros datos. Pero podemos crear una nueva columna, copiar datos de la columna anterior en ella y escribir activadores que, al actualizar los datos, los copiarán y actualizarán simultáneamente en otra columna. Y después de la implementación exitosa de la nueva versión de la aplicación, después del período de soporte posterior al lanzamiento, podremos eliminar la columna anterior y el activador que ya no es necesario.

Si la nueva versión de la aplicación no funciona correctamente, podemos volver a la versión anterior, incluida la versión anterior de la base de datos. En resumen, nuestros cambios te permitirán trabajar simultáneamente con varias versiones de la aplicación.

Planeamos automatizar la migración de bases de datos a través del trabajo K8S, integrándolo en el proceso de CD. Y definitivamente compartiremos esta experiencia en Habré.

Fuente: habr.com

Añadir un comentario