EventBridge Schedulerを使ってEC2を定期起動・停止するCloudFormationテンプレート

Amazon EventBridge SchedulerとAWS CloudFormationでEC2インスタンスの定期起動・停止をラクラク設定
2023.02.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コスト削減のために、業務時間内だけAmazon EC2インスタンスを起動したいことってありますよね。 9時-18時だけ起動したいとか、週末は停止しておきたいとか。

そんな要望を実現するために、ノンコーディングなAmazon EventBridge Schedulerを使ってEC2を定期起動・停止するAWS CloudFormationテンプレートを紹介します。

Amazon EventBridge Schedulerでコーディング不要なスケジュール実行

AWS上で定期実行したい場合、かつてはAmazon EventBridge rulesでスケジュール実行するのが鉄板でしたが、2022年末にもっと便利なAmazon EventBridge Schedulerがリリースされました。

EventBridge Schedulerを使用すると

など、管理者に優しい機能が強化されています。

EC2の定期起動・停止設定をCloudFormation化

EventBridge Schedulerを使うと、次のブログのようにコンソールから画面をポチポチするだけで、簡単に設定できてしまいます。

EventBridgeスケジューラを使ってEC2の定期起動/停止を行う方法 | DevelopersIO

EC2の定期起動・停止のような定形作業をより楽をするために、この設定をCloudFormationのテンプレート化してみました。

スタック作成時に

  • プルダウンで対象インスタンス
  • 起動・停止のスケジュール
  • タイムゾーン

を指定するだけです。

CloudFormationテンプレート

Lambdaなどのコードが存在しないため、テンプレートは非常にシンプルです。 設定を指定しているだけです。

scheduler-ec2-start-stop.yml

---
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:StartInstances API
  • ec2:StopInstances API

は複数のインスタンス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

参考