Microservicios Versiones en sistemas de integración continua y despliegue Estudio de caso de CI / CD usando TFS

Problema


Para proyectos grandes y técnicamente complejos, en los que, por regla general, muchos equipos distribuidos trabajan simultáneamente, existe un problema bien conocido de desarrollo de software versionado, que diferentes compañías resuelven de manera diferente.

Actualmente, varios de nuestros clientes y socios entregan las últimas versiones (CI / CD) a Producción manualmente instalando las versiones más recientes / actuales de su software, habiéndolo probado previamente con el resto del entorno. Por ejemplo, al proporcionar compilaciones de aplicaciones iOS, Android, etc. si hablamos de software de cliente, o al actualizar imágenes de docker en un entorno de docker si estamos hablando de backend. Para proyectos grandes e importantes donde la decisión de lanzar una nueva versión en Producción cada vez es tomada por Project Manager, tal decisión está justificada y no es demasiado costosa, especialmente si los lanzamientos no se lanzan con frecuencia. Sin embargo, para el entorno de desarrollo de pruebas (entorno Dev / Stage), el uso de herramientas "manuales" conduce a la complejidad del proyecto, la posible interrupción de las impresiones para el Cliente, etc. Puede haber muchas razones para esto, incluidas inconsistencias en las versiones de varios contenedores en el software de middleware o la falta de un historial detallado de lanzamientos.

Teníamos que asegurarnos de esto personalmente y experimentar muchas dificultades en un proyecto grande, en el que se lanzaban diariamente entre 6 y 8 nuevas versiones de software en el backend y 2-3 versiones de software en la interfaz del sistema de CI, donde los ingenieros de prueba no podían hacer frente objetivamente a la carga y hubo una constante falta de comprensión sobre qué versión del software en el frontend / backend se considera actualmente estable.

Nuestra experiencia


Nuestra empresa utiliza varios sistemas CI / CD en su trabajo, cuya elección a menudo está determinada por los requisitos del Cliente. Por ejemplo, nuestros especialistas a menudo se encuentran con sistemas CI / CD como Jenkins, TeamCity, Travis CI, Circle CI, Gitlab CI, Atlassian Bamboo, donde a veces trabajamos completamente en la infraestructura del cliente. En consecuencia, con este enfoque, el problema con la solución de las versiones recae completamente en el Cliente.

Cuando desarrollamos soluciones para clientes, cuando tenemos la oportunidad de hacerlo en nuestra propia infraestructura, utilizamos la versión TFS 2018 como base para el sistema de Integración Continua / Entrega Continua. Esto nos permite resolver la tarea principal de crear un ciclo completo de desarrollo de software, a saber:

  • Establecer objetivos (problemas, errores, tareas) en función del enfoque para el desarrollo de software utilizado en el proyecto actual;
  • Almacenamiento del código fuente del proyecto;
  • Despliegue de la infraestructura de agentes de compilación para ensamblajes para diferentes sistemas operativos (Windows, Linux, MacOS);
  • Montaje de proyectos en modo "manual" y CI;
  • Despliegue de proyectos en modo "manual" y CD;
  • Proyectos de prueba;
  • Formación de datos sobre el tiempo empleado por los empleados en el proyecto y una serie de funciones adicionales que implementamos usando Extensiones TFS de nuestro propio diseño y agregando estadísticas a WIT (en esta forma, TFS reemplazó a nuestra empresa Redmine y simplificó la recopilación de estadísticas, informes, etc., en el contexto de los proyectos )

En este caso, sería lógico asignar la solución al problema de versiones a TFS, finalizando la funcionalidad de TFS para nuestras tareas y los deseos del Cliente. Como resultado, la tarea de construir un sistema de versiones para proyectos de arquitectura de microservicios se resolvió mediante herramientas TFS personalizando varios scripts de compilación y organizando entornos de prueba / lanzamiento.

La solución: usar TFS y herramientas de terceros


Por lo tanto, necesitamos un sistema de versiones para proyectos de arquitectura de microservicios para organizar entornos de prueba y lanzamientos.

Como datos iniciales tenemos:

  • Orquestación: utilizamos enjambre Docker principalmente para reducir el uso de otras herramientas de terceros. Al mismo tiempo, hay convertidores para convertir configuraciones, por ejemplo, la utilidad Kompose , que le permitirá usar Kubernetes si es necesario.
  • Agentes de compilación: VM basada en servidores Linux.
  • Repositorio de origen: Git basado en TFS.
  • Almacenamiento de imágenes: registro de Docker en VM.

A la pregunta del nombre de las compilaciones


  • Será lógico utilizar los estándares de nomenclatura existentes, por ejemplo, como la Especificación de versiones semánticas .
  • Seguimos este nombre cuando iniciamos manualmente el proceso de compilación de la versión de lanzamiento, porque de lo contrario no podrá obtener el nombre correcto automáticamente (a menos que lo ingrese en el código manualmente, lo que nuevamente tiene poca relación con la ideología de CI).
  • En el modo CI para versiones de software de "depuración", usamos los siguientes nombres en diferentes proyectos:

    1. Extensiones TFS incorporadas
    2. Numeración basada en la fecha actual y el número de compilación de ese día;
    3. El número de la confirmación que inició la compilación.

Una solución específica, por ejemplo, se puede ver en base a un ejemplo del servicio Calculator , realizado en Javascript, y varios proyectos disponibles públicamente.

Algoritmo de decisión


1. En TFS2018, cree un proyecto llamado SibEDGE Semver e importe el repositorio en el repositorio local

imagen
Figura 1 - Proyecto SibEDGE Semver en el repositorio en TFS 2018

