Pipeline de CI/CD: diseñar tu propio robot de despliegue

La automatización no es algo desconocido

La vez pasada aprendí una lección dolorosa a través de 10 minutos de caída y un informe de incidente. El despliegue no es magia, sino que debe ser una cadena de estrictos mecanismos de seguridad: “Git, registro – Test, validación – Build, empaquetado – Deploy, entrega”.

Ahora el objetivo está claro. No puedo seguir comprobando con mis propias manos, una y otra vez, estos mecanismos de seguridad tan complejos y molestos. Necesito un “robot trabajador” que haga el trabajo por mí incluso después de que me haya ido a casa o cuando esté de vacaciones.

“¿Automatización? ¿No suena eso demasiado grandioso?”

Al principio me dio miedo, pero pensándolo bien, ya había vivido algo muy parecido. Era “Docker”, del que hablamos en la serie anterior.

Cuando escribimos en un Dockerfile “instala Ubuntu, instala Java, copia el código”, Docker lo lee y construye el entorno del servidor por sí solo. Gracias a eso, nos libramos del trabajo pesado de teclear comandos manualmente.

Un “pipeline de CI/CD” es exactamente lo mismo. Si Docker automatizó la “configuración del servidor”, el pipeline automatiza “todo el proceso de despliegue”. Lo único que cambió es que el escenario se amplió: ya no es solo mi ordenador, sino un mundo más grande llamado “GitLab y el servidor de producción”.

Si el Dockerfile es el manual de montaje del servidor, el pipeline es el manual de funcionamiento de la fábrica.

CI/CD: la cinta transportadora automatizada

Ahora instalemos una “línea automatizada” en nuestro “centro logístico digital”. Suena grande, pero el principio es simple.

1. CI (Continuous Integration, integración continua)

  • Significado: “Integrar continuamente en uno solo el código de los desarrolladores y verificarlo.”
  • Función: [Build + Test]. Es la etapa en la que, en cuanto subo el código, la máquina comprueba por mí: “¿Esta sintaxis es correcta?”, “¿No se ha roto ninguna funcionalidad existente?”. Aquí se filtran los productos defectuosos.

2. CD (Continuous Delivery/Deployment, entrega o despliegue continuos)

  • Significado: “Entregar al cliente el código que ya ha pasado la verificación.”
  • Función: [Creación de la imagen + despliegue en el servidor]. Es la etapa en la que el producto en buen estado que superó la inspección (Docker Image) se carga en el camión, se envía al servidor de producción y, además, se pone en marcha.

El plano del pipeline: .gitlab-ci.yml

“Entonces, ¿cómo le damos trabajo a ese robot?” En GitLab basta con crear un archivo llamado .gitlab-ci.yml en la raíz del proyecto. Esa es precisamente la “hoja de instrucciones de trabajo” que se le entrega al robot.

¿Recuerdas el dolor del despliegue manual que sufrí la vez pasada? Traslademos ese mismo proceso al código. Igual que cuando se escribe un Dockerfile, basta con ir escribiéndolo línea por línea.

# .gitlab-ci.yml (la hoja de tareas)

stages:          # 1. Definir el orden completo del trabajo
  - test         #   (Etapa 1: revision)
  - build        #   (Etapa 2: empaquetar)
  - deploy       #   (Etapa 3: envio)

# [Etapa 1] Test: maquina, comprueba si mi codigo esta bien (CI)
unit_test_job:
  stage: test
  image: openjdk:17-alpine # Ejecutar en un entorno con Java instalado
  script:
    - ./gradlew test       # "Ejecuta los tests!" (evita el error anterior)

# [Etapa 2] Build: si pasan los tests, construye una imagen (CI)
build_image_job:
  stage: build
  image: docker:latest     # Ejecutar en un entorno con Docker instalado
  script:
    - docker build -t my-app:v1 .  # "Crea la imagen!"
    - docker push my-regisry/my-app:v1 # "Sube al registro!" (etiqueta de rollback obligatoria)

# [Etapa 3] Deploy: ahora dejalo en el servidor de produccion (CD)
deploy_job:
  stage: deploy
  script:
    - ssh user@server "docker service update my-app" # "Actualiza el servidor!"

Con este único archivo es suficiente. En el momento en que hago git push, es decir, en el trigger, GitLab lee esta hoja de instrucciones y despierta a un robot trabajador llamado “GitLab Runner” para ponerlo a trabajar.

[Check] Los mecanismos de seguridad que debemos incluir

Dentro de este pipeline están integrados los tres mecanismos de seguridad que tan dolorosamente aprendí la vez pasada.

  1. Git (Trigger):
    • El simple hecho de hacer push del código desde mi entorno local se convierte en el “botón de inicio” del pipeline. Si no queda un registro (Commit), el despliegue tampoco empieza.
  2. Unit Test (Quality Gate):
    • ¿Y si falla el test en unit_test_job? El pipeline se “detiene (Fail)” de inmediato. Bloquea de raíz que un producto defectuoso pase a la siguiente etapa (build/deploy). (¡Se acabó saltarse los tests por ir con prisas!)
  3. Docker Image (Artifact):
    • La imagen generada en la etapa de build se guarda de forma segura en Docker Hub. Aunque más adelante el servidor se caiga, con solo tener esta imagen se puede recuperar en un segundo.
El código que no supera las pruebas jamás puede cargarse en el camión de despliegue.

Consejo práctico: un pipeline es un ser vivo

No intentes escribir un pipeline perfecto desde el principio. Yo mismo, al inicio, solo hice dos etapas, build y deploy, y fue solo después de causar un incidente cuando añadí delante la etapa de test.

  • Al principio: build -> deploy (lo importante era, ante todo, automatizar)
  • Fase intermedia: test -> build -> deploy (se añade un mecanismo de seguridad)
  • Fase avanzada: test -> análisis estático (SonarQube) -> build -> deploy al servidor de desarrollo -> (aprobación) -> deploy al servidor de producción

Un pipeline es un “sistema vivo” que sigue evolucionando al ritmo del crecimiento de nuestro equipo.

Para cerrar: escribimos las instrucciones, pero ¿quién hace realmente el trabajo?

Ahora el plano perfecto, .gitlab-ci.yml, ya está terminado. Pero una hoja de instrucciones escrita en papel no se mueve sola. Igual que un Dockerfile necesita que Docker Daemon esté instalado para poder ejecutarse, la hoja de instrucciones del pipeline también necesita un “robot de campo” que realmente sude construyendo y ejecutando el código.

El nombre de este robot es “GitLab Runner”. El jefe de la fábrica, es decir, el GitLab Server, solo da instrucciones. El trabajo real lo lleva a cabo este runner.

La próxima vez, instalemos este runner en mi ordenador o en un servidor aparte, conectémoslo con GitLab y pongamos en marcha de verdad el pipeline. Por fin es el momento en que se abrocha el primer botón de la automatización.

Deja un comentario