概要
ECS Fargateのタスク起動を日次起動にしたいことってありませんでしょうか。
例えば平日8:00-20:00の間だけ使えれば良いというな社内サービスとか。
今までECS on EC2を使っていて、その時はCloudWatchRuleでEC2 instanceのStart/Stop設定が可能だったのですが、Fargateの場合は異なる手段が必要だったので紹介します。
前提
Lambda関数を使って設定することもできるとのことでしたが、CW Ruleのようにマネコンから簡単に変更できるようなものがいいな〜と思っていました。
FargateのECSを対象にCloudwatchRuleでタスク数を1にする、と言う設定は可能だったのですが、タスク数を0にするルールを作成したら以下のエラーに。
Resource handler returned message: "1 validation error detected: Value '0' at 'targets.1.member.ecsParameters.taskCount' failed to satisfy constraint: Member must have value greater than or equal to 1
と言うことで、ECS on Fargateを利用していると、CloudwatchRuleで日次起動の設定を行うことができないことがわかったので、EventBridgeのSchedulerを利用することにしました。これであればマネコンからも簡単に変更もできます。
参考CFnテンプレート
以下が参考Cloudformationテンプレートです。
この「arn:aws:scheduler:::aws-sdk:ecs:updateService」を使った記事があまり見当たらなかったので、作成に少し苦労しました。
Parameters:
  EnvTag:
    Type: String
    Default: "dev"
  SysTag:
    Type: String
    Default: "sample"
Resources:
  EcsClusterSample:
    Type: AWS::ECS::Cluster
    ## 略 ##
  ServiceSample:
    Type: AWS::ECS::Service
    ## 略 ##
  TaskDefinitionSample:
    Type: AWS::ECS::TaskDefinition
    ## 略 ##
  ScheduleGroup:
    Type: AWS::Scheduler::ScheduleGroup
    Properties:
      Name: !Sub ${SysTag}_${EnvTag}
  ScheduleEcsStart:
    Type: AWS::Scheduler::Schedule
    Properties:
      Name: !Sub ${SysTag}_${EnvTag}_Start_Ecs
      Description: Start Ecs
      GroupName: !Ref ScheduleGroup
      ScheduleExpression: cron(00 08 ? * MON-FRI *)
      ScheduleExpressionTimezone: Asia/Tokyo
      FlexibleTimeWindow:
        Mode: "OFF"
      State: ENABLED
      Target:
        Arn: arn:aws:scheduler:::aws-sdk:ecs:updateService
        Input: !Sub |
          {
            "Service": "${ServiceSample}",
            "Cluster": "${EcsClusterSample}",
            "DesiredCount": 1
          }
        RoleArn: !GetAtt EcsStartStopRole.Arn
  ScheduleEcsStop:
    Type: AWS::Scheduler::Schedule
    Properties:
      Name: !Sub ${SysTag}_${EnvTag}_Stop_Ecs
      Description: Stop Ecs
      GroupName: !Ref ScheduleGroup
      ScheduleExpression: cron(0 20 * * ? *)
      ScheduleExpressionTimezone: Asia/Tokyo
      FlexibleTimeWindow:
        Mode: "OFF"
      State: ENABLED
      Target:
        Arn: arn:aws:scheduler:::aws-sdk:ecs:updateService
        Input: !Sub |
          {
            "Service": "${ServiceSample}",
            "Cluster": "${EcsClusterSample}",
            "DesiredCount": 0
          }
        RoleArn: !GetAtt EcsStartStopRole.Arn
  EcsStartStopRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: EcsStartStopRole
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: scheduler.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: EcsStartStopPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ecs:UpdateService
                Resource: "*"
Schedulerの公式ドキュメントはこちら。
CLIコマンド
ちなみに、作成したスケジューラーをCLIコマンドで参照する方法は以下です。
(最初「aws events...なのか?」とよくわからなくなったので...笑)
$ aws scheduler get-schedule --name sample_dev_Start_Ecs --region ap-northeast-1
