IT-Admin.tech

Automatización: configurar una canalización CI/CD con GitLab CI, escaneo de imágenes Docker y rollbacks automatizados

Architekturdiagramm einer CI/CD-Pipeline mit GitLab CI, Trivy Image-Scanning, Container Registry und automatischem...
Schematische Darstellung: GitLab CI, Image-Scanning und Canary-Deploy mit automatischem Rollback in Kubernetes.

Un proceso de entrega fiable y automatizado reduce tiempos de inactividad y errores humanos en la operación de soluciones empresariales digitales. En este artículo explico de forma práctica cómo montar una CI/CD-Pipeline con GitLab CI, integrar el escaneo de imágenes Docker e implementar rollbacks automatizados. El objetivo es una ruta de operación mantenible: Build → Test → Scan → Deploy → observación → rollback automático en caso de fallos críticos. La palabra clave de enfoque CI/CD-Pipeline con GitLab CI ya aparece en la introducción, para que la intención de búsqueda quede clara.

¿Por qué una CI/CD-Pipeline con GitLab CI?

GitLab CI es un sistema CI/CD integrado en GitLab que ejecuta pipelines basadas en .gitlab-ci.yml. Para los administradores es importante: GitLab CI orquesta runners (agentes de ejecución), dispone de integraciones con registries incorporadas y puede conectarse con herramientas externas (scanning, monitoring). Una pipeline estructurada reduce el riesgo del despliegue, automatiza las comprobaciones de seguridad (image-scanning) y permite despliegues con posibilidad de rollback seguro (rollbacks).

Visión general de la arquitectura y requisitos

La arquitectura típica incluye GitLab (repositorio + CI), GitLab Runners, un registro de contenedores (p. ej. GitLab Registry o un Harbor privado), una herramienta de escaneo de imágenes (p. ej. Trivy, Clair o GitLabs Container Scanning), una capa de orquestación (habitualmente Kubernetes) y monitorización/alertas (p. ej. Prometheus + Alertmanager). Los requisitos son:

  • Instancia de GitLab con runners y acceso al registro.
  • Accesos autenticados al registro (Tokens/CI_JOB_TOKEN oder Deploy-Keys).
  • Entorno objetivo con API de despliegue (kubectl + Kubeconfig oder Helm).
  • Monitorización con métricas de salud y SLO definidas para la toma de decisiones.
  • Mecanismos de rollback y playbooks documentados para los equipos de operación.

Terminología

CI/CD (Continuous Integration / Continuous Deployment) describe pasos automatizados desde la integración de código hasta la entrega. El image-scanning examina imágenes de contenedores en busca de vulnerabilidades y errores de configuración. Rollback se refiere a revertir un cambio de despliegue cuando una versión es defectuosa. SBOM (Software Bill of Materials) es un listado de todos los componentes de un artefacto y facilita análisis de cumplimiento y seguridad.

Diseño de la pipeline: etapas, responsabilidades, políticas

Una estructura de stages práctica:

  1. prepare: Checkout, preparación de artefactos
  2. build: construcción de imagen y etiquetado
  3. scan: image-scanning (controles de seguridad/política)
  4. test: pruebas unitarias, de integración y smoke
  5. deploy: despliegue canario/primario
  6. verify: healthchecks, comprobaciones de telemetría
  7. promote / finalize: promoción tras canary exitoso

Es importante la separación de responsabilidades: los jobs de build y scan no deberían ejecutarse en el mismo runner que los jobs de despliegue productivo, para minimizar el blast radius y los permisos.

Estrategia de etiquetado de imágenes

Use etiquetas inmutables (p. ej. Git-Commit-SHA o semver más build-id). Etiquetas mutables como latest son problemáticas en entornos productivos, porque dificultan la reproducibilidad y los rollback.

Ejemplo .gitlab-ci.yml: minimal pero seguro para producción

El siguiente ejemplo muestra los elementos centrales: build, scan con Trivy, push y deploy en un clúster Kubernetes. Preste atención a los secrets definidos y a una configuración de runners segura.

Yaml
stages:
  - build
  - scan
  - test
  - deploy
  - verify

variables:
  IMAGE_REGISTRY: registry.example.local
  IMAGE_NAME: "$IMAGE_REGISTRY/myapp"
  KUBE_CONTEXT: production

build:
  stage: build
  image: docker:24
  services:
    - docker:dind
  script:
    - docker build -t "$IMAGE_NAME:$CI_COMMIT_SHORT_SHA" .
    - docker push "$IMAGE_NAME:$CI_COMMIT_SHORT_SHA"
  only:
    - main