2. Cree un archivo Dockerfile con la descripción del ensamblado node.js para nuestras necesidades ( enlace ).

FROM node:7 WORKDIR /usr/src/app COPY package.json app.js LICENSE /usr/src/app/ COPY lib /usr/src/app/lib/ LABEL license MIT COPY tests tests ENV NODE_ENV dev RUN npm config set strict-ssl false RUN npm update && \ npm install -g mocha CMD ["mocha", "tests/test.js", "--reporter", "spec"] 

Script 1 - Dockerfile para construir una compilación


3. En el banco de pruebas (con docker instalado), donde planeamos implementar nuestro entorno, cree un clúster de enjambre. En nuestro caso, consistirá en un servidor.

 $ docker swarm init 

4. Cree un archivo yml con una descripción de microservicios para nuestras necesidades ( enlace ).
Tenga en cuenta que vm-docker-registry.development.com:5000 es el repositorio interno para este proyecto que preparamos de antemano. Para que el banco de pruebas pueda usar este repositorio, es necesario registrar el certificado SSL en el banco en la carpeta /etc/docker/certs.d/ <nombre del repositorio> /ca.crt

 version: '3.6' services: #--- # Portainer for manage Docker #--- portainer: image: portainer/portainer:1.15.3 command: --templates http://templates/templates.json -d /data -H unix:///var/run/docker.sock networks: - semver-network ports: - 9000:9000 volumes: - /var/run/docker.sock:/var/run/docker.sock #--- #----Service Calculator Test# #--- semver-calc: image: vm-docker-registry.development.com:5000/calculator:latest networks: - semver-network #--- #----Pminder - Nginx# #--- nginx: image: nginx:1.9.6 depends_on: - mysql ports: - "8888:80" - "6443:443" networks: - semver-network # #----------------------------- # START NoSQL - Redis. #--- redis: image: redis:4.0 networks: - semver-network ports: - "8379:6379" # # END NoSQL - Redis. #--- #----Pminder - DB# #--- mysql: image: mysql:5.7 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: 'ODdsX0xcN5A9a6q' MYSQL_DATABASE: 'semver' MYSQL_USER: 'user' MYSQL_PASSWORD: 'uXcgTQS8XUm1RzR' networks: - semver-network #--- #----PhpMyAdmin # #--- phpmyadmin: image: phpmyadmin/phpmyadmin depends_on: - mysql environment: PMA_HOST: 'mysql' PMA_USER: 'user' PMA_PASSWORD: 'uXcgTQS8XUm1RzR' ports: - "8500:80" - "8600:9000" networks: - semver-network #--- networks: semver-network: 

El script 2 es el contenido del archivo semver.yml, que es el archivo de proyecto docker-compose.


5. Cree una descripción de compilación en TFS2018 (Definición de compilación).

6. La primera acción de nuestro script es construir la imagen del contenedor acoplable:

imagen
Figura 2: creación de una imagen para nuestra compilación en TFS 2018

7. Envíe la imagen del contenedor acoplable creada en la máquina de compilación al repositorio interno para este proyecto:

imagen
Figura 3: Guardar la imagen acoplable para nuestro ensamblaje en el repositorio TFS 2018

8. Para todo el entorno en el banco de pruebas en el archivo de descripción de microservicios, cambie el nombre de la imagen a uno nuevo:

imagen
Figura 4: Reemplazar el nombre de la imagen en el script de compilación para nuestra compilación en TFS 2018

9. En el banco de pruebas, copie la imagen del contenedor docker creado desde el repositorio interno y actualice el servicio en el enjambre docker:

imagen
Figura 5: Implementación del contenedor acoplable con el script de compilación para nuestra compilación a partir de la imagen en TFS 2018

Como resultado, cuando salimos al repositorio TFS, tenemos un archivo yml con versiones de lanzamiento de imágenes de acoplador, que a su vez tiene un nombre de lanzamiento para todo el proyecto.

10. Iremos al banco de pruebas y verificaremos los servicios y nos aseguraremos de que el servicio Calculadora se haya actualizado y use la nueva versión del ensamblaje.

 $ docker service ls 


imagen
Figura 6: Actualización del servicio Calculadora y verificación de su versión actual en nuestro banco de pruebas

Por lo tanto, en nuestro almacenamiento de imágenes de registro de Docker, tenemos un conjunto de imágenes de varias versiones de microservicios (en este caso particular, se cambia la versión de un solo microservicio). Al iniciar un proceso de implementación por separado (a través de un script que cambia el archivo de descripción yml), en cualquier momento puede obtener el entorno que necesita para probar en un banco de pruebas y transferir esta configuración a la división de control de calidad. Después de las pruebas (regresión, carga, etc.), obtenemos información de que el microservicio de una determinada versión funciona de manera estable en un banco de pruebas con las versiones de lanzamiento de otros microservicios de tales y tales versiones, y la decisión final ya está tomada sobre si actualizar o no soporte de lanzamiento a la nueva versión.

Resumen: lo que tienes en la salida


Gracias a la implementación de versiones en proyectos con arquitectura de microservicio, se logró el siguiente resultado:

  • la cantidad de caos en las versiones ha disminuido;
  • la velocidad de despliegue de un nuevo entorno en proyectos ha aumentado;
  • la calidad de los ensambles ha mejorado y el nivel de errores en ellos ha disminuido;
  • mayor transparencia de desarrollo para los Gerentes de Proyecto y el Cliente;
  • la interacción entre departamentos ha mejorado;
  • Hay nuevas direcciones en el trabajo de DevOps.

PD: Gracias a mi colega Kirill B. por ayudarme a escribir este artículo.

Source: https://habr.com/ru/post/437992/


All Articles