Despliegues automáticos usando GitLab CI/CD

Despliegues automáticos usando GitLab CI/CD

Contenidos ocultar

Introducción a GitLab CI/CD

GitLab CI/CD es una herramienta integrada en GitLab que permite automatizar las diferentes etapas del ciclo de vida del desarrollo de software, desde la integración continua (CI) hasta la entrega continua (CD) y el despliegue continuo (CD). Esto significa que puedes configurar GitLab para que automáticamente construya, pruebe y despliegue tu código cada vez que hagas un cambio en tu repositorio.

Integración Continua (CI): La CI se centra en la integración frecuente del código de diferentes desarrolladores en un repositorio compartido. Cada integración desencadena un proceso automatizado que verifica el código (por ejemplo, mediante pruebas unitarias y de integración) para detectar errores lo antes posible. Esto ayuda a evitar los problemas de integración que pueden surgir cuando se trabaja en ramas separadas durante mucho tiempo.

Entrega Continua (CD): La entrega continua amplía la CI al asegurar que el código que ha pasado las pruebas esté listo para ser liberado en un entorno de producción. Aunque el código está listo para ser desplegado, el despliegue real a producción puede requerir una aprobación manual.

Despliegue Continuo (CD): El despliegue continuo va un paso más allá que la entrega continua. Con el despliegue continuo, cada cambio que pasa todas las etapas del pipeline (incluyendo las pruebas) se despliega automáticamente en producción, sin intervención manual.

Beneficios de usar GitLab CI/CD:

  • Automatización: Reduce el trabajo manual y repetitivo, liberando a los desarrolladores para que se centren en tareas más importantes.
  • Detección temprana de errores: Las pruebas automatizadas ayudan a identificar los errores en las primeras etapas del desarrollo, lo que reduce el coste de corregirlos.
  • Entregas más rápidas y frecuentes: La automatización del proceso de despliegue permite lanzar nuevas versiones de software con mayor rapidez y frecuencia.
  • Mayor calidad del software: La integración y las pruebas continuas garantizan que el código que se despliega sea de alta calidad.
  • Mejor colaboración: GitLab CI/CD facilita la colaboración entre los miembros del equipo al proporcionar una visión clara del estado del proyecto.
  • Integrado en GitLab: Al estar integrado en GitLab, no es necesario utilizar herramientas externas, lo que simplifica la configuración y la gestión.
  • Flexibilidad: GitLab CI/CD es altamente configurable y se puede adaptar a las necesidades específicas de cada proyecto. Se puede usar con cualquier lenguaje de programación.

En resumen, GitLab CI/CD es una poderosa herramienta que ayuda a los equipos de desarrollo a automatizar sus flujos de trabajo, mejorar la calidad del software y entregar valor a los usuarios de forma más rápida y eficiente.

Configuración Inicial del Entorno GitLab

Antes de poder utilizar GitLab CI/CD, necesitas configurar tu entorno GitLab. Esto implica crear un proyecto en GitLab y configurar los runners, que son los agentes que ejecutan los trabajos definidos en tu pipeline CI/CD.

Creación de un Proyecto en GitLab

Si aún no tienes un proyecto en GitLab, sigue estos pasos para crear uno:

  1. Inicia sesión en GitLab: Accede a tu instancia de GitLab (ya sea GitLab.com o una instancia auto-gestionada).
  2. Crea un nuevo proyecto:
    • Haz clic en el botón "New project" o "+".
    • Selecciona la opción "Create blank project".
    • Dale un nombre a tu proyecto (Project name). Este nombre también se usará para generar la URL del proyecto.
    • (Opcional) Añade una descripción al proyecto (Project description).
    • Selecciona el nivel de visibilidad (Visibility Level):
      • Private: Solo los miembros del proyecto pueden acceder.
      • Internal: Cualquier usuario que haya iniciado sesión en GitLab puede acceder.
      • Public: Cualquiera puede acceder, sin necesidad de iniciar sesión.
    • (Opcional) Marca la casilla "Initialize repository with a README" si quieres que GitLab cree un archivo README.md inicial en tu repositorio. Esto es recomendable para la mayoría de los proyectos.
    • Haz clic en el botón "Create project".

Una vez creado el proyecto, tendrás un repositorio Git vacío listo para que empieces a añadir tu código.

Configuración de Runners

Los Runners son los agentes que ejecutan los trabajos definidos en tu archivo

.gitlab-ci.yml
. Son esenciales para el funcionamiento de GitLab CI/CD. GitLab ofrece diferentes tipos de runners, y puedes elegir el que mejor se adapte a tus necesidades.

Tipos de Runners (Shared, Specific, Group)

  • Shared Runners (Corredores Compartidos):
    • Disponibles para todos los proyectos en una instancia de GitLab.
    • Gestionados por los administradores de GitLab (en GitLab.com) o por los administradores de tu instancia auto-gestionada.
    • Ideales para trabajos que no requieren configuraciones especiales o recursos dedicados.
    • Son una buena opción para empezar, ya que no requieren configuración adicional.
    • En GitLab.com, los shared runners tienen limitaciones de tiempo de ejecución por mes, según el plan de tu cuenta.
  • Specific Runners (Corredores Específicos):
    • Vinculados a un proyecto específico.
    • Solo ejecutan trabajos para ese proyecto.
    • Ideales para trabajos que requieren configuraciones especiales, dependencias específicas o acceso a recursos privados.
    • Ofrecen mayor control y aislamiento.
    • Debes instalarlos y registrarlos tú mismo.
  • Group Runners (Corredores de Grupo):
    • Vinculados a un grupo de GitLab.
    • Disponibles para todos los proyectos dentro de ese grupo y sus subgrupos.
    • Útiles para organizaciones que tienen varios proyectos relacionados que comparten requisitos similares.
    • También debes instalarlos y registrarlos tú mismo.

