CD (Entrega Continua) — Parte 4: Deploy a Staging y Performance Smoke Tests


📚 Serie: CI/CD y la IA: De la teoría a la práctica

Esta parte cubre el despliegue en el entorno de preproducción (staging), la validación E2E y de rendimiento ligero, y la aprobación manual antes de promover a producción.

Partes de este bloque:


Deploy a Staging

Promueve el artefacto ya verificado (misma imagen firmada y SBOM) a un entorno de preproducción que replica la configuración de producción con mayor fidelidad. Staging es el último entorno para validar integraciones, performance a escala reducida, pruebas de regresión y validaciones de compliance antes del despliegue a producción.

Lo que incluye esta etapa

  • Selección del artefacto: promover la misma imagen firmada que pasó Dev y los scans.
  • Provisionamiento de entorno: aplicar IaC para crear/actualizar recursos (namespaces, ingress, secrets, configmaps) con valores de staging.
  • Configuración de datos: usar datos sintéticos o copias anonimizadas; preparar fixtures y migraciones necesarias.
  • Despliegue con estrategia realista: Helm/Kustomize con valores de staging; aplicar recursos de red, límites y tolerancias equivalentes a producción.
  • Activación de observabilidad completa: métricas, trazas distribuidas y logging centralizado con retención adecuada.
  • Ejecución de suites completas: E2E, performance smoke, tests de seguridad adicionales y validaciones de compliance.
  • Gates y aprobaciones: gates automáticos y, si procede, aprobación manual antes de promover a producción.
  • Registro y trazabilidad: anotar release con commit SHA, tag de imagen, SBOM y firma; almacenar artefactos y reportes.

Pasos

  1. Obtener imagen firmada del registry.
  2. Verificar firma (cosign) y SBOM asociado.
  3. Aplicar IaC (Terraform para infra, Helm/Kustomize para manifiestos).
  4. Configurar secrets desde Vault/Secret Manager; no exponer valores.
  5. Desplegar con wait y probes (helm upgrade --install --wait --timeout).
  6. Ejecutar validaciones automáticas: E2E, contract tests, smoke de performance.
  7. Evaluar resultados y ejecutar gates: si OK → marcar listo para producción; si KO → rollback y crear ticket.
  8. Aprobación humana opcional para producción (manual approval step).

Buenas prácticas

  • Promover el mismo artefacto firmado entre entornos para garantizar reproducibilidad.
  • Paridad de configuración con producción en límites, recursos y sidecars; diferencias solo en datos y endpoints externos.
  • Entorno inmutable: evitar cambios ad-hoc en staging; todo por IaC.
  • Datos anonimizados o synthetic data para pruebas realistas sin exponer PII.
  • Gates claros: definir qué fallos bloquean y cuáles generan tickets.
  • Aprobaciones para producción: integrar un paso de aprobación humana con contexto (logs, métricas, reportes).
  • Rollback automático y plan de mitigación si las validaciones fallan.
  • Observabilidad y trazabilidad: anotar release con metadatos y conservar reportes (E2E, perf, security).

Ventajas

  • Alta confianza antes de producción por la similitud con el entorno real.
  • Permite pruebas de integración y compliance en condiciones realistas.
  • Reduce riesgos de regresiones y errores de configuración.

Desventajas / riesgos

  • Coste en recursos y tiempo; pipelines más largos.
  • Si no se mantiene paridad, staging puede dar falsos positivos/negativos.
  • Gestión de datos sensibles exige controles estrictos.

Ejemplo: job simple GitLab CI para Deploy a Staging

