2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ECS Fargate を定期的に停止&起動する仕組みを CloudFormation で作成する

Posted at

概要

ECS のタスク数を AWS EventBridge Scheduler にて定期的に変更する仕組みを CloudFormation で構築します。

仕組み

AWS EventBridge Scheduler より直接 ECS へ API を発行し、ECS の DesiredCount を変更します。
eventbridge-scheduler.png

動作検証

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 のターゲット設定の画面]
image.png

参考

タイムゾーンの指定:
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

GitHub
https://github.com/coni524/aws-ecs-fargate-schedule

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?