Blog de Amazon Web Services (AWS)

Integrar pruebas de resiliencia en el pipeline de CI/CD con AWS Step Functions

Por Oriol Matavacas, Sr. Solutions Architect en AWS.

Nivel: 300 – DevOps, SRE y equipos de plataforma. Serverless

Introducción

En la primera parte de esta serie, se presentó una máquina de estados de AWS Step Functions que orquesta pruebas de resiliencia progresivas para un servicio de Amazon ECS sobre AWS Fargate – sin código intermedio. La máquina descubre la topología del servicio, genera escenarios con Amazon Bedrock, los ejecuta con AWS FIS y emite un veredicto determinista (PASS o FAIL).

En esta segunda parte, aprenderá cómo convertir ese veredicto en una puerta de calidad dentro de su pipeline de CI/CD, cómo depurar ejecuciones fallidas y cómo asegurar la solución en producción.

Integración como puerta de CI/CD

Una prueba de resiliencia se convierte en puerta de calidad cuando su pipeline puede lanzarla y obtener una respuesta clara: pasa o no pasa. La propia máquina de estados proporciona esta interpretación determinista: si el veredicto es aceptable, la ejecución termina con éxito; si no lo es, la ejecución falla y la puerta se cierra. Su pipeline inicia la ejecución, espera a que termine y comprueba el estado final.

Flujo de invocación

Para invocar la validación desde un pipeline:

  1. Llamar a la API StartExecution con la entrada en JSON.
  2. Sondear con DescribeExecution hasta que el estado deje de ser RUNNING (una ejecución típica tarda entre 5 y 15 minutos, según la duración de los escenarios y los tiempos de recuperación).
  3. Comprobar el estado final: si es SUCCEEDED, la validación pasó. Si es FAILED, la puerta bloquea el despliegue.

Este patrón funciona con cualquier orquestador de CI/CD: AWS CodePipeline (con su acción nativa de Step Functions), GitHub Actions, GitLab CI, Bitbucket Pipelines o Jenkins.

Ejemplo con GitHub Actions

El siguiente flujo de trabajo muestra la integración completa:

name: puerta-de-resiliencia
on:
  workflow_dispatch:

jobs:
  fis-gate:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Configurar credenciales de AWS
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::111122223333:role/GitHubActionsResilienceGate
          aws-region: eu-west-1

      - name: Iniciar la validación de resiliencia
        id: start
        run: |
          EXEC_ARN=$(aws stepfunctions start-execution \
            --state-machine-arn "arn:aws:states:eu-west-1:111122223333:stateMachine:ecs-ha-progressive" \
            --input file://example-input.json \
            --query executionArn --output text)
          echo "exec_arn=$EXEC_ARN" >> "$GITHUB_OUTPUT"

      - name: Esperar el resultado y aplicar la puerta
        run: |
          EXEC_ARN="${{ steps.start.outputs.exec_arn }}"
          while [ "$(aws stepfunctions describe-execution \
                --execution-arn "$EXEC_ARN" --query status --output text)" = "RUNNING" ]; do
            sleep 30
          done
          STATUS=$(aws stepfunctions describe-execution \
            --execution-arn "$EXEC_ARN" --query status --output text)
          if [ "$STATUS" != "SUCCEEDED" ]; then
            echo "La puerta de resiliencia ha bloqueado el despliegue (estado: $STATUS)."
            exit 1
          fi
          aws stepfunctions describe-execution \
            --execution-arn "$EXEC_ARN" --query output --output text \
            | jq -r '"haScore=\(.evaluation.haScore), verdict=\(.evaluation.verdict)"'

      - name: Eliminar las plantillas de experimento de AWS FIS
        if: always()
        run: |
          aws fis list-experiment-templates \
            --query "experimentTemplates[?tags.Project=='FIS_SF' && tags.AutoGenerated=='true'].id" \
            --output text | tr '\t' '\n' | while read -r TID; do
            [ -n "$TID" ] && aws fis delete-experiment-template --id "$TID"
          done

Nota: Es necesario reemplazar 111122223333 con el ID de cuenta de AWS correspondiente. El archivo example-input.json contiene la configuración de su servicio (clúster, servicio, ARN del modelo de Amazon Bedrock y ARN de la alarma de parada). Consulte el repositorio para ver la estructura completa del archivo de entrada.

Detalles del flujo:

  • Paso 1: Asume un rol de IAM mediante OpenID Connect (OIDC), sin claves de larga duración. Consulte la documentación de GitHub Actions para OIDC con AWS.
  • Paso 2: Inicia la ejecución y guarda su ARN.
  • Paso 3: Sondea hasta que la ejecución termine. Si el estado final no es SUCCEEDED, el paso devuelve código de salida 1 y el pipeline se detiene.
  • Paso 4: Se ejecuta siempre (incluso si la puerta bloquea el despliegue). Localiza las plantillas de experimento por etiquetas Project y AutoGenerated y las elimina para que no se acumulen entre ejecuciones.

