
EventBridge Schedulerを使ってEC2を定期起動・停止するCloudFormationテンプレート
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
コスト削減のために、業務時間内だけAmazon EC2インスタンスを起動したいことってありますよね。 9時-18時だけ起動したいとか、週末は停止しておきたいとか。
そんな要望を実現するために、ノンコーディングなAmazon EventBridge Schedulerを使ってEC2を定期起動・停止するAWS CloudFormationテンプレートを紹介します。
Amazon EventBridge Schedulerでコーディング不要なスケジュール実行
AWS上で定期実行したい場合、かつてはAmazon EventBridge rulesでスケジュール実行するのが鉄板でしたが、2022年末にもっと便利なAmazon EventBridge Schedulerがリリースされました。
EventBridge Schedulerを使用すると
- Lambdaなどのコーディング無しに270を超えるAWSサービス、6000以上のAPIを直接を呼び出せる(ユニバーサルターゲット)ため、だれでもメンテナンスできる
 - タイムゾーンを指定できるため、時差やサマータイムを考慮せずにスケジュール設定できる
 
など、管理者に優しい機能が強化されています。
EC2の定期起動・停止設定をCloudFormation化
EventBridge Schedulerを使うと、次のブログのようにコンソールから画面をポチポチするだけで、簡単に設定できてしまいます。
EventBridgeスケジューラを使ってEC2の定期起動/停止を行う方法 | DevelopersIO
EC2の定期起動・停止のような定形作業をより楽をするために、この設定をCloudFormationのテンプレート化してみました。
スタック作成時に
- プルダウンで対象インスタンス
 - 起動・停止のスケジュール
 - タイムゾーン
 
を指定するだけです。
CloudFormationテンプレート
Lambdaなどのコードが存在しないため、テンプレートは非常にシンプルです。 設定を指定しているだけです。
---
AWSTemplateFormatVersion: '2010-09-09'
Description:  EventBridge Scheduler to start/stop EC2 instance
Parameters:
  InstanceId:
    Type: AWS::EC2::Instance::Id
  ScheduleStartTime:
    Type: String
    Default: "cron(0 8 * * ? *)"
  ScheduleStopTime:
    Type: String
    Default: "cron(0 19 * * ? *)"
  ScheduleTimezone:
    Type: String
    Default: Japan
Resources:
  ScheduleEC2Sart:
    Type: AWS::Scheduler::Schedule
    Properties:
      Name: !Sub 'EC2-Start-${InstanceId}'
      Description: Start EC2 Instance
      ScheduleExpression: !Ref ScheduleStartTime 
      ScheduleExpressionTimezone: !Ref ScheduleTimezone
      FlexibleTimeWindow:
        Mode: "OFF"
      State: ENABLED
      Target:
        Arn: arn:aws:scheduler:::aws-sdk:ec2:startInstances
        Input: !Sub |-
          {
            "InstanceIds": ["${InstanceId}"]
          }
        RoleArn:
          Fn::GetAtt:
          - SchedulerEC2StopStartRole
          - Arn
  ScheduleEC2Stop:
    Type: AWS::Scheduler::Schedule
    Properties:
      Name: !Sub 'EC2-Stop-${InstanceId}'
      Description: Stop EC2 Instance
      ScheduleExpression: !Ref ScheduleStopTime 
      ScheduleExpressionTimezone: !Ref ScheduleTimezone
      FlexibleTimeWindow:
        Mode: "OFF"
      State: ENABLED
      Target:
        Arn: arn:aws:scheduler:::aws-sdk:ec2:stopInstances
        Input: !Sub |-
          {
            "InstanceIds": ["${InstanceId}"]
          }
        RoleArn:
          Fn::GetAtt:
          - SchedulerEC2StopStartRole
          - Arn
  SchedulerEC2StopStartRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - scheduler.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      Policies:
        - PolicyName: EC2StopStart
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ec2:StartInstances
                  - ec2:StopInstances
                Resource:
                  - "*"
作成されたリソースを確認
このCloudFormationテンプレートは以下のリソースを作成します。
- 起動用と停止用の2つのEventBridge Schedule
 - 上記Schedule実行用のIAMロール
 
スタック作成完了後、コンソールの「Amazon EventBridge > スケジュール」に作成されたリソースを確認できます。
スケジュール通りに起動・停止できていることを確認してください。
CloudFormatationの改善ポイント
本記事では、EventBridge Schdulerのユニバーサルターゲットのサンプルとして、極力シンプルなCloudFormationテンプレートを用意しました。
より実用的にするための改善ポイントを紹介します。
複数のEC2インスタンスを対象にする
今回紹介したテンプレートはスケジュールと対象EC2インスタンスを1:1で作成しています。
ec2:StartInstancesAPIec2:StopInstancesAPI
は複数のインスタンスIDを受け取れるため、CloudFormationパラメータのインスタンスID指定を List<AWS::EC2::Instance::Id> にかえてターゲットの指定も合わせて調整すると、複数IDに対応できます。
CloudFormationではスケジュールだけを登録し、ターゲットのインスタンスIDリストを手動で管理するのも現実的です。
EC2インスタンス以外を対象にする
EventBridge SchedulerはEC2を含む270のAWSサービス、6000以上のAPIに対応しています。
そのため、RDS/Aurora の自動起動・停止などにも簡単に応用できます。
エラー検知を追加
定期実行を安定運用させるため、実行失敗を検知できるようにデッドレターキューを設定しましょう。
Amazon EventBridge Schedulerのデッドレターキュー(DLQ)を使ってみた | DevelopersIO