scan:
  stage: scan
  image: aquasec/trivy:latest
  script:
    - trivy image --severity HIGH,CRITICAL --exit-code 1 --no-progress "$IMAGE_NAME:$CI_COMMIT_SHORT_SHA"
  allow_failure: false

deploy_canary:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl --context="$KUBE_CONTEXT" set image deployment/myapp myapp="$IMAGE_NAME:$CI_COMMIT_SHORT_SHA" --record
    - kubectl --context="$KUBE_CONTEXT" rollout status deployment/myapp --timeout=120s
  when: manual
  only:
    - main

verify_canary:
  stage: verify
  image: curlimages/curl:latest
  script:
    - /usr/local/bin/healthcheck.sh "$KUBE_CONTEXT" "myapp" || exit 1
  allow_failure: false

Por qué funciona: Build genera una imagen inmutable; Scan detiene la pipeline ante vulnerabilidades críticas; Deploy usa kubectl para actualizar el recurso Deployment existente; Verify ejecuta un healthcheck basado en métricas de tiempo de ejecución o en pruebas de humo. Fallos en Scan/Verify impiden la promoción automática a producción.

Escaneo de imágenes: herramientas, políticas y riesgos comunes

Los escáneres habituales son Trivy (rápido, basado en CLI), Clair (servidor), Grype o el Container Scanning integrado de GitLabs (SAST/DAST). Los escáneres proporcionan listas de CVE, niveles de severidad y versiones con corrección. Elija la definición de la política con prudencia:

  • Niveles de severidad bloqueantes (p. ej. CRITICAL/HIGH) para abortar automáticamente el pipeline.
  • Allow-listing para vulnerabilidades aceptadas pero evaluadas (con proceso de revisión).
  • Actualización regular de la base de datos del escáner (feeds de vulnerabilidades) – bases de datos desactualizadas generan falsos negativos.

Errores típicos:

  • Autenticación ausente frente al registry: falta CI_JOB_TOKEN o deploy-keys.
  • El caché de imágenes en los runners enmascara problemas: pruebe los escaneos contra imágenes descargadas (pulled), no solo contra capas locales.
  • Las versiones del escáner varían en los escaneos de CVE – documente las versiones para auditoría.

Estrategias de despliegue y rollbacks automatizados

Los rollbacks automatizados requieren que los Deployment sean reversibles y observables. Estrategias habituales:

  • Blue/Green: entorno paralelo completo, conmutación de tráfico al éxito.
  • Canary: porcentaje de tráfico al nuevo release; métricas observadas deciden la promoción.
  • Rolling Update con readiness-probes: por defecto en Kubernetes, pero garantías limitadas sin monitorización.

Mecanismos de rollback en Kubernetes

En Kubernetes, la reversión más sencilla es kubectl rollout undo, que reactiva el ReplicaSet anterior. Requisito: que los ReplicaSets se conserven (default: sí, salvo limpieza explícita). En despliegues con Helm, utilice helm rollback con releases guardados.

Shell
# Rollback auf letzte Revision (kubectl)
kubectl --context=production rollout undo deployment/myapp

# Helm rollback auf Revision 2
helm --kube-context production rollback myapp 2

Cuándo eso falla: los Rollbacks son ineficaces cuando los pasos de migración de la base de datos no se pueden revertir de forma compatible o cuando los cambios de configuración no son reversibles. Planifique las migraciones de base de datos como procesos separados y controlados (p. ej., migraciones que sean compatibles hacia adelante y hacia atrás).

Implementación de un disparador de Rollback automático

Un Rollback automático no debe ejecutarse a ciegas. Buenos disparadores son:

  • Los smoke tests (comprobaciones de endpoints, flujo de autenticación, conectividad con la BD) fallan.
  • La tasa de errores supera los umbrales definidos (p. ej., 5xx > X%).
  • La latencia o la tasa de éxito cae por debajo de los valores SLA definidos.

Técnicamente, el disparador se implementa mediante un job de verificación en la pipeline o mediante monitorización externa con webhook. Ejemplo de un script de comprobación de salud que se puede usar en la etapa verify:

