🕐
AWS CDK でコマンド指定して ECS Scheduled Task を作成する
ググってもあまり情報が出てこなったので備忘録として。
要件としては以下の通り。
- cron式で ECS Task を定期実行したい
- タスク定義を再利用し、コマンドだけルールごとに置き換える
- ECS Console の
スケジュールされたタスク
に定義したルール群を表示させたい
結論から言えば、下記のように aws-cdk-lib/aws-events
の Rule
props の targets
に aws-cdk-lib/aws-events-targets
の EcsTask
を指定してやれば良い。
もし CDK 外でタスク定義を更新している場合、基本的には最新のタスク定義を使わせたいはずなので、それらに関するコードも入れる必要がある(下記の前半部分)。
// 最新のタスク定義
// taskDefinitionArn を文字生成するのがポイント(cdk によって作られたタスク定義を再利用すると、作った時点のタスク定義リビジョンで起動してしまうため)
const cronTaskDefLatest = FargateTaskDefinition.fromFargateTaskDefinitionAttributes(this, "CronTaskDefLatest", {
taskDefinitionArn: `arn:aws:ecs:${env.region}:${env.account}:task-definition/${ecsTaskDefName}`,
taskRole: taskRole,
networkMode: NetworkMode.AWS_VPC,
})
// EventBridge に ECS RunTask をさせる Role
// 本当はもう少し権限絞ったほうが良さげ?
const ecsEventsRole = new Role(this, "EcsEventsRole", {
assumedBy: new ServicePrincipal("events.amazonaws.com"),
managedPolicies: [ManagedPolicy.fromAwsManagedPolicyName("service-role/AmazonEC2ContainerServiceEventsRole")],
})
// containerOverrides.command で実行コマンドを上書きする
const target = new EcsTask({
cluster: ecsCluster,
taskDefinition: cronTaskDefLatest,
taskCount: 1,
containerOverrides: [
{
containerName: "app",
command: ["command", "args1", "args2", ...],
},
],
subnetSelection: {
subnetType: SubnetType.PRIVATE_WITH_EGRESS,
},
launchType: LaunchType.FARGATE,
platformVersion: FargatePlatformVersion.VERSION1_4,
securityGroups: [securityGroup],
enableExecuteCommand: true,
propagateTags: PropagatedTagSource.TASK_DEFINITION,
executionRole: execRole,
taskRole: taskRole,
role: ecsEventsRole.withoutPolicyUpdates(),
})
new Rule(this, `Rule${name}`, {
ruleName: `run_task_test`,
schedule: Schedule.expression('cron(1 0 ? * * *)'),
enabled: true,
targets: [target],
})
Discussion