在进入 AWS Step Function 的下一步之前,如何等待 AWS ECS 任务处于 运行 状态?
How do wait for AWS ECS Task to be in RUNNING state before moving to next step in AWS Step Function?
我有一个对象数组,我想将其迭代传递给 Lambda 函数。但是,对于我启动的每个 Lambda 函数,我还需要一个 ECS 任务 运行。
我发现我需要一个 AWS Step Function,我可以在其中迭代 JSON 个输入数组。对于每个输入,我都必须启动一个 ECS 任务,等待它处于 运行 状态,然后转到调用 Lambda 函数的下一步。在我的例子中,ECS 任务本身没有 return 任何东西。它应该保留 运行 因为 Lambda 函数使用它。
目前,我有它以便 ECS 任务启动,但它停留在启动 ECS 任务步骤中,因为它没有 return 任何东西。在进入下一步之前,我如何才能等待它处于 运行 状态?
当前步进函数定义:
{
"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
}
}
}
ecs:runTask 可以通过两种不同的方式触发。
- arn:aws:states:::ecs:runTask.sync > 运行并等待任务完成
- arn:aws:states:::ecs:runTask.waitForTaskToken - 触发并等待它收到 SendTaskSucess or 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"
}
}
}
}
我没有使用集成的 AWS 服务(即 AWS Step Function),而是使用 aws-sdk
v3 for JavaScript 创建了自己的启动 ECS 任务的脚本。我专门使用 @aws-sdk/client-ecs
包中的 waitUntilTasksRunning
函数来等待 ECS 任务处于 运行 状态。
从文档中了解更多信息
- 适用于 JavaScript v3 的 AWS SDK:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/index.html
- @aws-sdk/client-ecs : https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-ecs/index.html
- @aws-sdk/client-ecswaitUntilTasksRunning:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-ecs/globals.html#waituntiltasksrunning
运行 的示例函数并等待 ECS 任务处于 运行 状态(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
}
}
我有一个对象数组,我想将其迭代传递给 Lambda 函数。但是,对于我启动的每个 Lambda 函数,我还需要一个 ECS 任务 运行。
我发现我需要一个 AWS Step Function,我可以在其中迭代 JSON 个输入数组。对于每个输入,我都必须启动一个 ECS 任务,等待它处于 运行 状态,然后转到调用 Lambda 函数的下一步。在我的例子中,ECS 任务本身没有 return 任何东西。它应该保留 运行 因为 Lambda 函数使用它。
目前,我有它以便 ECS 任务启动,但它停留在启动 ECS 任务步骤中,因为它没有 return 任何东西。在进入下一步之前,我如何才能等待它处于 运行 状态?
当前步进函数定义:
{
"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
}
}
}
ecs:runTask 可以通过两种不同的方式触发。
- arn:aws:states:::ecs:runTask.sync > 运行并等待任务完成
- arn:aws:states:::ecs:runTask.waitForTaskToken - 触发并等待它收到 SendTaskSucess or 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"
}
}
}
}
我没有使用集成的 AWS 服务(即 AWS Step Function),而是使用 aws-sdk
v3 for JavaScript 创建了自己的启动 ECS 任务的脚本。我专门使用 @aws-sdk/client-ecs
包中的 waitUntilTasksRunning
函数来等待 ECS 任务处于 运行 状态。
从文档中了解更多信息
- 适用于 JavaScript v3 的 AWS SDK:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/index.html
- @aws-sdk/client-ecs : https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-ecs/index.html
- @aws-sdk/client-ecswaitUntilTasksRunning:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-ecs/globals.html#waituntiltasksrunning
运行 的示例函数并等待 ECS 任务处于 运行 状态(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
}
}