Shell
#!/usr/bin/env bash
# healthcheck.sh: einfache Smoke-Checks für Canary
set -euo pipefail
KUBE_CONTEXT="$1"
DEPLOYMENT="$2"
NAMESPACE="default"
# Beispiel: 3 Versuche, 2 Sekunden Pause
for i in 1 2 3; do
  POD=$(kubectl --context="$KUBE_CONTEXT" -n "$NAMESPACE" get pods -l app="$DEPLOYMENT" -o jsonpath='{.items[0].metadata.name}')
  kubectl --context="$KUBE_CONTEXT" -n "$NAMESPACE" exec "$POD" -- /bin/sh -c 'curl -fsS --max-time 5 http://localhost:8080/healthz' && exit 0 || sleep 2
done
exit 1

Si este script termina con código de salida 1, debería ejecutarse un job de Rollback automático en la pipeline o activarse una alerta que dispare una acción automatizada del runbook.

Extensión práctica de la pipeline: Job de Rollback

Agregue el .gitlab-ci.yml un job de rollback dedicado que solo se dispare cuando falle la etapa verify. Es importante: los permisos para rollback deben ser RESTrictivos (rol RBAC con los mínimos privilegios), y la acción de rollback debe ser idempotente.

Yaml
rollback_on_verify_failure:
  stage: deploy
  image: bitnami/kubectl:latest
  when: on_failure
  script:
    - kubectl --context="$KUBE_CONTEXT" rollout undo deployment/myapp || true
  only:
    - main

Nota: use when: on_failure de forma selectiva – en pipelines complejas esto puede generar efectos secundarios inesperados si fallan varios jobs. Pruebe el comportamiento en un entorno de staging.

Pipeline CI/CD con GitLab CI: operación, escalado y gobernanza

El escalado y la gobernanza son tan importantes en el entorno productivo como la lógica de la pipeline. Temas operativos importantes:

  • Escalado de runners: configure el autoscaling de GitLab Runner (p. ej., executor de Kubernetes o Docker Machine) para absorber picos de carga sin intervenciones manuales.
  • Runners compartidos vs. específicos: los runners compartidos son cómodos, pero aumentan el riesgo de contención de recursos. Use runners dedicados para jobs de despliegue con privilegios.
  • Auditoría y cumplimiento: active los audit logs en GitLab y conserve los informes de escaneo y los SBOMs para auditorías.

Ejemplo: extracto de una config.toml de GitLab Runner para un executor de Kubernetes con autoscaling (representación simplificada):

Ini
[[runners]]
  name = "k8s-runner"
  url = "https://gitlab.example.local/"
  token = ""
  executor = "kubernetes"
  [runners.kubernetes]
    namespace = "gitlab-runner"
    image = "alpine:3.18"
    idle_timeout = 1800
    poll_timeout = 180

Por qué ayuda: el executor de Kubernetes crea pods por job y así limita los efectos secundarios causados por runners compartidos en el host. PRESTe atención a los resource-requests/limits para que los pods de los jobs no agoten los recursos del nodo.

Secrets, RBAC y principio de menor privilegio

Los Secrets nunca deben incluirse en la imagen. En GitLab utilice Protected Variables (enmascaradas, solo disponibles en ramas protegidas). Para los despliegues en el clúster de Kubernetes se deben usar ServiceAccounts con los mínimos permisos RBAC necesarios — no tokens de administrador del clúster.

Yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: deployer
  namespace: production
