Serie CI/CD: Trabajando con Pipelines
En la primera parte vimos cómo levantar un entorno CI/CD desde cero. Ahora toca hablar del corazón del asunto: los pipelines. Sin un pipeline bien estructurado, todo lo demás es decoración. Definen el recorrido del código desde que alguien hace push hasta que llega a producción, y cuando están mal diseñados, te das cuenta rápido.
¿Qué es un Pipeline?
Un pipeline en CI/CD es una cadena de etapas que automatizan la compilación, las pruebas y el despliegue de una aplicación. Cada etapa agrupa un conjunto de acciones que corren en secuencia o en paralelo, y cada acción puede bloquearse si la anterior falla. Eso es lo que lo hace útil de verdad: el fallo es explícito, no silencioso.
Estructura Básica de un Pipeline
Un pipeline típico incluye varias etapas clave:
- Build: Compilación del código fuente y generación de artefactos.
- Test: Ejecución de pruebas automáticas para verificar la funcionalidad.
- Deploy: Despliegue de la aplicación en un entorno de pruebas o producción.
Ejemplo de Pipeline en GitLab CI
stages:
- build
- test
- deploy
build_job:
stage: build
script:
- echo "Construyendo la aplicación..."
- make build
test_job:
stage: test
script:
- echo "Ejecutando pruebas..."
- make test
deploy_job:
stage: deploy
script:
- echo "Desplegando en producción..."
- make deploy
Cada job (build_job, test_job, deploy_job) pertenece a una etapa del pipeline. Los scripts dentro de cada job son las instrucciones concretas que el runner ejecuta. Simple, pero ya funciona.
Mejores Prácticas para Configurar Pipelines
1. Mantén tus Pipelines Simples y Modulares
Un pipeline que nadie entiende es un pipeline que nadie va a querer tocar. La complejidad acumulada en un solo archivo de 400 líneas no es señal de madurez, es deuda técnica disfrazada de automatización. Parte las tareas en etapas pequeñas con responsabilidades claras. Cuando algo falla a las 2 de la mañana, no deberías necesitar leer un mapa para saber dónde buscar.
2. Asegura la Reproducibilidad
El pipeline tiene que producir el mismo resultado en tu máquina, en el servidor de CI y en producción. Si no lo hace, no es un pipeline confiable: es una fuente de sorpresas con nombre bonito. Docker resuelve mucho de esto al empaquetar el entorno junto con el código, pero no es magia. Hay que diseñarlo así desde el principio, no pegarlo al final.
3. Implementa Pruebas Automatizadas
Sin pruebas automatizadas, el pipeline es solo una cinta transportadora sin control de calidad. Unitarias, de integración y, cuando el coste vale la pena, end-to-end. Lo que no es negociable: que sean rápidas. Un pipeline que tarda 40 minutos en dar feedback termina siendo ignorado, y con razón.
4. Usa Entornos de Pruebas y Producción Separados
Nunca desplegues directo a producción sin pasar por staging. Parece obvio. En equipos con presión de tiempo o con pocos recursos, se omite igual. Los bugs que solo afloran con datos reales o con tráfico concurrente te alcanzan tarde o temprano, y siempre en el peor momento.
Herramientas y Estrategias Avanzadas
1. Estrategias de Despliegue
Hay varias formas de llevar código nuevo a producción sin tumbar el servicio. Las más usadas:
- Despliegue Azul/Verde: Mantener dos entornos de producción, uno activo y otro inactivo. El nuevo código se despliega en el entorno inactivo, y luego el tráfico se cambia al nuevo entorno.
- Canary Releases: Desplegar el nuevo código a un pequeño subconjunto de usuarios antes de hacer el despliegue completo.
- Rolling Updates: Desplegar gradualmente la nueva versión a todas las instancias de producción.
Cuál elegir depende del riesgo que puedas asumir y de qué tan rápido necesitas rollback. No hay respuesta universal, y desconfío de quien diga que sí la hay.
2. Monitorización y Alerta
Desplegar y olvidarse es media tarea, la mitad mala. El pipeline debería terminar dejando la aplicación observable: métricas expuestas, dashboards configurados, alertas activas antes de que el equipo de turno se vaya a dormir. Prometheus y Grafana son el estándar de facto en entornos Kubernetes, y tienen buena integración con GitLab CI si los conectas bien desde el pipeline.
Ejemplo Avanzado de Pipeline
stages:
- build
- test
- security
- deploy
- monitor
build_job:
stage: build
script:
- echo "Construyendo la aplicación..."
- docker build -t mi-app .
test_job:
stage: test
script:
- echo "Ejecutando pruebas unitarias..."
- docker run --rm mi-app pytest
security_job:
stage: security
script:
- echo "Analizando vulnerabilidades de seguridad..."
- docker run --rm mi-app trivy mi-app
deploy_job:
stage: deploy
script:
- echo "Desplegando en producción..."
- kubectl apply -f deployment.yaml
monitor_job:
stage: monitor
script:
- echo "Configurando monitorización..."
- kubectl apply -f monitoring.yaml
Este pipeline añade dos etapas que en proyectos reales no son opcionales: análisis de vulnerabilidades con Trivy y configuración de monitorización post-despliegue. La etapa de seguridad se omite mucho al principio. Se lamenta después, siempre con un incidente de por medio.
En la próxima entrega vamos a ver cómo manejar errores dentro del pipeline y dónde están los cuellos de botella más comunes.