【问题标题】:AWS Step Functions and Fargate task: container runtime error does not cause pipeline to failAWS Step Functions 和 Fargate 任务:容器运行时错误不会导致管道失败
【发布时间】:2020-12-28 02:15:14
【问题描述】:

我在AWS Step Functions 中定义了一个管道。一个步骤定义为Fargate Task,它会拉取一个 docker 映像并运行一些 python 代码。我惊讶地发现,如果在 Fargate 任务中运行的容器遇到运行时错误,Step Functions 不会捕获失败的任务并正常继续管道(将 Fargate 任务设置为成功),但根据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 中的管道成功(全为绿色)。 我错过了什么?这是一个错误吗?

【问题讨论】:

  • 容器的命令是什么?你是显式调用那个 python 文件,还是有一个包装脚本?
  • CMD python index.py

标签: amazon-web-services debugging aws-fargate aws-step-functions


【解决方案1】:

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 Functions API,而不是等待 ECS 容器退出。您还需要将任务令牌传递到 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。

【讨论】:

  • 非常感谢,我会试试这个方法!
【解决方案2】:

我认为使用 arn:aws:states:::ecs:runTask.sync 会使您的 stepfunction 失败,因为 ECS 将显示容器状态已停止,详细消息为“任务中的基本容器已退出"

如果您使用 arn:aws:states:::ecs:runTask(不带 .syn)stepfunction 将不会打扰 ECS,会导致成功。

根据您的情况,您应该使用 arn:aws:states:::ecs:runTask.waitForTaskToken 并使用 StepFunction 提供的令牌发送 sendTaskSuccess 或 sendTaskFailure

【讨论】:

    猜你喜欢
    • 2021-11-16
    • 1970-01-01
    • 2021-09-28
    • 2021-11-15
    • 2018-08-28
    • 1970-01-01
    • 2019-09-25
    • 1970-01-01
    • 2020-09-05
    相关资源
    最近更新 更多