rules:
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets"]
  verbs: ["get","list","watch","update","patch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: deployer-binding
  namespace: production
subjects:
- kind: ServiceAccount
  name: ci-deployer
  namespace: gitlab-runner
roleRef:
  kind: Role
  name: deployer
  apiGroup: rbac.authorization.k8s.io

El ejemplo anterior de Role/RoleBinding permite al ServiceAccount únicamente acciones de despliegue y rollback en el namespace production. Este nivel de granularidad reduce el riesgo asociado a tokens de CI comprometidos.

SBOM, retención de artefactos y gobernanza del registro

Los SBOMs hacen verificables las dependencias y las bibliotecas incluidas. Trivy puede generar SBOMs; vincúlelos como artefacto a los jobs de compilación. Defina una estrategia de retención para artefactos e imágenes: una garbage-collection demasiado agresiva puede impedir rollbacks; políticas demasiado laxas llenarán el almacenamiento del registry.

Shell
# Trivy SBOM erzeugen
trivy image --format cyclonedx --output sbom.cdx.json registry.example.local/myapp:$CI_COMMIT_SHORT_SHA

Recomendación: conserve al menos las últimas N imágenes por servicio (p. ej. N=10) y los SBOMs durante los plazos legales de conservación que exija el cumplimiento normativo.

Observability e integración de alertas con CI

Las decisiones automatizadas se basan en métricas. Defina reglas de alerta claras en Prometheus y conecte Alertmanager a un webhook que invoque un GitLab-Trigger o cree un ticket. Ejemplo de una AlertRule simple de Prometheus (ejemplo simplificado):

Yaml
groups:
- name: app.rules
  rules:
  - alert: HighErrorRate
    expr: rate(http_requests_total{job="myapp",status=~"5.."}[2m]) > 0.05
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "Hohe Fehlerquote bei myapp"
      runbook: "https://wiki.example.local/runbooks/myapp-rollback"

Alertmanager puede enviar un webhook a un endpoint de trigger de CI al activarse. Asegúrese de que los endpoints de trigger estén protegidos y que solo alerts autorizadas puedan desencadenar acciones.

Garbage Collection, caching y notas de rendimiento

El rendimiento del scanner depende en gran medida de la disponibilidad de la red y de la estrategia de caché local. Evite que los runners descarguen constantemente imágenes grandes empleando un cache o proxy local para el registry. Asimismo, use Docker-in-Docker solo cuando el aislamiento de los runners no sea posible por otros medios; Kaniko, BuildKit o Podman suelen ser alternativas más seguras para el Kubernetes-Executor.

Estrategia de pruebas y validación antes del despliegue en producción

Valide cada paso:

  • Validar el acceso de runners y del registry con imágenes dummy.
  • Comprobar las actualizaciones de la DB del scanner y los códigos de salida (Trivy –version, trivy db update).
  • Realizar repetidamente deploys y rollbacks en staging; verifique los historiales de ReplicaSet/Helm-Release.
  • Simule fallos de health check para comprobar los rollbacks automatizados.
Shell
# Trivy DB-Update (wichtig vor Scans)
trivy db update

Casos de error típicos y resolución de problemas

Error: Los trabajos de escaneo tardan mucho o se producen timeouts. Causas: Scanner-DB desactualizada, proxy de red bloquea el acceso a los feeds de vulnerabilidades, gran caché de capas de imagen. Pasos de verificación: comprobar la versión del scanner, probar el acceso de red, comprobar la ejecución del escaneo de la imagen de forma local.

Error: El rollback falla porque se han eliminado los ReplicaSets. Causa: Garbage-Collection/Cluster-Cleanup. Medidas: Configure las políticas del clúster para conservar los ReplicaSets/Releases anteriores durante un periodo de tiempo definido.

Error: Incompatibilidad de base de datos durante el rollback. Causa: Migraciones que no pueden deshacerse. Solución: migraciones en dos pasos (compatibles hacia delante), usar Feature-Flags, planificar estrategias separadas de rollback de base de datos.

Runbook: Acciones rápidas paso a paso ante un incidente

  1. Comprobar la alarma: métricas, logs, historial de despliegues.
  2. Aislar: revertir inmediatamente el tráfico canario o RESTaurar el servicio a réplicas previas.
  3. Ejecutar rollback (kubectl rollout undo o helm rollback).
  4. Post-mortem: analizar la causa, resultados del scanner, cobertura de pruebas, métricas.
  5. Lecciones aprendidas: ajustar Pipeline/Tests/Probes, proporcionar parche.

Conclusión: Madurez operativa en lugar de solo automatización

Las pipelines CI/CD automatizadas con GitLab CI, escaneo integrado de imágenes Docker y procesos de rollback claramente definidos reducen considerablemente los riesgos, pero requieren disciplina: tags de imagen inmutables, políticas de scanner limpias, decisiones basadas en observability y estrategias de base de datos compatibles con rollback. Pruebe los rollbacks regularmente en staging, documente los Runbooks y mantenga los permisos de acceso de forma RESTrictiva. Solo así la automatización en producción será realmente resiliente y no se convertirá en una nueva fuente de fallos.

Siguientes pasos: Comience con un pequeño proof-of-concept: Build → Trivy-Scan → Canary-Deploy → Verify → Rollback, y vaya ampliando la pipeline paso a paso con controles de monitoring y de cumplimiento. Planifique ejercicios periódicos (Chaos-Tests, Rollback-Drills) y auditorías de las políticas de Runner-/Registry-Policies.

Para este tema también son importantes el escaneo de imágenes Docker y el despliegue canario. El artículo sitúa estos aspectos de forma comprensible y muestra qué importa en el día a día.