deploy_to_staging:
  stage: deploy
  image: alpine/helm:3.12.0
  variables:
    NAMESPACE: staging
  before_script:
    - echo "$KUBE_CONFIG_BASE64" | base64 -d > /tmp/kubeconfig
    - export KUBECONFIG=/tmp/kubeconfig
  script:
    - echo "Verifying image signature"
    - cosign verify --key "$COSIGN_PUBKEY" $REGISTRY/$IMAGE_NAME:${IMAGE_TAG}
    - echo "Deploying to staging"
    - helm upgrade --install myapp ./chart \
        --namespace $NAMESPACE \
        --create-namespace \
        --set image.repository=$REGISTRY/$IMAGE_NAME \
        --set image.tag=${IMAGE_TAG} \
        --wait --timeout 10m
    - echo "Annotate release metadata"
    - kubectl -n $NAMESPACE annotate deployment myapp "ci.commit=${CI_COMMIT_SHA}" --overwrite || true
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release\/.*$/ || $CI_COMMIT_BRANCH == "develop"

Ejemplo completo: Deploy a Staging con E2E, Performance y Aprobación manual

Este ejemplo ejecuta en staging la batería completa de pruebas de aceptación (E2E) y pruebas de rendimiento a escala reducida, automatiza la evaluación de resultados y expone un paso de aprobación manual antes de promover a producción.

El siguiente pipeline hace lo siguiente:

  • Obtiene la imagen firmada del registry y verifica firma y SBOM.
  • Despliega en staging con IaC y Helm/Kustomize usando valores de staging.
  • Ejecuta E2E (Cypress o Newman) contra el entorno staging y publica reportes JUnit/HTML.
  • Ejecuta pruebas de rendimiento con k6 para medir latencia y throughput en escenarios críticos.
  • Evalúa gates automáticos: fallos E2E o umbrales de performance (p. ej. p95 > X ms, error rate > Y%) bloquean la promoción.
  • Publica artefactos y reportes para auditoría y trazabilidad.
  • Si todo OK crea un paso de aprobación manual para promover a producción.
  • Si KO realiza rollback y crea ticket de remediación con evidencia.
stages:
  - staging-deploy
  - staging-validate
  - approval

variables:
  REGISTRY: registry.example.com
  IMAGE_NAME: myapp
  IMAGE_TAG: ${IMAGE_TAG}
  NAMESPACE: staging
  HELM_CHART_PATH: ./chart
  K6_SCRIPT: tests/k6/staging-scenario.js
  CYPRESS_CONFIG: cypress.json

deploy_to_staging:
  stage: staging-deploy
  image: alpine/helm:3.12.0
  before_script:
    - echo "$KUBE_CONFIG_BASE64" | base64 -d > /tmp/kubeconfig
    - export KUBECONFIG=/tmp/kubeconfig
  script:
    - echo "Verify image signature"
    - cosign verify --key "$COSIGN_PUBKEY" $REGISTRY/$IMAGE_NAME:$IMAGE_TAG
    - echo "Deploying to staging"
    - helm upgrade --install myapp $HELM_CHART_PATH \
        --namespace $NAMESPACE \
        --create-namespace \
        --set image.repository=$REGISTRY/$IMAGE_NAME \
        --set image.tag=$IMAGE_TAG \
        --wait --timeout 10m
    - kubectl -n $NAMESPACE annotate deployment myapp "ci.commit=${CI_COMMIT_SHA}" --overwrite || true
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release\/.*$/ || $CI_COMMIT_BRANCH == "develop"