Instalación y Registro de un Runner

Para instalar y registrar un runner específico o de grupo, sigue estos pasos (los ejemplos son para un runner específico en Linux, pero el proceso general es similar para otros sistemas operativos y tipos de runners):

  1. Instala el GitLab Runner:
    • Descarga el paquete binario para tu sistema operativo desde la página de descargas de GitLab Runner:
      https://docs.gitlab.com/runner/install/ (Consulta la documentación oficial para instrucciones detalladas para tu sistema operativo específico).
    • Ejemplo (Linux - usando el repositorio de paquetes de GitLab):
      
      curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
      sudo apt-get install gitlab-runner
                     
  2. Registra el Runner:
    • Ve a la configuración de tu proyecto en GitLab: Settings > CI/CD > Runners.
    • Expande la sección "Set up a specific Runner manually". Ahí encontrarás la URL de GitLab y el token de registro. Necesitarás esta información.
    • Ejecuta el comando de registro en la máquina donde instalaste el runner (reemplaza
      <URL_de_GitLab>
      y
      <token_de_registro>
      con los valores reales):
      
      sudo gitlab-runner register --url <URL_de_GitLab> --registration-token <token_de_registro>
                      
    • El comando te pedirá información adicional:
      • Descripción del runner: Una descripción para identificar el runner en GitLab.
      • Tags: Etiquetas para asociar el runner con trabajos específicos (opcional, pero muy útil). Por ejemplo,
        docker
        ,
        linux
        ,
        deploy
        , etc.
      • Executor: El tipo de ejecutor que utilizará el runner (
        shell
        ,
        docker
        ,
        kubernetes
        , etc.). Elige el que mejor se adapte a tus necesidades. El más común y versatil es
        docker
        .
      • Si eliges
        docker
        , te pedirá la imagen de Docker por defecto a utilizar.
  3. Verifica el Runner:
    • Una vez registrado, el runner debería aparecer en la sección "Runners" de la configuración de CI/CD de tu proyecto en GitLab.
    • El estado del runner debería ser "Online" (verde) si se ha registrado correctamente.
  4. (Opcional) Configuración adicional:
    • Puedes configurar opciones avanzadas del runner editando el archivo
      config.toml
      (normalmente ubicado en
      /etc/gitlab-runner/config.toml
      en Linux). Consulta la documentación de GitLab Runner para más detalles.

Con estos pasos, habrás configurado tu entorno GitLab para empezar a utilizar CI/CD. El siguiente paso es crear el archivo

.gitlab-ci.yml
en tu repositorio para definir tu pipeline.

Creación del Archivo .gitlab-ci.yml

El archivo

.gitlab-ci.yml
es el corazón de GitLab CI/CD. Es un archivo en formato YAML que se coloca en la raíz del repositorio Git y define la estructura y configuración de tu pipeline. En este archivo, especificas las etapas (stages), los trabajos (jobs), las dependencias, y las condiciones de ejecución de tu flujo de trabajo de CI/CD.

Sintaxis Básica y Estructura

El archivo

.gitlab-ci.yml
sigue una sintaxis YAML estricta. Algunas reglas básicas de YAML que debes tener en cuenta:
  • Indentación: La indentación es crucial en YAML. Utiliza espacios (no tabulaciones) para la indentación. El número de espacios no importa tanto, pero la consistencia es clave. Normalmente se usan 2 o 4 espacios.
  • Comentarios: Los comentarios comienzan con el símbolo
    #
    .
  • Claves y valores: Las configuraciones se definen como pares clave-valor, separados por dos puntos (
    :
    ). Por ejemplo:
    image: node:latest
    .
  • Listas: Las listas se definen usando guiones (
    -
    ) seguidos de un espacio.
  • Diccionarios: Los diccionarios (objetos) son conjuntos de pares clave-valor anidados.

Un archivo

.gitlab-ci.yml
básico tiene la siguiente estructura:

# Define las etapas globales del pipeline.
stages:
  - build
  - test
  - deploy

# Define un trabajo llamado 'build_job'.
build_job:
  stage: build  # Indica que este trabajo se ejecuta en la etapa 'build'.
  script:
    - echo "Compilando el código..."
    - # ... comandos para compilar ...

# Define un trabajo llamado 'test_job'.
test_job:
  stage: test  # Indica que este trabajo se ejecuta en la etapa 'test'.
  script:
    - echo "Ejecutando pruebas..."
    - # ... comandos para ejecutar pruebas ...

# Define un trabajo llamado 'deploy_job'.
deploy_job:
  stage: deploy  # Indica que este trabajo se ejecuta en la etapa 'deploy'.
  script:
    - echo "Desplegando la aplicación..."
    - # ... comandos para desplegar ...
  only:
      - main

Definición de Stages (Etapas)

