如何等待 AWS ECS 任务处于 RUNNING 状态,然后再转到 AWS Step Function 中的下一步?

问题描述 投票:0回答:3

我有一个对象数组,我想将其迭代传递给 Lambda 函数。但是,我还需要为我启动的每个 Lambda 函数运行一个 ECS 任务。

我发现我需要一个 AWS Step Function,在其中迭代 JSON 输入数组。对于每个输入,我必须启动一个 ECS 任务,等待它处于 RUNNING 状态,然后转到下一步,调用 Lambda 函数。就我而言,ECS 任务本身不返回任何内容。它应该保持运行,因为 Lambda 函数使用它。

目前,我拥有它,以便 ECS 任务启动,但它停留在启动 ECS 任务步骤,因为它不返回任何内容。在进行下一步之前,我如何才能等待它处于 RUNNING 状态?

当前阶跃函数定义:

{
  "StartAt": "Iterate",
  "States": {
    "Iterate": {
      "Type": "Map",
      "Iterator": {
        "StartAt": "Start ECS Task",
        "States": {
          "Start ECS Task": {
            "Type": "Task",
            "Resource": "arn:aws:states:::ecs:runTask",
            "Parameters": {
              "LaunchType": "FARGATE",
              "Cluster": "<cluster-arn>",
              "TaskDefinition": "<task-definition-arn>",
              "NetworkConfiguration": {
                "AwsvpcConfiguration": {
                  "Subnets": [
                    "<subnet-id>"
                  ],
                  "AssignPublicIp": "ENABLED"
                }
              }
            },
            "Next": "Invoke Lambda function"
          },
          "Invoke Lambda function": {
            "Type": "Task",
            "Resource": "arn:aws:states:::lambda:invoke",
            "Parameters": {
              "FunctionName": "<lambda-function-arn>",
              "Payload": {
                "Input.$": "$"
              }
            },
            "End": true
          }
        }
      },
      "End": true
    }
  }
}
amazon-web-services aws-lambda amazon-ecs aws-step-functions
3个回答
4
投票

我没有使用集成的 AWS 服务(即 AWS Step Function),而是使用 JavaScript 的

aws-sdk
v3 创建了自己的脚本来启动 ECS 任务。我专门使用了
waitUntilTasksRunning
包中的
@aws-sdk/client-ecs
函数来等待 ECS 任务处于 RUNNING 状态。

从文档中了解更多信息

用于运行并等待 ECS 任务处于 RUNNING 状态的示例函数(TypeScript)注意:并非函数中的所有参数都是必需的,请检查文档:

import { ECSClient, RunTaskCommand, waitUntilTasksRunning } from '@aws-sdk/client-ecs'

const startAndWaitUntilECSTaskRunning = async (region: string, clusterARN: string, launchType: string, subnets: Array<string>, taskDefinition: string, securityGroups: Array<string>, assignPublicIp: string) => {
    var ecsClient = new ECSClient({ "region": region })
    var runTaskCommand = new RunTaskCommand({
        cluster: clusterARN,
        taskDefinition: taskDefinition,
        launchType: launchType,
        networkConfiguration: {
            awsvpcConfiguration: {
                assignPublicIp: assignPublicIp,
                subnets: subnets,
                securityGroups: securityGroups
            }
        }
    })
    var ecsTask = await ecsClient.send(runTaskCommand)
    var taskArn: string | undefined = ecsTask.tasks?.[0].taskArn
    if (typeof taskArn !== "string") {
        throw Error("Task ARN is not defined.")
    }
    var waitECSTask = await waitUntilTasksRunning({"client": ecsClient, "maxWaitTime": 600, "maxDelay": 1, "minDelay": 1}, {"cluster": clusterARN, "tasks": [taskArn]})
    // note: there are multiple waitECSTask states, check the documentation for more about that
    if (waitECSTask.state !== 'SUCCESS') {
        // your code to handle this
    } else {
        // your code to handle this
    }
}

3
投票

ecs:runTask 可以通过两种不同的方式触发。

  • arn:aws:states:::ecs:runTask.sync > 运行并等待任务完成
  • arn:aws:states:::ecs:runTask.waitForTaskToken - 触发并等待,直到收到 SendTaskSucess 或 sendTaskFailure

这种情况我们需要使用第二种方法,

将 TASK_TOKEN 作为环境变量传递给 ECS 任务,在 ECS 任务的前几行代码中,我们需要发送 SendTaskSucess。

这是一个例子:

{
   "StartAt":"Run",
   "States":{
      "Run":{
         "End":true,
         "Type":"Task",
         "Resource":"arn:aws:states:::ecs:runTask.waitForTaskToken",
         "Parameters":{
            "Cluster":"arn:aws:ecs:us-east-1:620018741331:cluster/HelloCdkStack-ecstaskEc2ClusterB0EAAA1E-yPWjSYf8d03O",
            "TaskDefinition":"HelloCdkStackecstaskTD1950FF01",
            "Overrides":{
               "ContainerOverrides":[
                  {
                     "Name":"TheContainer",
                     "Environment":[
                        {
                           "Name":"TASK_TOKEN",
                           "Value.$":"$$.Task.Token"
                        }
                     ]
                  }
               ]
            },
            "LaunchType":"EC2"
         }
      }
   }
}

0
投票

AWS CLI 有一个方便的

aws ecs wait tasks-running
命令。一些 AWS 开发工具包提供类似的操作。此命令的文档指出:

等到使用

describe-tasks
轮询时,JMESPath 查询tasks[].lastStatus 对所有元素返回 RUNNING。它将每 6 秒轮询一次,直到达到成功状态。在 100 次失败检查后,这将退出并返回代码 255

换句话说,“等待”操作只是构建在 ECSDescribeTasks API 操作之上的简单轮询行为。

您可以在 AWS Step Function 中本地实现相同的轮询行为。 等待状态,然后是AWS SDK集成状态以调用ECSDescribeTasks操作,然后是选择状态以评估

lastStatus
值并继续到适当的下一个状态(例如“正在运行”、“失败”) ”,或返回等待状态。)

可视化 Workflow Studio 设计器使定义这种轮询模式变得非常容易。本机 Step Function 解决方案的一个潜在好处是需要管理的 AWS 资源更少(您无需定义 Lambda 函数来实施轮询)。一个潜在的缺点是成本。当前标准工作流程的AWS Step Function 定价基于状态转换,因此这种方法可能会很昂贵(取决于数量),因为每个轮询循环都涉及“等待”、“描述”和“选择”状态的转换。如果您的工作流程运行时间不超过 5 分钟,那么快速工作流程可能是更好的选择。

© www.soinside.com 2019 - 2024. All rights reserved.