Integración con AWS CodePipeline

Con AWS CodePipeline, se puede usar la acción de invocación de AWS Step Functions. Para una máquina de estados de tipo Standard, la acción espera a que la ejecución termine y refleja su resultado directamente en la etapa del pipeline.

Para una guía paso a paso de esta integración, consulte el tutorial Uso de una acción de invocación de AWS Step Functions en una canalización en la documentación de AWS CodePipeline.

Ajuste del umbral

El umbral de aprobación está definido en el estado EvaluateVerdict de la máquina de estados. El veredicto es PASS cuando haScore alcanza 70. Para aumentar la exigencia en servicios críticos, se puede subir ese valor en la definición del estado. No es necesario modificar el pipeline.

Depuración

La consola dibuja el grafo de la ejecución y colorea cada estado según su resultado, así que puede distinguir de un vistazo si la parada ocurrió en ValidatePrerequisites, en ValidateGuardrails o en un nivel concreto del Map. Al seleccionar un estado, ve su entrada, su salida y las variables asignadas en ese punto (Figura 7). El historial completo de la ejecución se expone además como una secuencia de eventos estructurados (JSON), no como texto libre, lo que permite que herramientas de análisis, incluidas las basadas en IA, lean el historial y expliquen el fallo o sugieran correcciones.

Para rastrear un fallo concreto, habría que identificar el paso rojo en el pipeline de CI/CD, abrir la ejecución fallida de AWS Step Functions y leer la causa del estado Fail, que resume el veredicto. El grafo señala directamente el nivel del Map que no superó la prueba y el estado exacto donde el experimento se detuvo o falló.

Detalle de un estado en la consola de AWS Step Functions

Figura 7: Detalle de un estado en la consola de AWS Step Functions.

Salida de evaluación

La salida de la ejecución incluye información detallada del veredicto, accesible tanto desde la consola de AWS Step Functions (pestaña «Output» de la ejecución) como mediante la API DescribeExecution (campo output). La estructura es la siguiente:

  • evaluation.haScore – Puntuación de alta disponibilidad (0-100). Un valor de 70 o superior produce un veredicto PASS con la configuración por defecto.
  • evaluation.verdict – Veredicto final: PASS o FAIL. Determina si la ejecución de la máquina de estados termina con éxito o falla.
  • evaluation.riskLevel – Nivel de riesgo identificado por Amazon Bedrock: LOW, MEDIUM, HIGH o CRITICAL. Refleja la severidad global de los problemas encontrados.
  • evaluation.recoveryAnalysis – Análisis textual de la recuperación del servicio tras cada escenario. Incluye tiempos observados y comportamiento del balanceador.
  • evaluation.recommendations – Lista de recomendaciones accionables generadas por Amazon Bedrock (por ejemplo, «Aumentar el número mínimo de tareas a 3» o «Distribuir tareas en una tercera zona de disponibilidad»).
  • levelResults – Array con el detalle de cada nivel ejecutado. Cada elemento incluye level, actionId, status (PASS, FAIL o STOPPED), experimentId y las métricas posteriores al experimento (postMetrics).

A continuación se muestra un ejemplo parcial de la salida cuando la validación es exitosa:

{
  "evaluation": {
    "haScore": 85,
    "verdict": "PASS",
    "riskLevel": "LOW",
    "recoveryAnalysis": "El servicio recuperó la capacidad completa en menos de 45 segundos tras la detención del 50% de las tareas. La interrupción de conectividad en una subred no produjo errores 5xx gracias al redireccionamiento del balanceador.",
    "recommendations": [
      "Considerar distribuir tareas en una tercera zona de disponibilidad para mejorar la tolerancia a fallos zonales.",
      "Configurar una política de escalado que responda al aumento de latencia durante la recuperación."
    ]
  },
  "levelResults": [
    { "level": 1, "actionId": "aws:ecs:stop-task", "status": "PASS" },
    { "level": 2, "actionId": "aws:network:disrupt-connectivity", "status": "PASS" },
    { "level": 3, "actionId": "aws:ecs:stop-task", "status": "PASS" }
  ]
}

Cuando el veredicto no es PASS, la ejecución termina en el estado ValidationFailed y la causa incluye haScore, verdict y riskLevel, lo que permite al pipeline identificar rápidamente la razón del bloqueo.

Recuperación del servicio en la consola de Amazon ECS

Figura 8: Recuperación del servicio en la consola de Amazon ECS.

Rol de las alarmas de Amazon CloudWatch

