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")

More details on this approach

我还建议在状态机中配置一个超时,以防您的 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 的提供令牌=]