Menu Close

CI/CD Basic Example – Amazon (AWS)

Ejemplo básico de CI/CD:

Cuando hablamos de CI/CD (Continuous Integration/Continuous Delivery) muchas veces los conceptos se consideran más ‘filosóficos’, olvidándose de cómo ponerlos en práctica. En este blog precisamente queremos presentarles un enfoque de cómo poner en práctica un flujo de CI/CD básico.

Es muy importante comprender el flujo básico de CI/CD para un proyecto de Desarrollo de Software, porque al principio puede parecer confuso saber qué paso lleva al siguiente, qué se debe hacer en cada etapa o qué elemento es responsable de que tarea

Una vez entendido este flujo, el segundo punto más complejo de entender podría ser la configuración de los propios Sistemas de Integración Continua (qué herramientas se deben utilizar, qué plugins se deben instalar, cómo configurar los permisos, cómo generar los contenedores, etc)

Aunque hay muchas formas de abordar una implementación de CI/CD, vamos a tomar un ejemplo básico representado de la siguiente manera:

(Flujo básico para un proyecto de CI/CD de back-end)

Este flujo comienza cuando un desarrollador envía el código fuente ( ‘push’ ) a un repositorio, que puede ser GitHub. Cuando GitHub detecta una inserción, envía una notificación a un Sistema de integración continua (por ejemplo, Jenkins). Una vez que Jenkins recibe la información de GitHub, la construye ( ‘build’ ) a través de una configuración previamente establecida (trabajos de Jenkins):

  • Compilacion
  • Pruebas unitarias
  • Pruebas de integración

Entre otros, sobre el proyecto. Esta compilación depende del tipo de proyecto: podemos tener proyectos Front-End o Back-End. Para este ejemplo vamos a trabajar con Java.

Si la compilación se realizó correctamente sin ningún error, Jenkins genera un contenedor y este contenedor se puede cargar en Amazon ECR. Por el contrario, si hay algún error, el proceso no llegará hasta ECR.

Depende del desarrollador con qué frecuencia enviar al repositorio (desde su IDE).

Para GitHub, es necesario configurar ‘webhooks’ , que representan el ‘punto de información’ para notificar a un servicio externo cada vez que hay un impulso:

En la imagen anterior, la URL corresponde a un webhook asociado a Jenkins. Jenkins, a su vez, permite configurar trabajos asociados a este webhook:

Un trabajo (en Jenkins) es un proyecto que se puede configurar para especificar cómo compilar, construir y distribuir un sistema:


El
‘disparador’ asociado a este Jexz

Permite especificar el repositorio y la ‘sucursal’ asociada al proyecto:

En este caso, la compilación pasa por un archivo ( Jenkinsfile ):

En el archivo Jenkinsfile podríamos configurar las diferentes etapas por las que puede pasar una aplicación:

En la imagen anterior, el archivo Jenkinsfile especifica diferentes etapas de construcción. Cada etapa debe ejecutarse con éxito antes de que comience la siguiente.

La primera etapa es el ‘checkout’ , en este Jenkins recopila todas las fuentes modificadas por el repositorio una vez que GitHub informa un nuevo   ‘Push’ .

En la segunda etapa ( ‘compilar’ ) se construye el proyecto. Para este ejemplo, estamos construyendo un proyecto Java a través de Maven, ejecutando este comando:

mvn -U compilación limpia


Con este comando, a partir del código fuente, generamos los archivos .class Java (que luego serán interpretados por la Máquina Virtual Java).

Para la tercera etapa, las ‘Pruebas Unitarias’ , el comando a ejecutar es el siguiente:

prueba mvn


Una vez que se han completado todas las pruebas, el proyecto se
’empaqueta’ con el comando:

paquete mvn


Crear un .jar, que podría considerarse como la
‘entrega’ final que contiene todos los .class necesarios para el proyecto Java:

Finalmente realizamos pruebas de integración:

mvn verificar


Un ejemplo de una prueba de integración podría ser hacer una solicitud a una API REST y verificar que la respuesta sea siempre la esperada (llamar a la API proporcionando un argumento y comparar la respuesta). Para este punto se utiliza un contenedor Docker temporal, que dura solo durante la ejecución de las pruebas de integración.

Cuando las pruebas de integración se completan con éxito, se realiza la implementación final. El ‘deploy’ consiste en tomar la imagen recién generada y llevarla al repositorio de imágenes (en este caso Amazon ECR ). En el ejemplo anterior, este despliegue se está haciendo en un entorno UAT, el último paso antes de entrar en producción.

Cada compilación se rastrea en Jenkins:

La ‘ruta’ ( pipeline ) que sigue el proyecto en Jenkins también se puede visualizar gráficamente en la siguiente pantalla:

En la imagen anterior podemos observar como es un flujo (en Jenkins):


En caso de error, Jenkins muestra la etapa exacta en la que ocurrió. Por ejemplo en la
compilación #39 el error ocurrió en las Pruebas de Integración. En las otras compilaciones no hubo errores:


Es posible obtener más información sobre el error:


Cuando una etapa falla, las siguientes (si están disponibles) no se ejecutarán:

En cada etapa de la construcción podemos ver su duración (en milisegundos o segundos). Jenkins también muestra la duración promedio de cada etapa en todo el proyecto.

Una vez que Jenkins envía la nueva imagen a Amazon ECR, Jenkins reinicia el servicio para que ECS pueda detectar la nueva imagen (las instancias de contenedores actualmente disponibles comienzan a terminar y las nuevas instancias comienzan a lanzarse).

Las imágenes que se envían a Amazon ECR se almacenan en repositorios:

Cada repositorio puede contener una o más imágenes:

Cada vez que se solicita un reinicio de Jenkins, lo que realmente se reinicia es un servicio asociado a un clúster de AWS ECS:

En la imagen anterior hay varios servicios dentro del clúster. Cada uno de esos servicios (para este ejemplo) tiene una instancia en ejecución porque han sido configurados para esa cantidad de instancias deseadas.

Una vez reiniciado el servicio, se puede acceder a las diferentes opciones que pueda tener el software desarrollado. Por ejemplo, si el proyecto es una API REST, podría comenzar a realizar solicitudes a esta API.

Es importante resaltar que el único paso ‘humano’ se realizó al principio, cuando el desarrollador envió su código ( ‘push’ ) al repositorio de archivos, y este único evento desencadenó el resto del proceso automatizado. La única preocupación era hacer bien su código, ejecutar las pruebas unitarias (asegúrese de que no fallaran, estas pruebas son importantes para evitar la ejecución innecesaria del proceso automatizado) y que su código compilara correctamente. A partir de ahí, el desarrollador puede “olvidarse” de lo que está sucediendo.

Jenkins permite configurar la notificación por correo electrónico para algunos eventos. Por ejemplo, si la construcción falla, el Equipo de Desarrolladores puede informar a alguien responsable de esta etapa. Esto permite una retroalimentación constante al Equipo para que puedan realizar las comprobaciones correspondientes.

Una vez ejecutadas todas las etapas, el mismo Desarrollador podrá consultar la última versión de su desarrollo actual. Por ejemplo, si se trata de un nuevo ícono en el sitio web, este podría verificarse al final de todo el proceso (existen herramientas automatizadas para verificar desarrollos ‘Front-End’ ).

En el caso de un desarrollo ‘Front-End’ , Jenkins podría enviar (cuando todas las etapas se completen con éxito) los archivos actualizados a un Repositorio de archivos (como Amazon S3):

(Flujo básico de CI/CD para un proyecto ‘Front-End’)

 

Write us!

Posted in »Blog English

Close Bitnami banner
Bitnami