タスクをスケジュールで増減させたい!
本番でもstagingでも開発環境でもECS Fargateのタスクの増減をスケジュールを決めて実行したいということがあると思います。
EC2の場合はAutoScaling Groupの設定でスケジュールが合ったのですが、Fargateの場合はどうもなさそう。
このような記事が作成されていることからも、直接的な機能は提供されていなさそうです。
今回は上記のクラスメソッドさんの記事を参考に作成しました。
CloudFormationで作成
EventBridgeでタスクのDesiredCountを操作します。
start時は1、stopの際は0としていますが、これは状況によって変えて良さそうです。
このymlファイルをCloudformationに渡すとAWSコンソール上で
- クラスター名
- サービス名
- 止める時間のcron
- 開始時間のcron
- DesiredCount(デフォルト1)
が聞かれます。これに回答するだけで自動での起動・停止のスケジュールが作成されます。
ちなみにcronは以下の形式で書きます。cron()が必要です。
cron(0 20 ? * MON-FRI *)
AWSTemplateFormatVersion: '2010-09-09'
Description: 'ECS Fargate Auto Start/Stop Scheduler'
Parameters:
ClusterName:
Type: String
Description: 'Name of the ECS cluster'
ServiceName:
Type: String
Description: 'Name of the ECS service'
StopCron:
Type: String
Description: 'Cron expression for stopping (e.g., cron(0 20 ? * MON-FRI *))'
StartCron:
Type: String
Description: 'Cron expression for starting (e.g., cron(0 8 ? * MON-FRI *))'
DesiredCount:
Type: Number
Default: 1
Description: 'Number of tasks when starting'
Resources:
EcsAutoStopSchedule:
Type: AWS::Scheduler::Schedule
Properties:
GroupName: default
ScheduleExpression: !Ref StopCron
Target:
Input: !Sub '{ "Cluster": "${ClusterName}", "Service": "${ServiceName}", "DesiredCount": 0 }'
Arn: arn:aws:scheduler:::aws-sdk:ecs:updateService
RetryPolicy:
MaximumEventAgeInSeconds: 86400
MaximumRetryAttempts: 3
RoleArn: !GetAtt SchedulerExecutionRole.Arn
State: ENABLED
FlexibleTimeWindow:
Mode: 'OFF'
ScheduleExpressionTimezone: Asia/Tokyo
Name: !Sub '${ClusterName}-${ServiceName}-Stop'
SchedulerExecutionRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: scheduler.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: ECSUpdateServicePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: 'ecs:UpdateService'
Resource: !Sub 'arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:service/${ClusterName}/${ServiceName}'
EcsAutoStartSchedule:
Type: AWS::Scheduler::Schedule
Properties:
GroupName: default
ScheduleExpression: !Ref StartCron
Target:
Input: !Sub |-
{
"Cluster": "${ClusterName}",
"Service": "${ServiceName}",
"DesiredCount": ${DesiredCount}
}
Arn: arn:aws:scheduler:::aws-sdk:ecs:updateService
RetryPolicy:
MaximumEventAgeInSeconds: 86400
MaximumRetryAttempts: 3
RoleArn: !GetAtt SchedulerExecutionRole.Arn
State: ENABLED
FlexibleTimeWindow:
Mode: 'OFF'
ScheduleExpressionTimezone: Asia/Tokyo
Name: !Sub '${ClusterName}-${ServiceName}-Start'