e2e_and_performance:
  stage: staging-validate
  image: node:20-alpine
  needs:
    - job: deploy_to_staging
      artifacts: false
  before_script:
    - apk add --no-cache curl bash jq
    - npm ci
    - echo "$KUBE_CONFIG_BASE64" | base64 -d > /tmp/kubeconfig
    - export KUBECONFIG=/tmp/kubeconfig
  script:
    - echo "Discover service endpoint"
    - SERVICE_HOST=$(kubectl -n $NAMESPACE get svc myapp -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' || kubectl -n $NAMESPACE get svc myapp -o jsonpath='{.spec.clusterIP}')
    - echo "Service host: $SERVICE_HOST"
    # Run E2E with Cypress headless and export JUnit
    - npx cypress run --config-file $CYPRESS_CONFIG --env baseUrl="http://$SERVICE_HOST" --reporter junit --reporter-options "mochaFile=reports/cypress-junit-[hash].xml"
    - |
      if [ $? -ne 0 ]; then
        echo "E2E tests failed" >&2
        exit 10
      fi
    # Run k6 performance scenario
    - apk add --no-cache curl
    - wget -q -O /usr/local/bin/k6 https://github.com/grafana/k6/releases/download/v0.45.0/k6-v0.45.0-linux64 && chmod +x /usr/local/bin/k6
    - k6 run --out json=reports/k6-results.json $K6_SCRIPT || true
    - |
      ERR_RATE=$(jq '[.metrics.iterations.rate] | add' reports/k6-results.json || echo 0)
      P95=$(jq '.metrics["http_req_duration"].p[95]' reports/k6-results.json || echo 0)
      echo "k6 p95: $P95 ms, err_rate: $ERR_RATE"
      if (( $(echo "$P95 > 500" | bc -l) )); then
        echo "Performance threshold exceeded: p95 > 500ms" >&2
        exit 11
      fi
  artifacts:
    when: always
    paths:
      - reports/
    reports:
      junit: reports/cypress-junit-*.xml
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release\/.*$/ || $CI_COMMIT_BRANCH == "develop"

staging_to_prod_approval:
  stage: approval
  image: alpine:3.18
  when: manual
  allow_failure: false
  script:
    - echo "Manual approval to promote to production. Review reports and metrics before approving."
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release\/.*$/ || $CI_COMMIT_BRANCH == "develop"

Notas:

  • E2E usa Cypress en modo headless y exporta JUnit para integración con GitLab Test Reports.
  • Performance usa k6 y guarda resultados JSON; el job evalúa umbrales básicos y falla si se exceden. Ajusta métricas y umbrales a tu SLA.
  • Artifacts: todos los reportes se guardan para auditoría.
  • Approval: el job staging_to_prod_approval es manual; al aprobarlo se puede disparar el job de promoción a producción que use el mismo artefacto firmado.
  • Exit codes diferenciados para distinguir fallos E2E y performance.

IA

  • Mejora: optimiza valores de recursos, sugiere configuraciones de tolerancia, genera tests E2E y scripts de carga, prioriza findings de seguridad y performance.
  • Automatización: puede rellenar plantillas de issue con evidencia, proponer parches y generar PRs de remediación.
  • Limitación: no sustituye la ejecución real ni la aprobación humana en decisiones de riesgo; no puede firmar artefactos ni ejecutar despliegues por sí sola sin integración.

Performance Smoke Tests

Ejecuta pruebas de rendimiento ligeras y deterministas tras un despliegue para validar que los endpoints críticos cumplen requisitos básicos de latencia y estabilidad antes de avanzar a pruebas de carga completas o a producción. Buscan detectar degradaciones evidentes (p95/p99, error rate) que indicarían que el despliegue no es apto para promoción.

Pasos

  • Selección de escenarios críticos: elegir 2–6 rutas o flujos representativos (login, búsqueda, checkout, endpoints de lectura intensiva).
  • Definición de métricas y umbrales: p50/p95/p99, latencia máxima aceptable, tasa de errores máxima, throughput mínimo.
  • Ejecución rápida y controlada: usar herramientas como k6 para escenarios cortos (30s–2min) con carga reducida.
  • Medición y evaluación automática: calcular percentiles y error rate; comparar con umbrales y decidir pasar/fallar.
  • Salida estructurada: exportar resultados en JSON/CSV para ingestión en el pipeline y para adjuntar a reportes.
  • Acciones según resultado: si se exceden umbrales críticos → bloquear promoción, crear ticket y/o rollback; si están dentro de límites → continuar.

Buenas prácticas

  • Mantener tests cortos y deterministas: objetivo < 2–5 minutos para no alargar pipelines.
  • Elegir escenarios de alto impacto en lugar de cubrir todo el API.
  • Ejecutar en staging con paridad de recursos para obtener mediciones representativas.
  • Correlacionar con trazas y métricas para identificar la causa raíz (CPU, GC, latencia de DB).
  • Aislar ruido: ejecutar en ventanas controladas y limpiar datos entre runs.
  • Definir umbrales basados en SLAs y revisarlos periódicamente.
  • Automatizar decisiones: pasar/fallar pipeline según reglas claras; generar reportes y tickets con evidencia.

Ventajas

  • Detección temprana de degradaciones antes de pruebas de carga completas.
  • Bajo coste temporal comparado con pruebas de stress.
  • Automatización fácil en CI/CD para gates rápidos.

Desventajas

  • Cobertura limitada: no sustituye pruebas de carga o stress.
  • Resultados sensibles al entorno: si staging no replica producción, las métricas pueden engañar.
  • Posible flakiness si no se controlan variables externas.

Herramientas

Ejemplos

Ejemplo k6 minimal (tests/k6/perf-smoke.js):

import http from 'k6/http';
import { check } from 'k6';
export let options = { vus: 10, duration: '1m' };
export default function () {
  let res = http.get(`${__ENV.BASE_URL}/api/v1/critical`);
  check(res, { 'status 200': (r) => r.status === 200 });
}

Evaluación simple (bash):

k6 run --out json=perf.json tests/k6/perf-smoke.js
P95=$(jq '.metrics.http_req_duration.p[95]' perf.json)
if (( $(echo "$P95 > 500" | bc -l) )); then exit 1; fi

GitLab CI job:

performance_smoke:
  stage: validate
  image: loadimpact/k6:latest
  variables:
    BASE_URL: "http://myapp-staging.example.com"
    K6_SCRIPT: tests/k6/perf-smoke.js
  script:
    - k6 run --out json=perf.json $K6_SCRIPT
    - P95=$(jq '.metrics.http_req_duration.p[95]' perf.json)
    - ERR_RATE=$(jq '.metrics.http_req_failed.rate' perf.json)
    - echo "p95=$P95 ms err_rate=$ERR_RATE"
    - |
      if (( $(echo "$P95 > 500" | bc -l) )) || (( $(echo "$ERR_RATE > 0.01" | bc -l) )); then
        echo "Performance smoke failed: p95 or error rate exceeded" >&2
        exit 1
      fi
  artifacts:
    when: always
    paths:
      - perf.json
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release\/.*$/ || $CI_COMMIT_BRANCH == "develop"

IA

  • Mejora: la IA puede sugerir escenarios críticos a partir de logs y telemetría histórica, proponer umbrales realistas y generar scripts k6 automáticamente.
  • Diagnóstico: al fallar un test, correlacionar métricas, agrupar anomalías y proponer la causa raíz (latencia de DB, saturación de CPU).
  • Automatización: generar tickets con resumen ejecutivo, evidencia y recomendaciones; proponer PRs con ajustes de configuración (timeouts, pool sizes).
  • Limitación: la IA no sustituye la ejecución real ni la validación humana de cambios de arquitectura.

En el siguiente artículo, “CD — Parte 5: LCA — Load, Stress y Chaos Engineering”, entraremos en la validación de resiliencia real: pruebas de carga, estrés y caos para asegurar que el sistema se mantiene estable y recuperable bajo condiciones extremas.

Comparte esta entrada en:
Safe Creative #1401310112503
CD (Entrega Continua) — Parte 4: Deploy a Staging y Performance Smoke Tests por "www.jarroba.com" esta bajo una licencia Creative Commons
Reconocimiento-NoComercial-CompartirIgual 3.0 Unported License.
Creado a partir de la obra en www.jarroba.com

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies

ACEPTAR
Aviso de cookies