この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
「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
lib/sample-ecs.ts
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)でした。