AWS Step Functions中Fargate任务容器运行时错误未触发流水线失败排查
这个问题其实不是AWS的Bug,而是ecs:runTask.sync集成的默认设计逻辑导致的——我来帮你拆解清楚:
为什么Step Functions没捕获到容器失败?
Step Functions的arn:aws:states:::ecs:runTask.sync默认只关注ECS任务的整体生命周期状态:只要任务能成功启动、最终进入STOPPED状态(不管容器是正常退出还是报错退出),Step Functions就会标记该任务为成功。只有当任务无法启动(比如任务定义不存在、资源不足)或者被强制终止时,才会触发Step Functions的失败流程。
你的Python代码抛出异常导致容器退出码非零,但ECS任务本身只是正常停止(因为essential容器退出后任务就会停止),所以Step Functions认为整个任务执行完成,继续走后续流程。
两种解决方法
方法一:检查容器退出码(最直接)
修改你的Step Functions定义,在Fargate任务执行后添加一个Choice状态,显式检查容器的退出码。如果退出码非零,直接进入Fail状态;否则继续到Done。
修改后的状态机定义如下:
{ "Comment": "My state machine", "StartAt": "MyFargateTask", "States": { "MyFargateTask": { "Type": "Task", "Resource": "arn:aws:states:::ecs:runTask.sync", "InputPath": "$", "Parameters": { "Cluster": "my-cluster", "TaskDefinition": "arn:aws:ecs:us-east-1:617090640476:task-definition/my-task:1", "LaunchType": "FARGATE", "NetworkConfiguration": { "AwsvpcConfiguration": { "Subnets": [ "subnet-xxxxxxxxxxxxxxxxx", "subnet-yyyyyyyyyyyyyyyyy" ], "AssignPublicIp": "ENABLED" } } }, "ResultPath": "$.ecsResult", "Next": "CheckContainerStatus" }, "CheckContainerStatus": { "Type": "Choice", "Choices": [ { "Variable": "$.ecsResult.containers[0].exitCode", "NumericEquals": 0, "Next": "Done" } ], "Default": "TaskFailed" }, "TaskFailed": { "Type": "Fail", "Error": "ContainerNonZeroExit", "Cause": "Container exited with non-zero exit code." }, "Done": { "Type": "Succeed" } } }
注意点:
- 用
ResultPath保留ECS任务的执行结果,方便后续检查 - 如果你的任务包含多个容器,需要调整
containers[0]的索引,指向运行Python代码的容器 - 确保你的容器在ECS任务定义中是
essential: true(默认就是true,无需额外配置),这样容器退出时整个任务会停止
方法二:利用ECS任务停止原因(可选)
如果你的容器是essential容器,当它以非零码退出时,ECS任务的stopReason会包含Essential container in task exited。你也可以在Choice状态中检查这个字段,来判定任务是否失败,逻辑和方法一类似,只是检查的变量换成$.ecsResult.stopReason。
总结
这是正常的设计行为,不是Bug——Step Functions的ECS同步任务默认不感知容器内部的应用错误,需要你显式添加检查逻辑来捕获这类失败场景。
内容的提问来源于stack exchange,提问作者revy