Las etapas (

stages
) definen las diferentes fases del pipeline. Los trabajos dentro de la misma etapa se ejecutan en paralelo (si hay suficientes runners disponibles), mientras que los trabajos en etapas posteriores se ejecutan secuencialmente, solo si los trabajos de la etapa anterior han tenido éxito. La palabra clave
stages
se usa al inicio, antes de definir los Jobs.

stages:
  - build  # Etapa de construcción.
  - test   # Etapa de pruebas.
  - deploy # Etapa de despliegue.

Si no defines

stages
, GitLab CI/CD utiliza un conjunto predeterminado de etapas:
build
,
test
y
deploy
. Sin embargo, es una buena práctica definir explícitamente las etapas que necesitas.

Definición de Jobs (Tareas)

Los trabajos (

jobs
) son las unidades básicas de ejecución en un pipeline. Cada trabajo se define como un bloque en el archivo
.gitlab-ci.yml
y contiene una serie de instrucciones que se ejecutan en un runner.

Un trabajo debe tener al menos una clave

stage
, que indica la etapa a la que pertenece, y una clave
script
, que contiene los comandos a ejecutar.

Uso de
script

La clave

script
es obligatoria y contiene una lista de comandos que se ejecutarán en el runner. Estos comandos se ejecutan en un shell, y puedes usar cualquier comando válido en el entorno del runner.

job_name:
  stage: build
  script:
    - echo "Hola, mundo!"
    - mkdir build
    - cp source.txt build/

Uso de
image

La clave

image
especifica la imagen de Docker que se utilizará para ejecutar el trabajo. Esto te permite ejecutar tus trabajos en un entorno aislado y consistente, con todas las dependencias necesarias.

job_name:
  stage: test
  image: node:16 # Usa la imagen de Node.js versión 16.
  script:
    - npm install
    - npm test

Si no especificas una imagen y utilizas un runner configurado con el executor `docker`, se usará la imagen por defecto que especificaste durante el registro del runner.

Uso de
variables

La clave

variables
te permite definir variables de entorno que estarán disponibles para el trabajo. Puedes definir variables a nivel global (para todo el pipeline) o a nivel de trabajo.

variables:
  GLOBAL_VARIABLE: "Valor global"

job_name:
  stage: build
  variables:
    JOB_VARIABLE: "Valor local"
  script:
    - echo "Variable global: $GLOBAL_VARIABLE"
    - echo "Variable local: $JOB_VARIABLE"

Uso de
only
y
except
(Control de Ejecución)

Las claves

only
y
except
te permiten controlar cuándo se ejecutan los trabajos, basándose en condiciones como la rama (branch), las etiquetas (tags) o los eventos de pipeline.
  • only
    : Especifica las condiciones en las que el trabajo *sí* se ejecutará.
  • except
    : Especifica las condiciones en las que el trabajo *no* se ejecutará.

deploy_job:
  stage: deploy
  script:
    - echo "Desplegando..."
  only:
    - main  # Solo se ejecuta en la rama 'main'.
    - tags  # Solo se ejecuta cuando se crea una etiqueta (tag).

test_job:
    stage: test
    script:
        - echo "testing"
    except:
        - main

Uso de
tags

La clave

tags
se utiliza para especificar qué runner debe ejecutar el trabajo. Cuando registras un runner, puedes asignarle etiquetas (tags). Luego, en el archivo
.gitlab-ci.yml
, puedes usar la clave
tags
para indicar que un trabajo solo debe ejecutarse en un runner que tenga esas etiquetas.

build_job:
  stage: build
  tags:
    - docker  # Este trabajo solo se ejecutará en runners con la etiqueta 'docker'.
  script:
    - echo "Construyendo..."

Uso de
artifacts

La clave

artifacts
se utiliza para especificar archivos o directorios que se deben guardar como artefactos del trabajo. Los artefactos se pueden descargar desde la interfaz de GitLab o utilizarse en trabajos posteriores del pipeline.

build_job:
  stage: build
  script:
    - echo "building"
    - mkdir build
    - echo "my artifact" > build/my_artifact.txt
  artifacts:
    paths:
      - build/  # Guarda el directorio 'build' como artefacto.
    expire_in: 1 week #tiempo que se guardarán

Uso de `dependencies`

Permite que un Job pueda hacer uso de los artifacts generados por Jobs de stages anteriores. Si el stage anterior no tiene artefactos, no fallará el Job actual, a menos que el Job del que depende no haya sido ejecutado.

stages:
    - build
    - test

build_job:
    stage: build
    script:
        - echo "building"
        - mkdir build
        - echo "my artifact" > build/my_artifact.txt
    artifacts:
        paths:
            - build/

test_job:
    stage: test
    dependencies:
        - build_job
    script:
        - cat build/my_artifact.txt

Este es un resumen de los elementos más importantes del archivo

.gitlab-ci.yml
. Con estos conceptos, puedes empezar a crear tus propios pipelines de CI/CD en GitLab.

Ejemplos de Pipelines CI/CD Comunes

Para ilustrar mejor cómo funciona GitLab CI/CD, veamos algunos ejemplos de pipelines comunes para diferentes tipos de aplicaciones.

Pipeline para una Aplicación Web (Despliegue en un Servidor)

Este ejemplo muestra un pipeline simple para una aplicación web que se construye, se prueba y se despliega en un servidor remoto (asumiendo que tienes acceso SSH al servidor).


stages:
  - build
  - test
  - deploy

