🦤
S3からのイベントをトリガにECS Fargateのタスクを起動するEventBridgeを構築した話
タイトルの通り、S3にファイルが置かれたことをトリガに、ECS Fargateのタスクを起動するEventBridgeをCloudFormationで作成しました。
簡単な構成図はこちら。
今回のポイントは以下2点です。
- 特定のディレクトリ(正確にはキー)に配置された時だけイベントを発火したい
- 置かれたファイルの情報(ディレクトリ、ファイル名)をFargateのタスクに渡したい
作成したものをベースに、上記2つのポイントに絞って簡単に説明します。
前提
VPC、サブネット、セキュリティグループ、Fargate、S3は作成済みであることを前提としています。
ご自分の環境と照らし合わせて適宜読み替えてくださいm()m。
※ymlファイルの中で個別に修正が必要な箇所には「適宜修正ください」というコメントをつけています。
作ったもの
AWSTemplateFormatVersion: "2010-09-09"
Description: CloudFormation template for EventBridge.
Parameters:
ProjectName:
Description: Project name
Type: String
ProjectEnv:
Description: Envirment of project
Type: String
AllowedValues:
- dev
- stg
- prd
Resources:
EventBridgeRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: !Sub ${ProjectName}-${ProjectEnv}-event-bridge-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "events.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: !Sub ${ProjectName}-${ProjectEnv}-event-bridge-policy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "ecs:RunTask"
Resource:
- !Sub arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:task-definition/${ProjectName}-${ProjectEnv}-task-def # 適宜修正ください
- Effect: "Allow"
Action:
- "iam:PassRole"
Resource:
- "*"
Condition:
StringLike:
iam:PassedToService: "ecs-tasks.amazonaws.com"
EventBridgeRule:
Type: "AWS::Events::Rule"
Properties:
Name: !Sub ${ProjectName}-${ProjectEnv}-event-bridge-rule
EventPattern:
source:
- aws.s3
detail-type:
- Object Created
detail:
bucket:
name:
- !Sub ${ProjectName}-${ProjectEnv}-input-bucket # 適宜修正ください
object:
key:
- prefix: key-name # 適宜修正ください
Targets:
- Arn: !Sub arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:cluster/${ProjectName}-${ProjectEnv}-cluster # 適宜修正ください
Id: !Sub ${ProjectName}-${ProjectEnv}-event-bridge-target # 適宜修正ください
RoleArn: !GetAtt EventBridgeRole.Arn
EcsParameters:
EnableExecuteCommand: false
LaunchType: FARGATE
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- ${セキュリティグループのID} # 適宜修正ください
Subnets:
- ${サブネットのID} # 適宜修正ください
TaskDefinitionArn: !Sub arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:task-definition/${ProjectName}-${ProjectEnv}-task-def # 適宜修正ください
InputTransformer:
InputPathsMap:
key: "$.detail.object.key"
InputTemplate: !Sub '{"containerOverrides":[{"name":"${ProjectName}-${ProjectEnv}-container-def","environment":[{"name":"OBJECT_KEY","value":"<key>"}]}]}' # 適宜修正ください
ポイント①:特定のディレクトリ(正確にはキー)に配置された時だけイベントを発火したい
yamlの中の以下の部分です。
EventPattern:
source:
- aws.s3
detail-type:
- Object Created
detail:
bucket:
name:
- !Sub ${ProjectName}-${ProjectEnv}-input-bucket # 適宜修正ください
object:
key:
- prefix: key-name # 適宜修正ください
object.key.prefixの箇所で、イベントを発火させるディレクトリを指定することができます。
ポイント②:置かれたファイルの情報(ディレクトリ、ファイル名)をFargateのタスクに渡したい
yamlの中の以下の部分です。
InputTransformer:
InputPathsMap:
key: "$.detail.object.key"
InputTemplate: !Sub '{"containerOverrides":[{"name":"${ProjectName}-${ProjectEnv}-container-def","environment":[{"name":"OBJECT_KEY","value":"<key>"}]}]}' # 適宜修正ください
ECSの「コンテナの上書き」の機能を使って、置かれたファイルの情報を環境変数でFargateに渡すようにします。
これをやるには、TargetsのInputTransformer
という項目で指定するようです。わかりにくいです。
この中のInputPathsMap
で、key
という項目に取得したパス($.detail.object.key
)をマッピングします。
そして、マッピングされた項目はInputTemplate
の中で<key>
のように記載することで使用できます。
今回はkey
という名前を使用しましたが、名前はなんでも良いですし、key
に加えてobject-name
も加えるなど、複数の項目をマッピングすることも可能です。
あとは、Fargateの中で、渡された環境変数OBJECT_KEY
を参照すればOKです。
Discussion