Las alarmas de Amazon CloudWatch cumplen un doble papel en esta solución:

  1. Métricas de referencia: Alimentan las métricas previas y posteriores a cada experimento, para comparar el estado antes y después de la inyección.
  2. Condición de parada: Si la alarma indicada en la entrada entra en estado ALARM durante la inyección, AWS FIS detiene el experimento automáticamente. El nivel se marca como STOPPED y la razón queda registrada en experimentReason. La Figura 8 muestra un ejemplo de la recuperación del servicio en la consola de Amazon ECS, donde se observan las tareas detenidas y las nuevas tareas que el servicio inicia automáticamente.

Consideraciones de seguridad

Tenga en cuenta las siguientes prácticas de seguridad al implementar esta solución:

  • Principio de mínimo privilegio: Los roles de IAM de la máquina de estados y del experimento de AWS FIS deben tener solo los permisos necesarios. No se deberían usar políticas de acceso amplio como AdministratorAccess.
  • Protección contra invocaciones no autorizadas: Se debería limitar quién puede invocar StartExecution en la máquina de estados mediante políticas de IAM basadas en recurso o condiciones de etiquetas.
  • Barrera de seguridad para el modelo: La lista de acciones permitidas actúa como capa de protección contra comportamientos inesperados del modelo. Se recomienda revisar y actualizar periódicamente esta lista.
  • Modelo de Amazon Bedrock fijo: Es recomendable usar un ARN de modelo con versión específica para evitar cambios de comportamiento por actualizaciones del modelo.
  • Condición de parada obligatoria: Es imprescindible configurar una alarma de Amazon CloudWatch como condición de parada del experimento. Esto limita el impacto si un experimento causa degradación inesperada.
  • Ejecuciones concurrentes: Si la validación se ejecuta contra el mismo servicio en paralelo, los experimentos pueden interferir entre sí. Lo recomendable es usar una ejecución a la vez por servicio o configurar nombres de ejecución que eviten la concurrencia.

Permisos IAM mínimos

La máquina de estados necesita un rol de ejecución con los siguientes permisos (adaptando los ARN a la cuenta y región correspondientes):

  • ecs:DescribeServices, ecs:ListTasks, ecs:DescribeTasks, ecs:DescribeTaskDefinition – sobre el clúster y servicio de destino. Permiten a la fase de descubrimiento consultar la configuración real del servicio: recuento de tareas, distribución entre zonas y definición de tarea.
  • elasticloadbalancing:DescribeTargetHealth – sobre el grupo de destino del ALB. Permite consultar el estado de los destinos registrados en el Application Load Balancer para establecer la línea base de salud.
  • cloudwatch:GetMetricData – sobre las métricas del servicio. Permite recopilar métricas de referencia antes y después de cada experimento (por ejemplo, HealthyHostCount y HTTPCode_Target_5XX_Count).
  • fis:ListActions, fis:CreateExperimentTemplate, fis:StartExperiment, fis:GetExperiment, fis:DeleteExperimentTemplate – sobre los recursos de AWS FIS. Permiten descubrir las acciones disponibles, crear y ejecutar las plantillas de experimento, sondear su estado y limpiar las plantillas autogeneradas al finalizar.
  • bedrock:InvokeModel – sobre el modelo de Amazon Bedrock especificado. Permite invocar el modelo de Amazon Bedrock para generar los escenarios progresivos y para evaluar los resultados al final de la prueba.
  • iam:PassRole condicionado a fis.amazonaws.com. Permite a la máquina de estados pasar el rol del experimento a AWS FIS al crear cada plantilla.

El rol de experimento de AWS FIS necesita:

  • ecs:StopTask – sobre las tareas del servicio de destino. Permite a AWS FIS detener tareas individuales durante la acción aws:ecs:stop-task, simulando la pérdida de una instancia.
  • ec2:CreateNetworkAcl*, ec2:ReplaceNetworkAclAssociation – para la acción aws:network:disrupt-connectivity.

Nota: Consulte la documentación de roles de IAM para AWS Step Functions y la documentación de roles de experimento de AWS FIS para ejemplos de políticas detalladas. Para las integraciones con el SDK de AWS, hay que tener en cuenta que Step Functions no genera políticas IAM automáticamente; la guía de permisos para SDK integrations describe cómo construir la política manualmente.

Solución de problemas

La siguiente tabla recoge los síntomas más frecuentes, su causa probable y la acción recomendada para resolverlos:

