AWS Step Functions 和 Fargate 任务:容器运行时错误不会导致管道失败
AWS Step Functions and Fargate task: container runtime error does not cause pipeline to fail
我在 AWS Step Functions. One step is defined as Fargate Task, which pulls a docker image and run some python code. I've surprisingly found that if the container running in the Fargate task encounters a runtime error the Step Functions doesn't catch the failed task and continue the pipeline as normal (setting the Fargate task as successful), but according to the documentation 中定义了一个管道,一旦发生这种情况管道就会失败。
这是阶跃函数定义:
{
"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"
}
},
},
"Next": "Done"
},
"Done": {
"Type": "Succeed"
}
}
}
我已经为 Fargate 容器尝试了以下简单的 python 代码:
def main():
raise Exception("foobar")
if __name__ == '__main__':
main()
在 CloudWatch 的容器日志中,我可以看到程序按预期失败,但 Step Function 中的管道成功(全绿色)。
我错过了什么?这是一个错误吗?
AWS Step Functions 不知道 ECS 作业是成功还是失败。 Step Functions 需要查看 ECS 作业的容器日志,并尝试确定 Docker 容器内的进程 运行 是否退出并显示故障代码。这不是 Step Functions 所做的事情。正如您所配置的那样,Step Functions 只是假设只要容器存在,任务就会成功。
如果您将 arn:aws:states:::ecs:runTask.sync
更改为 arn:aws:states:::ecs:runTask.waitForTaskToken
,那么 Step Fuctions 将等待 ECS 容器将成功或失败代码发送回 Step 而不是等待 ECS 容器退出函数 API。您还需要将任务令牌传递到 ECS 容器中,这可以通过 ContainerOverrides
设置来完成,如下所示:
{
"Comment": "My state machine",
"StartAt": "MyFargateTask",
"States": {
"MyFargateTask": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.waitForTaskToken",
"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"
}
},
"Overrides": {
"ContainerOverrides": [{
"Environment": [{
"Name": "TASK_TOKEN",
"Value.$": "$$.Task.Token"
}]
}]
}
},
"Next": "Done"
},
"Done": {
"Type": "Succeed"
}
}
}
现在,在您的 Python 脚本中,您可以获取 TASK_TOKEN
环境变量,并将成功或失败消息发回 Step Functions,如下所示:
token = os.environ['TASK_TOKEN']
def step_success():
if token is not None:
stfn = boto3.client('stepfunctions')
stfn.send_task_success(taskToken=token, output='{"Status": "Success"}')
def step_fail():
if token is not None:
stfn = boto3.client('stepfunctions')
stfn.send_task_failure(taskToken=token, error="An error occurred")
我还建议在状态机中配置一个超时,以防您的 Python 脚本无法在容器或其他东西中执行。此外,您还需要向 Fargate 任务的 IAM 角色添加适当的 IAM 权限,以允许它向 Step Functions API.
发出这些状态调用。
我认为使用 arn:aws:states:::ecs:runTask.sync 将使您的 stepfunction 失败,因为 ECS 将显示容器状态已停止和详细消息作为“任务中的基本容器已退出”
如果您使用 arn:aws:states:::ecs:runTask(没有 .syn)stepfunction 将不会理会 ECS 并且会导致成功。
鉴于您的情况,您应该使用 arn:aws:states:::ecs:runTask.waitForTaskToken 并发送 sendTaskSuccess 或 sendTaskFailure 以及来自 StepFunction[=10 的提供令牌=]
我在 AWS Step Functions. One step is defined as Fargate Task, which pulls a docker image and run some python code. I've surprisingly found that if the container running in the Fargate task encounters a runtime error the Step Functions doesn't catch the failed task and continue the pipeline as normal (setting the Fargate task as successful), but according to the documentation 中定义了一个管道,一旦发生这种情况管道就会失败。
这是阶跃函数定义:
{
"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"
}
},
},
"Next": "Done"
},
"Done": {
"Type": "Succeed"
}
}
}
我已经为 Fargate 容器尝试了以下简单的 python 代码:
def main():
raise Exception("foobar")
if __name__ == '__main__':
main()
在 CloudWatch 的容器日志中,我可以看到程序按预期失败,但 Step Function 中的管道成功(全绿色)。 我错过了什么?这是一个错误吗?
AWS Step Functions 不知道 ECS 作业是成功还是失败。 Step Functions 需要查看 ECS 作业的容器日志,并尝试确定 Docker 容器内的进程 运行 是否退出并显示故障代码。这不是 Step Functions 所做的事情。正如您所配置的那样,Step Functions 只是假设只要容器存在,任务就会成功。
如果您将 arn:aws:states:::ecs:runTask.sync
更改为 arn:aws:states:::ecs:runTask.waitForTaskToken
,那么 Step Fuctions 将等待 ECS 容器将成功或失败代码发送回 Step 而不是等待 ECS 容器退出函数 API。您还需要将任务令牌传递到 ECS 容器中,这可以通过 ContainerOverrides
设置来完成,如下所示:
{
"Comment": "My state machine",
"StartAt": "MyFargateTask",
"States": {
"MyFargateTask": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.waitForTaskToken",
"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"
}
},
"Overrides": {
"ContainerOverrides": [{
"Environment": [{
"Name": "TASK_TOKEN",
"Value.$": "$$.Task.Token"
}]
}]
}
},
"Next": "Done"
},
"Done": {
"Type": "Succeed"
}
}
}
现在,在您的 Python 脚本中,您可以获取 TASK_TOKEN
环境变量,并将成功或失败消息发回 Step Functions,如下所示:
token = os.environ['TASK_TOKEN']
def step_success():
if token is not None:
stfn = boto3.client('stepfunctions')
stfn.send_task_success(taskToken=token, output='{"Status": "Success"}')
def step_fail():
if token is not None:
stfn = boto3.client('stepfunctions')
stfn.send_task_failure(taskToken=token, error="An error occurred")
我还建议在状态机中配置一个超时,以防您的 Python 脚本无法在容器或其他东西中执行。此外,您还需要向 Fargate 任务的 IAM 角色添加适当的 IAM 权限,以允许它向 Step Functions API.
发出这些状态调用。我认为使用 arn:aws:states:::ecs:runTask.sync 将使您的 stepfunction 失败,因为 ECS 将显示容器状态已停止和详细消息作为“任务中的基本容器已退出”
如果您使用 arn:aws:states:::ecs:runTask(没有 .syn)stepfunction 将不会理会 ECS 并且会导致成功。
鉴于您的情况,您应该使用 arn:aws:states:::ecs:runTask.waitForTaskToken 并发送 sendTaskSuccess 或 sendTaskFailure 以及来自 StepFunction[=10 的提供令牌=]