将来自Amazon EventBridge的事件数据传递到AWS Fargate任务

8

目标

我希望能够直接将Amazon EventBridge的事件数据传递到AWS Fargate任务中。然而,目前似乎还无法实现这一点。

解决方法

作为一个解决方法,我在AWS Fargate和EventBridge之间插入了一个额外的资源。AWS Step Functions允许您指定ContainerOverrides,其中Environment属性允许您配置环境变量,这些环境变量将从EventBridge事件传递到Fargate任务中。

不幸的是,这种解决方法增加了不必要的解决方案的复杂性和成本。

问题:是否有一种方式可以将EventBridge的事件数据直接传递到AWS Fargate(ECS)任务中,而我仅仅不知道它?


你能否使用SQS或SNS将事件从EventBridge传递到容器中? - Marcin
那会是什么样子呢?我的原始事件源是S3的PutObjectCompleteMultipartUpload。如果您愿意,您可以提供一个您所设想的架构图来帮助理解。 :) - user189198
有很多方法可以实现这个功能。你的Fargate应用程序可以拉取SQS消息。或者你可以在应用程序上公开一个HTTP端点,以便SNS可以将消息推送到它上面。细节取决于具体的用例,因此除了一些评论中的想法,我也无法提供具体的答案。 - Marcin
1
我的问题特别涉及EventBridge和ECS(Fargate)之间的直接转发行为,因此目前中介是不可能的。我使用Step Functions作为解决方法,但正如我在问题中提到的那样,我更喜欢减少解决方案的复杂性。 - user189198
2个回答

6

如果要将事件桥事件的数据传递给使用 FARGATE 启动类型的 ECS 任务,可以使用输入转换(Input Transformation)。例如,假设我们已经配置了一个 S3 存储桶,将所有事件通知发送到事件桥,并且我们有一个如下所示的事件桥规则。

{
      "detail": {
        "bucket": {
          "name": ["mybucket"]
        }
      },
      "detail-type": ["Object Created"],
      "source": ["aws.s3"]
}

现在假设我们想将存储桶名称、对象键和对象版本ID传递给运行在Fargate上的ECS任务,您可以使用以下输入转换器在Terraform中创建一个aws_cloudwatch_event_target资源。

resource "aws_cloudwatch_event_target" "EventBridgeECSTaskTarget"{
  target_id = "EventBridgeECSTaskTarget"
  rule = aws_cloudwatch_event_rule.myeventbridgerule.name
  arn = "arn:aws:ecs:us-east-1:123456789012:cluster/myecscluster"
  role_arn = aws_iam_role.EventBridgeRuleInvokeECSTask.arn

  ecs_target {
    task_count          = 1
    task_definition_arn = "arn:aws:ecs:us-east-1:123456789012:task-definition/mytaskdefinition"
    launch_type = "FARGATE"
    
    network_configuration {
      subnets         = ["subnet-1","subnet-2","subnet-3"]
      security_groups = ["sg-group-id"]
   }
  }

  input_transformer {
    input_paths = {
      bucketname = "$.detail.bucket.name",
      objectkey   = "$.detail.object.key",
      objectversionid = "$.detail.object.version-id",
    }
    input_template = <<EOF
{
  "containerOverrides": [
    {
      "name": "containername",
      "environment" : [
        {
          "name" : "S3_BUCKET_NAME",
          "value" : <bucketname>
        },
        {
          "name" : "S3_OBJECT_KEY",
          "value" : <objectkey>
        },
        {
          "name" : "S3_OBJ_VERSION_ID",
          "value": <objectversionid>
        }
      ]
    }
  ]
}
EOF
  }
}

当您的 ECS 任务正在运行时,您可以轻松访问这些变量以检查对象在哪个存储桶中被创建,对象是什么以及版本,并执行 GetObject 操作。

例如,在 Go 中,我们可以轻松地执行如下操作(仅为代码片段,未添加导入等内容,但您可以理解其思路)。

filename := aws.String(os.Getenv("S3_OBJECT_KEY"))
bucketname := aws.String(os.Getenv("S3_BUCKET_NAME"))
versionId := aws.String(os.Getenv("S3_OBJ_VERSION_ID"))

//You can print and verify the values in CloudWatch

//Prepare the s3 GetObjectInput

s3goi := &s3.GetObjectInput{
        Bucket: bucketname,
        Key:    filename,
        VersionId: versionId,
    }

s3goo, err := s3svc.GetObject(ctx, s3goi)
    if err != nil {
        log.Fatalf("Error retreiving object: %v", err)
    }

b, err := ioutil.ReadAll(s3goo.Body)
    if err != nil {
        log.Fatalf("Error reading file: %v", err)
    }

2

1
似乎是可以的:https://dev.to/maduranga95/run-a-scheduled-task-using-aws-fargate-with-ci-cd-3pej,https://docs.aws.amazon.com/AmazonECS/latest/userguide/cloudwatch_event_stream.html(“使用Fargate启动类型时…”) - The Onin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接