build_job:
  stage: build
  image: node:16 # Usamos una imagen de Node.js.  Cambia esto si usas otro lenguaje/entorno.
  script:
    - npm install  # Instala las dependencias.
    - npm run build # Construye la aplicación (asumiendo que tienes un script "build" en tu package.json).
  artifacts:
    paths:
      - dist/ # Guarda la carpeta 'dist' (o la carpeta donde se genera tu build) como artefacto.

test_job:
  stage: test
  image: node:16
  script:
    - npm install
    - npm test # Ejecuta las pruebas (asumiendo que tienes un script "test" en tu package.json).
  dependencies:
      - build_job

deploy_job:
  stage: deploy
  image: ruby:latest # Usamos una imagen de Ruby para tener acceso a herramientas como 'ssh' y 'scp'.
  script:
    - apt-get update -yq  #Actualizamos repositorios
    - apt-get install -yq openssh-client # Instalamos el cliente SSH.
    - mkdir -p ~/.ssh  #Crea carpeta ssh
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa # Guarda la clave privada SSH en un archivo (la variable $SSH_PRIVATE_KEY debe estar definida en la configuración de CI/CD de GitLab).
    - chmod 600 ~/.ssh/id_rsa  # Establece los permisos correctos para la clave SSH.
    - ssh-keyscan $SERVER_IP >> ~/.ssh/known_hosts #Agrega la ip a host conocidos.
    - scp -r dist/* $SERVER_USER@$SERVER_IP:$SERVER_PATH # Copia los archivos de la carpeta 'dist' al servidor (las variables $SERVER_USER, $SERVER_IP y $SERVER_PATH deben estar definidas en la configuración de CI/CD de GitLab).
    - ssh $SERVER_USER@$SERVER_IP "cd $SERVER_PATH && echo 'Despliegue completado'" # Ejecuta un comando en el servidor para confirmar el despliegue.
  only:
    - main # Solo despliega cuando se hace un push a la rama 'main'.
  environment:
      name: production
      url: http://$SERVER_IP

Explicación:

  • Variables de entorno: Este ejemplo utiliza variables de entorno (
    $SSH_PRIVATE_KEY
    ,
    $SERVER_USER
    ,
    $SERVER_IP
    ,
    $SERVER_PATH
    ) para almacenar información sensible y configurable. Debes definir estas variables en la configuración de CI/CD de tu proyecto en GitLab (Settings > CI/CD > Variables). La variable
    SSH_PRIVATE_KEY
    debe contener tu clave privada SSH para acceder al servidor.
  • `environment` Se usa esta key para indicar que se está haciendo un despliegue a un entorno determinado, en este caso, `production`. Además se puede indicar una url para que aparezca en el dashboard de GitLab.
  • Seguridad de la clave SSH: Es crucial que protejas tu clave privada SSH. No la guardes directamente en el repositorio. Utiliza las variables de entorno de GitLab CI/CD, que están encriptadas.
  • Adaptación: Adapta este ejemplo a tu aplicación específica. Cambia los comandos, las rutas, los nombres de las carpetas y las imágenes de Docker según sea necesario.

Pipeline para una Aplicación de Contenedores (Docker)

Este ejemplo muestra un pipeline para una aplicación que se empaqueta en una imagen de Docker, se sube a un registro de contenedores (Docker Hub en este caso, pero podría ser GitLab Container Registry u otro) y se despliega en un orquestador de contenedores (Kubernetes en este caso, pero podría ser Docker Swarm u otro).


stages:
  - build
  - test
  - build_image
  - deploy

variables:
  # Variables globales para Docker Hub (también podrían definirse en la configuración de CI/CD de GitLab).
  DOCKER_HUB_USER: mydockerhubuser
  DOCKER_HUB_REPO: mydockerhubuser/my-app
  #tag para la imagen docker
  IMAGE_TAG: $CI_COMMIT_SHORT_SHA

build_job:
    stage: build
    image: node:16
    script:
        - npm install
        - npm run build
    artifacts:
        paths:
          - dist/

test_job:
    stage: test
    image: node:16
    script:
        - npm install
        - npm test
    dependencies:
      - build_job

build_image:
  stage: build_image
  image: docker:latest  # Usamos la imagen oficial de Docker.
  services:
    - docker:dind  # Usamos el servicio "Docker-in-Docker" para poder construir imágenes de Docker dentro del trabajo.
  script:
    - docker login -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASSWORD # Inicia sesión en Docker Hub (la variable $DOCKER_HUB_PASSWORD debe estar definida en la configuración de CI/CD de GitLab).
    - docker build -t $DOCKER_HUB_REPO:$IMAGE_TAG . # Construye la imagen de Docker.  El punto (.) indica que el Dockerfile está en la raíz del repositorio.
    - docker push $DOCKER_HUB_REPO:$IMAGE_TAG # Sube la imagen a Docker Hub.

deploy_k8s:
  stage: deploy
  image: google/cloud-sdk:latest #Usamos una imagen con las herramientas de google cloud, ya que usaremos GKE.
  script:
    - echo "$GCLOUD_SERVICE_KEY" > gcloud-service-key.json # Guarda la clave de servicio de Google Cloud en un archivo (la variable $GCLOUD_SERVICE_KEY debe estar definida en la configuración de CI/CD de GitLab).
    - gcloud auth activate-service-account --key-file gcloud-service-key.json # Autentica con la clave de servicio.
    - gcloud config set project $GCLOUD_PROJECT # Establece el proyecto de Google Cloud (la variable $GCLOUD_PROJECT debe estar definida en la configuración de CI/CD de GitLab).
    - gcloud config set compute/zone $GCLOUD_ZONE # Establece la zona de Google Cloud (la variable $GCLOUD_ZONE debe estar definida en la configuración de CI/CD de GitLab).
    - gcloud container clusters get-credentials $GCLOUD_CLUSTER_NAME # Obtiene las credenciales del clúster de Kubernetes (la variable $GCLOUD_CLUSTER_NAME debe estar definida en la configuración de CI/CD de GitLab).
    - kubectl set image deployment/my-app my-app=$DOCKER_HUB_REPO:$IMAGE_TAG # Actualiza la imagen del deployment en Kubernetes.  Asume que ya tienes un deployment llamado 'my-app' en tu clúster.
  only:
    - main
  environment:
      name: production
      url: http://$GCLOUD_CLUSTER_NAME

Explicación:

  • Docker-in-Docker (dind): El servicio
    docker:dind
    permite construir imágenes de Docker dentro de un contenedor Docker. Es necesario para este pipeline.
  • Variables de entorno (de nuevo): Este ejemplo también utiliza variables de entorno para almacenar información sensible (credenciales de Docker Hub y de Google Cloud). Defínelas en la configuración de CI/CD de GitLab. La variable que contiene la llave de Google Cloud debe ser de tipo "File".
  • Kubernetes: Este ejemplo asume que ya tienes un clúster de Kubernetes configurado y un deployment llamado "my-app". Adapta los comandos
    kubectl
    a tu configuración específica de Kubernetes. Podrías usar archivos YAML de configuración de Kubernetes (
    kubectl apply -f deployment.yaml
    ) en lugar de
    kubectl set image
    .
  • **Registro de contenedores:** Se hace uso de Docker Hub, pero es totalmente compatible con GitLab Container Registry, en ese caso, solo se necesita cambiar el tag de la imagen y la variable `DOCKER_HUB_REPO` por `$CI_REGISTRY_IMAGE`. De esta forma, para hacer login, ya no es necesario el usuario y contraseña, se usan las variables `$CI_REGISTRY_USER` y `$CI_REGISTRY_PASSWORD` que son provistas por GitLab.
  • Adaptación: Adapta este pipeline a tu aplicación y a tu entorno de despliegue.

Pipeline para Pruebas Automatizadas


stages:
  - test

test_unitarias:
  stage: test
  image: node:16
  script:
    - npm install
    - npm run test:unit # Ejecuta pruebas unitarias (asumiendo un script en package.json).

test_integracion:
  stage: test
  image: node:16
  script:
    - npm install
    - npm run test:integration # Ejecuta pruebas de integración (asumiendo un script en package.json).

test_e2e:
  stage: test
  image: selenium/standalone-chrome # Usa una imagen con Selenium y Chrome para pruebas end-to-end.
  script:
    - npm install
    - npm run test:e2e # Ejecuta pruebas end-to-end (asumiendo un script en package.json).

Se pueden usar diferentes `image` para cada tipo de prueba o usar solo una para todas, lo importante, es tener instaladas las dependencias necesarias.

Estos son solo ejemplos básicos. Puedes crear pipelines mucho más complejos y personalizados según tus necesidades. La clave es entender los conceptos fundamentales de GitLab CI/CD y cómo se configuran en el archivo

.gitlab-ci.yml
.

Integración con Otras Herramientas

GitLab CI/CD no solo se limita a la construcción, prueba y despliegue de código. Su flexibilidad permite integrarlo con una amplia gama de herramientas externas para extender sus capacidades y adaptarse a flujos de trabajo más complejos. Estas integraciones pueden abarcar desde la gestión de la configuración hasta el monitoreo y las notificaciones.

Integración con herramientas de gestión de la configuración (Ansible, Chef, Puppet)

Las herramientas de gestión de la configuración, como Ansible, Chef y Puppet, automatizan la configuración y administración de la infraestructura. GitLab CI/CD puede integrarse con estas herramientas para automatizar la provisión y configuración de servidores, máquinas virtuales y otros recursos de infraestructura como parte del proceso de despliegue.

Ejemplo (Ansible):


deploy:
  stage: deploy
  image: python:3.9 # Usamos una imagen de Python, ya que Ansible está escrito en Python.
  before_script:
      - pip install ansible
  script:
    - ansible-playbook -i inventory.ini playbook.yml -u $ANSIBLE_USER -k # Ejecuta un playbook de Ansible.
  only:
    - main

Explicación:

  • Se instala Ansible en la imagen.
  • Se ejecuta un playbook de Ansible (
    playbook.yml
    ) usando un archivo de inventario (
    inventory.ini
    ). Estos archivos deben estar en el repositorio.
  • Las variables
    $ANSIBLE_USER
    y la contraseña, se obtienen de las variables de entorno de CI/CD de GitLab. La contraseña, en este caso, se introduce interactivamente durante la ejecución. Se puede evitar esto, usando una llave SSH.

Chef y Puppet se integrarían de manera similar, utilizando sus respectivos comandos y archivos de configuración.

Integración con Plataformas Cloud (AWS, Google Cloud, Azure)

GitLab CI/CD se integra fácilmente con las principales plataformas cloud (AWS, Google Cloud, Azure) para automatizar el despliegue de aplicaciones y la gestión de la infraestructura en la nube.

Despliegue de Aplicaciones Serverless

Se pueden automatizar los despliegues usando las herramientas CLI de cada nube.

Ejemplo (AWS Lambda - Serverless Framework):


deploy_lambda:
  stage: deploy
  image: node:16
  before_script:
      - npm install -g serverless
  script:
    - serverless deploy --stage production # Despliega la función Lambda usando Serverless Framework.
  only:
    - main

Despliegue en Máquinas Virtuales

Se puede usar SSH para desplegar, tal como se mostró en ejemplos anteriores, o usar las herramientas de cada nube.

Ejemplo (Google Cloud - gcloud):


deploy_vm:
  stage: deploy
  image: google/cloud-sdk:latest
  script:
    - echo "$GCLOUD_SERVICE_KEY" > gcloud-service-key.json
    - gcloud auth activate-service-account --key-file gcloud-service-key.json
    - gcloud config set project $GCLOUD_PROJECT
    - gcloud compute scp --zone $GCLOUD_ZONE ./dist/* $GCLOUD_VM_USER@$GCLOUD_VM_NAME:/home/$GCLOUD_VM_USER/app/ #Copia los archivos al servidor
    - gcloud compute ssh --zone $GCLOUD_ZONE $GCLOUD_VM_USER@$GCLOUD_VM_NAME --command "pm2 restart app" #Reinicia la aplicación
  only:
    - main

Gestión de Infraestructura como Código (Terraform, CloudFormation)

GitLab CI/CD puede integrarse con herramientas de infraestructura como código (IaC) como Terraform y CloudFormation para automatizar la creación, modificación y eliminación de recursos de infraestructura en la nube.

Ejemplo (Terraform):


stages:
  - validate
  - plan
  - apply

validate:
  stage: validate
  image: hashicorp/terraform:latest
  script:
    - terraform init
    - terraform validate

plan:
  stage: plan
  image: hashicorp/terraform:latest
  script:
    - terraform init
    - terraform plan -out=tfplan
  artifacts:
      paths:
          - tfplan
  only:
      - merge_requests

apply:
  stage: apply
  image: hashicorp/terraform:latest
  script:
    - terraform init
    - terraform apply -input=false tfplan
  only:
    - main
  when: manual #Se puede agregar para requerir aprobación manual
  • Se valida la sintaxis de los archivos de configuración.
  • Se genera un plan de ejecución.
  • Se aplica el plan (solo en la rama
    main
    en este ejemplo y de forma manual).
  • Se hace uso de los artifacts para pasar el plan entre Jobs.
  • Se restringe la ejecución del plan a solo merge requests.

Integración con Herramientas de Monitoreo y Notificaciones (Slack, Prometheus, Grafana)

GitLab CI/CD puede integrarse con herramientas de monitoreo y notificaciones para enviar alertas y reportes sobre el estado de los pipelines y las aplicaciones.

Ejemplo (Slack):


# .gitlab-ci.yml
stages:
  - build
  - notify

build:
    stage: build
    script:
        - echo "building"

slack_notify:
    stage: notify
    image: curlimages/curl:latest #Se usa una imagen que contenga curl
    script:
    - 'curl -X POST -H "Content-type: application/json" --data "{\"text\":\"Build failed for project $CI_PROJECT_NAME on branch $CI_COMMIT_REF_NAME.  See <$CI_PIPELINE_URL|pipeline>. \"}" $SLACK_WEBHOOK_URL'
    when: on_failure # Solo se ejecuta si el trabajo anterior falla.
    allow_failure: true
  • Se envía un mensaje a un canal de Slack si un trabajo falla.
  • Se utiliza la variable de entorno
    $SLACK_WEBHOOK_URL
    , que debe contener la URL del webhook de Slack (configurada en Slack). Se configura en GitLab como variable protegida.
  • Se puede usar `when: always` para que se ejecute siempre.
  • `allow_failure: true` permite que el pipeline continue, a pesar de que falle este Job.

Estas son solo algunas de las muchas integraciones posibles con GitLab CI/CD. La clave es utilizar las herramientas y los comandos adecuados dentro de los trabajos de tu pipeline, aprovechando las variables de entorno y las capacidades de GitLab CI/CD para conectar diferentes sistemas y automatizar tus flujos de trabajo.

Mejores Prácticas y Consejos

Para aprovechar al máximo GitLab CI/CD y crear pipelines eficientes, robustos y fáciles de mantener, es importante seguir algunas mejores prácticas y tener en cuenta algunos consejos útiles.

  • Mantén tus pipelines simples y modulares: Divide tus pipelines en etapas y trabajos lógicos y reutilizables. Evita crear pipelines monolíticos que sean difíciles de entender y mantener. Usa, si es posible, archivos `.yml` separados e inclúyelos.
  • Usa imágenes de Docker: Ejecuta tus trabajos en imágenes de Docker para garantizar un entorno consistente y aislado. Esto evita problemas de dependencias y asegura que tus pipelines funcionen de la misma manera en cualquier entorno.
  • Utiliza variables de entorno: Almacena información sensible (como contraseñas, tokens de API y claves SSH) y valores configurables (como nombres de servidores y rutas) en variables de entorno. No guardes información sensible directamente en el archivo
    .gitlab-ci.yml
    .
  • Aprovecha el almacenamiento en caché (cache): Utiliza el almacenamiento en caché de GitLab CI/CD para acelerar tus pipelines. Almacena en caché las dependencias (como los paquetes de npm o las imágenes de Docker) para evitar descargarlas en cada ejecución.
  • Usa `only` y `except` con cuidado: Utiliza `only` y `except` para controlar la ejecución de tus Jobs según tus necesidades.
  • Usa artifacts: Usa `artifacts` para pasar archivos entre jobs o para descargar los resultados del pipeline.
  • Escribe pruebas automatizadas: Las pruebas automatizadas son fundamentales para la integración continua. Escribe pruebas unitarias, de integración y end-to-end para garantizar que tu código funcione correctamente.
  • Mantén tu archivo
    .gitlab-ci.yml
    limpio y legible:
    Utiliza comentarios para explicar las diferentes secciones de tu pipeline. Sigue una estructura lógica y consistente. Utiliza una herramienta de linting para YAML para detectar errores de sintaxis.
  • Monitorea tus pipelines: Supervisa el estado de tus pipelines y recibe notificaciones en caso de fallos. Utiliza herramientas de monitoreo para analizar el rendimiento de tus pipelines y optimizarlos.
  • Utiliza ramas (branches) y merge requests: Trabaja en ramas separadas para cada nueva característica o corrección de errores. Utiliza merge requests para revisar el código antes de fusionarlo con la rama principal (normalmente
    main
    o
    master
    ). Configura tu pipeline para que se ejecute automáticamente en cada merge request.
  • Documenta tu pipeline: Explica cómo funciona tu pipeline, qué hace cada trabajo y cómo configurarlo. Esto facilitará la colaboración y el mantenimiento.
  • Empieza poco a poco: Si eres nuevo en CI/CD, empieza con un pipeline simple y ve añadiendo complejidad gradualmente.
  • Aprovecha la comunidad: Si tienes dudas o problemas, consulta la documentación de GitLab CI/CD, busca en foros y pregunta a la comunidad. Hay muchos recursos disponibles.
  • Utiliza un linter para tu archivo .gitlab-ci.yml: GitLab proporciona un linter integrado para el archivo .gitlab-ci.yml. Lo puedes encontrar en la interfaz web de GitLab, en la sección CI/CD, hay un botón que dice "CI Lint". Esto te ayudará a encontrar errores de sintaxis y problemas de configuración antes de ejecutar el pipeline.
  • Usa `include`: Permite reutilizar código de otros archivos `.yml`.
    
            include:
              - 'configs/common.yml'  # Archivo local en el mismo repositorio.
              - project: 'my-group/my-project'
                file: '/templates/.gitlab-ci-template.yml' # Archivo desde otro proyecto.
            

Siguiendo estas mejores prácticas y consejos, podrás crear pipelines de CI/CD eficientes, confiables y fáciles de mantener, lo que te permitirá entregar software de alta calidad de forma más rápida y segura.

Solución a problemas comunes

Incluso con la mejor configuración, es posible que encuentres problemas al trabajar con GitLab CI/CD. Aquí hay algunas soluciones a problemas comunes:

  • El pipeline falla con un error "Job failed: exit code 1" (o similar):
    • Causa: Este es un error genérico que indica que uno de los comandos en la sección
      script
      de tu trabajo ha fallado (devolvió un código de salida distinto de cero).
    • Solución:
      • Examina cuidadosamente la salida del registro del trabajo (job log) en GitLab. Busca el comando que falló y el mensaje de error específico.
      • Asegúrate de que todos los comandos en tu script sean válidos y estén escritos correctamente.
      • Verifica que todas las dependencias necesarias estén instaladas en la imagen de Docker que estás utilizando.
      • Si el comando que falla es una prueba, revisa el código de la prueba para identificar la causa del fallo.
      • Si estás ejecutando un script externo, asegúrate de que tenga permisos de ejecución (
        chmod +x my_script.sh
        ).
  • El pipeline se queda atascado en "pending" o "stuck":
    • Causa: Esto suele indicar que no hay runners disponibles para ejecutar el trabajo. Esto puede deberse a varias razones:
      • No has configurado ningún runner para tu proyecto o grupo.
      • Tus runners están offline o no están configurados correctamente.
      • Tus runners están ocupados ejecutando otros trabajos.
      • El trabajo tiene etiquetas (tags) que no coinciden con ningún runner disponible.
      • Estás usando shared runners en GitLab.com y has excedido tu cuota de minutos de CI/CD.
    • Solución:
      • Verifica que tengas runners configurados y que estén online. Ve a Settings > CI/CD > Runners en tu proyecto o grupo.
      • Si estás usando runners específicos o de grupo, asegúrate de que estén instalados y registrados correctamente.
      • Si estás usando shared runners, verifica tu cuota de minutos de CI/CD en GitLab.com.
      • Revisa las etiquetas (tags) de tu trabajo y asegúrate de que coincidan con las etiquetas de al menos un runner disponible.
      • Si el problema persiste, intenta reiniciar el runner.
      • Asegúrate de que el runner tenga suficiente memoria y CPU para ejecutar el trabajo.
  • El trabajo falla con un error relacionado con Docker:
    • Causa: Si estás utilizando Docker dentro de tus trabajos (por ejemplo, para construir imágenes de Docker), puedes encontrar errores relacionados con Docker.
      • No se puede conectar al daemon de Docker (Docker daemon).
      • No se encuentra la imagen de Docker.
      • Errores de permisos al ejecutar comandos de Docker.
    • Solución:
      • Si estás utilizando el servicio
        docker:dind
        (Docker-in-Docker), asegúrate de que esté configurado correctamente en tu archivo
        .gitlab-ci.yml
        .
      • Verifica que la imagen de Docker que estás utilizando exista y esté disponible en el registro de contenedores (Docker Hub, GitLab Container Registry, etc.).
      • Si estás construyendo una imagen de Docker, asegúrate de que el
        Dockerfile
        esté escrito correctamente y de que todos los archivos necesarios estén presentes en el contexto de construcción.
      • Si estás utilizando un runner con el executor `docker`, asegúrate de que el usuario que ejecuta el runner tenga permisos para ejecutar comandos de Docker (normalmente, esto se hace añadiendo el usuario al grupo `docker`).
      • Si estás usando un registro privado, asegúrate de iniciar sesión (
        docker login
        ) antes de intentar usar o crear una imagen.
  • Errores de sintaxis en el archivo
    .gitlab-ci.yml
    :
    • Causa: Los errores de sintaxis en el archivo
      .gitlab-ci.yml
      son comunes, especialmente si estás empezando. YAML es muy sensible a la indentación y a la estructura.
    • Solución:
      • Utiliza el linter de CI/CD integrado en GitLab (CI Lint) para validar tu archivo
        .gitlab-ci.yml
        . Lo encontrarás en la interfaz web de GitLab, en la sección CI/CD.
      • Utiliza un editor de código o IDE con soporte para YAML, que te ayudará a detectar errores de sintaxis y a formatear el archivo correctamente.
      • Presta mucha atención a la indentación. Utiliza espacios (no tabulaciones) y asegúrate de que la indentación sea consistente.
      • Revisa cuidadosamente la documentación de GitLab CI/CD para asegurarte de que estás utilizando las palabras clave y la sintaxis correctas.
  • Problemas con las variables de entorno:
    • Causa:
      • La variable no fue definida.
      • El nombre de la variable está mal escrito.
      • La variable no tiene el valor esperado.
      • La variable es de tipo "File" y no se usa adecuadamente.
    • Solución:
      • Verifica si la variable fue definida en: Settings > CI/CD > Variables.
      • Revisa la sintaxis, tanto en el archivo `.gitlab-ci.yml` como en la configuración de GitLab.
      • Usa `echo $VARIABLE` dentro del `script` para verificar el valor de la variable.
      • Si la variable es de tipo "File", recuerda que el valor de la variable será la *ruta* al archivo temporal que contiene el valor real, por lo tanto, debes usar un comando como `cat` para leer su contenido. Por ejemplo: `cat $MY_FILE_VARIABLE`.
  • Artifacts no encontrados:
    • Causa:
      • El Job del que depende no se ejecutó.
      • El Job del que depende no generó artifacts.
      • La ruta a los artifacts es incorrecta.
      • Los artifacts expiraron.
    • Solución:
      • Asegúrate de que el Job que genera los artifacts se ejecute antes y termine exitosamente.
      • Verifica que el Job que genera los artifacts tenga la sección `artifacts` bien configurada.
      • Revisa las rutas a los artifacts, tanto en la sección `artifacts:paths` como en el Job que los consume, usando `dependencies`.
      • Verifica la configuración de expiración de los artifacts (`artifacts:expire_in`).

Estos son solo algunos de los problemas más comunes que puedes encontrar al trabajar con GitLab CI/CD. La clave para solucionar problemas es leer cuidadosamente los registros de los trabajos, identificar la causa del error y aplicar la solución adecuada. La documentación de GitLab CI/CD es un recurso muy valioso para encontrar información y soluciones a problemas específicos.

Conclusión

GitLab CI/CD es una herramienta poderosa y flexible que transforma la forma en que los equipos desarrollan y entregan software. Al automatizar las tareas repetitivas de construcción, prueba y despliegue, GitLab CI/CD permite a los desarrolladores enfocarse en escribir código de calidad y entregar valor a los usuarios de manera más rápida y eficiente. La integración continua y el despliegue continuo, facilitados por GitLab CI/CD, promueven una cultura de colaboración, transparencia y responsabilidad, lo que se traduce en ciclos de desarrollo más cortos, menor riesgo de errores y mayor satisfacción del cliente.

Desde la configuración inicial del entorno GitLab hasta la creación de pipelines complejos e integrados con otras herramientas, este tutorial ha cubierto los aspectos esenciales de GitLab CI/CD. Hemos explorado la sintaxis del archivo

.gitlab-ci.yml
, los diferentes tipos de runners, ejemplos de pipelines comunes, las mejores prácticas y la solución de problemas frecuentes. Con este conocimiento, estás preparado para comenzar a implementar tus propios pipelines de CI/CD en GitLab y aprovechar todos los beneficios que ofrece esta herramienta.

No obstante, el aprendizaje no termina aquí. Te animo a seguir explorando la documentación oficial de GitLab, experimentar con diferentes configuraciones, y participar activamente en foros y comunidades de GitLab para expandir aún más tu conocimiento. La continua evolución de las prácticas de DevOps y de la propia plataforma GitLab CI/CD ofrecen un horizonte de posibilidades y mejoras continuas. ¡Adopta la automatización, la integración continua y el despliegue continuo y lleva tus proyectos de software al siguiente nivel!