Amazon EventBridge SchedulerでECS Fargateのタスクを定期起動・定期停止してみた
「Event Bridge Schedulerを使えば、ECS FargateのサービスをLambda無しで定期起動・定期停止できる」
夜間など使わない時間は検証環境のECS Fargateを止めて料金節約したいことがあると思います。
ECS Fargate サービスの自動起動停止に関しては、Instance Schedulerも対応しておらず自前でLambdaを書くなどする必要がありました。
先日リリースされたEvent Bridge Schedulerを使えば、Lambdaを書かずに簡単に定期起動・定期停止を実現できます。
前提
定期停止と定期起動は以下を指しています。
- 定期停止: ECS Fargateサービスのタスク数(desiredCount)を0にする
- 定期起動: ECS Fargateサービスのタスク数(desiredCount)を元の数に戻す
そのため、1つのサービスあたり起動と停止で2つのスケジュールが必要になります。
今回は検証環境を定期起動・定期停止する場合を想定して、平日の20時に停止・平日の8時に起動するスケジュールを設定します。
やってみる
事前準備
検証用の環境はAWS CDKで用意します。
現時点(2022/11 )では、AWS CDKがEvent Bridge Schedulerに対応していないためEvent Bridge Schedulerの部分は手動で対応します。
AWS CDK v2.51.0でL1 Constructが対応しました。
aws-cdk-lib.aws_scheduler module · AWS CDK
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as ec2 from 'aws-cdk-lib/aws-ec2' import * as ecs from 'aws-cdk-lib/aws-ecs' import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns' import * as iam from 'aws-cdk-lib/aws-iam' export class EcsStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // VPC const vpc = new ec2.Vpc(this, "Vpc", { vpcName: "sample-ecs", natGateways: 1 }) // ECSクラスター const cluster = new ecs.Cluster(this, "Cluster", { clusterName: "sample-cluster", vpc }) // ECSサービス const ecsService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, "EcsService", { cluster, memoryLimitMiB: 1024, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, desiredCount: 2, serviceName: "sample-service", }) // 検証用のためターゲットの解除時間を短くする ecsService.targetGroup.setAttribute( "deregistration_delay.timeout_seconds", "30" ) // IAMロール const ecsStartStopRole = new iam.Role(this, "EcsStartStopRole", { assumedBy: new iam.ServicePrincipal('scheduler.amazonaws.com'), roleName: 'ecs-start-stop-role' }) const policy = new iam.PolicyStatement({ actions: [ 'ecs:UpdateService' ], resources: ["*"] }) ecsStartStopRole.addToPolicy(policy) } }
Event Bridge Scheduelerの設定(定期停止)
スケジュールの詳細の指定
以下を設定します。cron式は平日20時に実行されるように設定します。
- スケジュール名:
ecs-sample-stop-weekday
- cron式:
00 20 ? * MON-FRI *
Schedule types on EventBridge Scheduler - EventBridge Scheduler
タイムゾーンが意図したものになっているか確認して、次に進みます。
ターゲットの選択
サービスの検索>検索バーにECS
>検索バーにUpdateService
の順に進んで、Amazon ECS UpdateService
を選択します。
JSONパラメータには以下を渡します。
{ "Service": "<サービス名>", "Cluster": "<クラスター名>", "DesiredCount": 0 }
設定
最後にCDKで作成した、IAMロール「ecs-start-stop-role」を指定して、次に進みます。
最後に確認画面が出るので、問題なければスケジュール作成を行います。
Event Bridge Scheduelerの設定(定期起動)
上記と手順は基本的に同じです。異なる部分だけ記載します。
スケジュールの詳細の指定
以下を設定します。cron式は平日8時に実行されるように設定します。
- スケジュール名:
ecs-sample-start-weekday
- cron式:
00 8 ? * MON-FRI *
ターゲットの選択
ターゲットは同様にAmazon ECS UpdateService
を指定します。
JSONパラメータのDesiredCountだけ変更します。
{ "Service": "<サービス名>", "Cluster": "<クラスター名>", "DesiredCount": <必要なタスク数> }
動作確認
テスト用に時間を変えてスケジューラを実行してみました。(11:55実行)
設定した時間にタスクのdrainingが発生して、タスクの必要数が「0」になっていることを確認できました。
おわりに
「Amazon EventBridge SchedulerでECS Fargateのタスクを定期起動・定期停止してみた」でした。
EventBridge Schedulerのみ用意すれば定期起動・定期停止ができるので導入のハードルが下がったと思います。
TerraformやCDKでECSモジュールを作ってその中に、STG環境だったら定期起動・定期停止のEventBridge Schedulerを追加するといった処理を追加したら便利かもしれません。
以上、AWS事業本部の佐藤(@chari7311)でした。