Síntoma Causa probable Solución
La ejecución se detiene en PrerequisiteFailed El servicio no cumple los requisitos de inyección Verificar que enableFaultInjection es true, que pidMode es task, que hay ≥2 tareas y ≥2 zonas de disponibilidad.
La ejecución se detiene en GuardrailViolation Amazon Bedrock propuso acciones fuera de la lista permitida Revisar los escenarios propuestos en la salida del estado GenerateScenarios. Ampliar la lista de acciones permitidas si las acciones son seguras para su entorno.
El experimento queda en estado initiating indefinidamente El rol de AWS FIS no tiene permisos suficientes Verificar que el rol del experimento tiene permisos sobre las tareas de Amazon ECS y las subredes de destino.
Amazon Bedrock devuelve un error de validación El payload excede el límite del modelo o el formato del prompt es incorrecto Revisar el tamaño de la entrada. Reducir el número de tareas descubiertas si el payload supera 256 KB.
El experimento se marca como STOPPED La alarma de Amazon CloudWatch entró en estado ALARM durante la inyección Revisar la métrica de la alarma. Si el umbral es demasiado sensible, ajustar la alarma. Si la degradación fue real, investigar la resiliencia del servicio.
El estado CheckExperimentStatus devuelve un error de throttling Demasiadas llamadas a GetExperiment en poco tiempo Aumentar el intervalo del estado Wait de 30 a 60 segundos.

Ampliaciones

El flujo descrito cubre el caso base y deja varios puntos de extensión:

  • Ejecución programada: Se puede usar Amazon EventBridge Scheduler para invocar StartExecution según una expresión cron. Esto proporciona una validación periódica (nocturna o semanal) además de la puerta en cada release. La documentación Inicio de una ejecución con Amazon EventBridge Scheduler detalla la configuración.
  • Notificaciones: La entrada ya admite el ARN de un tema de Amazon SNS. Es posible añadir un estado final con arn:aws:states:::aws-sdk:sns:publish para notificar al equipo del veredicto.
  • Persistencia de resultados: Los resultados se pueden escribir en un bucket Amazon S3 con arn:aws:states:::aws-sdk:s3:putObject, o envíelos a un sistema externo con la tarea HTTP de AWS Step Functions (arn:aws:states:::http:invoke) sobre una conexión de Amazon EventBridge. Workflow Studio, el editor visual de AWS Step Functions, facilita añadir este tipo de integraciones sin editar el JSON directamente (Figura 9).
  • Ampliar acciones de inyección: A medida que el equipo gane confianza, la lista de acciones permitidas puede ampliarse para incluir experimentos que actúan dentro del contenedor (estrés de CPU, latencia de red).
Configuración de la tarea HTTP en Workflow Studio de AWS Step Functions

Figura 9: Configuración de la tarea HTTP en Workflow Studio de AWS Step Functions.

Limpieza

El paso 4 del flujo de GitHub Actions elimina automáticamente las plantillas de experimento autogeneradas tras cada ejecución. Si se configura la integración con AWS CodePipeline, es recomendable añadir un paso equivalente de limpieza al final de la etapa.

Para una limpieza completa de todos los recursos de la solución (máquina de estados, roles de IAM, alarma de Amazon CloudWatch y configuración de inyección de fallos), consulte la sección de limpieza en la primera parte de esta serie.

Siguientes pasos

Una vez validada la integración básica, los siguientes pasos permiten consolidar la solución y ampliar su alcance:

  1. Conectar el primer pipeline: Copiar el flujo de GitHub Actions de esta publicación en su repositorio y configurarlo con los ARN de su cuenta.
  2. Automatizar la ejecución post-deploy: Usar Amazon EventBridge Scheduler o una regla de EventBridge que detecte ECS Service Steady State para disparar la validación automáticamente tras cada despliegue.
  3. Ajustar el umbral por servicio: Establecer un haScore acorde a la criticidad de cada servicio en el estado EvaluateVerdict.
  4. Habilitar notificaciones: Añadir un estado final con arn:aws:states:::aws-sdk:sns:publish para alertar al equipo cuando la puerta bloquee un despliegue.
  5. Actuar sobre las recomendaciones: Revisar evaluation.recommendations en la salida de la ejecución y convertirlas en tareas de mejora.

Conclusión

En esta publicación, aprendió cómo convertir el veredicto de la máquina de estados en una puerta de calidad para su pipeline de CI/CD. El patrón funciona con GitHub Actions, AWS CodePipeline o cualquier orquestador que pueda invocar StartExecution y comprobar el resultado con DescribeExecution. Las herramientas de observabilidad de AWS Step Functions – el grafo coloreado, el historial de eventos estructurado y la salida de evaluación con haScore, verdict y recommendations – permiten depurar ejecuciones fallidas en segundos, no en horas.

Recursos adicionales


Autor

Oriol Matavacas Rodriguez Oriol Matavacas Rodriguez es Senior Solutions Architect en AWS. Ayuda a organizaciones en la adopción estratégica de servicios de AWS, con experiencia en arquitecturas serverless, migración y DevOps.