概要
ECS のタスク数を AWS EventBridge Scheduler にて定期的に変更する仕組みを CloudFormation で構築します。
仕組み
AWS EventBridge Scheduler より直接 ECS へ API を発行し、ECS の DesiredCount を変更します。
動作検証
ECS Fargate 環境でのみ動作確認しています。
手順
以下の CloudFormation を AWS Management Console か AWS CLI などから展開します。
展開後、AWS EventBridge Scheduler にスケジュールが作成されていることを確認します。
[パラメータ]
すべて必須パラメーターです。
- NamePrefix: 任意のプレフィックス
- EcsClusterName: ECS cluster 名
- EcsServiceName: ECS service 名
- ScheduleExpressionTimezone: タイムゾーン(Asia/Tokyoなど)
- StopScheduleExpression: 停止するスケジュールを cron式で記載します
- StartScheduleExpression: 起動するスケジュールを cron式で記載します
- StopDesiredCount: 停止時の ECS の 起動数を指定します(停止=0)
- StartDesiredCount: 開始時の ECS の起動数を指定します
AWSTemplateFormatVersion: "2010-09-09"
Description: "Create EventBridge Scheduler for ECS task"
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "Global setting"
Parameters:
- NamePrefix
- Label:
default: "ECS setting"
Parameters:
- EcsClusterName
- EcsServiceName
- Label:
default: "Schedule setting"
Parameters:
- StopScheduleExpression
- StartScheduleExpression
- ScheduleExpressionTimezone
- Label:
default: "ECS DesiredCount setting"
Parameters:
- StopDesiredCount
- StartDesiredCount
Parameters:
# General Setting
NamePrefix:
Description: "Prefix"
Type: String
Default: ""
# ECS Setting
EcsClusterName:
Description: "ECS Cluster Name"
Type: String
Default: ""
EcsServiceName:
Description: "ECS Service Name"
Type: String
Default: ""
# Schedule Setting
StopScheduleExpression:
Description: "Schedule to stop Fargate task"
Type: String
Default: "cron(0 18 * * ? *)"
StartScheduleExpression:
Description: "Schedule to start Fargate task"
Type: String
Default: "cron(0 9 * * ? *)"
ScheduleExpressionTimezone:
Description: "Set Timezone. e.g. Asia/Tokyo. See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"
Type: String
Default: "Asia/Tokyo"
# ECS DesiredCount Setting
StopDesiredCount:
Description: "DesiredCount to stop Fargate task"
Type: Number
Default: 0
StartDesiredCount:
Description: "DesiredCount to start Fargate task"
Type: Number
Default: 1
Resources:
ScheduledRuleStop:
Type: AWS::Scheduler::Schedule
Properties:
Description: "Schedule to stop Fargate task"
Name: !Sub "${NamePrefix}-stop-ecs-task-schedule"
ScheduleExpression: !Ref StopScheduleExpression
ScheduleExpressionTimezone: !Ref ScheduleExpressionTimezone
FlexibleTimeWindow:
Mode: "OFF"
State: "ENABLED"
Target:
Arn: "arn:aws:scheduler:::aws-sdk:ecs:updateService"
Input: !Sub "{ \"DesiredCount\": ${StopDesiredCount}, \"Service\": \"${EcsServiceName}\", \"Cluster\": \"${EcsClusterName}\" }"
RoleArn: !GetAtt ScheduleRole.Arn
RetryPolicy:
MaximumRetryAttempts: 0
ScheduledRuleStart:
Type: AWS::Scheduler::Schedule
Properties:
Description: "Schedule to start Fargate task"
Name: !Sub "${NamePrefix}-start-ecs-task-schedule"
ScheduleExpression: !Ref StartScheduleExpression
ScheduleExpressionTimezone: !Ref ScheduleExpressionTimezone
FlexibleTimeWindow:
Mode: "OFF"
State: "ENABLED"
Target:
Arn: "arn:aws:scheduler:::aws-sdk:ecs:updateService"
Input: !Sub "{ \"DesiredCount\": ${StartDesiredCount}, \"Service\": \"${EcsServiceName}\", \"Cluster\": \"${EcsClusterName}\" }"
RoleArn: !GetAtt ScheduleRole.Arn
RetryPolicy:
MaximumRetryAttempts: 0
ScheduleRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${NamePrefix}-ecs-task-schedule-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "scheduler.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: "ecs-task-schedule-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: "arn:aws:logs:*:*:*"
- Effect: "Allow"
Action:
- "ecs:UpdateService"
Resource: !Sub "arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:service/${EcsClusterName}/${EcsServiceName}"
Tips
AWS EventBridge Scheduler で指定出来るターゲットとは?
以下のページに "templated targets" や "universal targets" などで紹介されています。
幅広いサービスで利用できるようです。
https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets.html
対応していないアクションとして "Unsupported actions" にも記載があるので注意する必要があります。
上記サービス一覧に記載の "arn:aws:scheduler:::aws-sdk:ecs:[apiAction]"などの "[apiAction]" の指定部分ですが、以下の JavaScriptSDK 向けの値を参考にしました。
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-ecs/index.html
Target の Input は Pascal Case で入力
例えば、AWSJavaScriptSDK で ECS の起動タスク数は "desiredConunt" を指定しますが、EventBridge Scheduler では "DesiredCount" と指定する必要がありました。
[AWS EventBridge Scheduler のターゲット設定の画面]
参考
タイムゾーンの指定:
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
EventBridge Scheduler で指定可能なサービス一覧:
https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets.html
AWSJavaScriptSDK
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest