0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EC2、RDS、Aurora を CloudFormation で自動定期起動/停止してみた

Posted at

はじめに

検証環境など限られた予算で実行しなければいけない場合、EC2 や RDS、Aurora の停止を忘れると致命的・・・
そこで、特定時間内のみで実行/停止できないかと思い調べてみました。

仕様

指定した EC2 or RDS or Aurora について、指定時間(曜日)になったら起動/停止
例えば、月から金曜日の 9:00 から 17:00 の間だけ起動など

EC2 の自動定期起動/停止

YAMLテンプレート

details ec2-start-stop.yaml(折り畳んでます)
AWSTemplateFormatVersion: '2010-09-09'
Description: EC2 instance start/stop schedule

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Resource Configuration
        Parameters:
          - InstanceId
          - StartDayOfWeek
          - StartHours
          - StartMinutes
          - StopDayOfWeek
          - StopHours
          - StopMinutes

Parameters:
  InstanceId:
    Type: String
    Description: Instance ID to start and stop
    ConstraintDescription: Please enter Instance ID
# ---Start Parameter--- #
  StartMinutes:
    Type: Number
    Description: Specified minutes starting instances
    ConstraintDescription: Please enter a number of 0-59
    MinValue: 0
    MaxValue: 59
  StartHours:
    Description: Specified hours starting instances
    ConstraintDescription: Please enter a number of 0-23
    Type: Number
    MinValue: 0
    MaxValue: 23
  StartDayOfWeek:
    Type: String
    Description: The day of the week starting instances
    ConstraintDescription: Please enter the day of the week
    AllowedPattern: (\*|SUN|MON|TUE|WED|THU|FRI|SAT)?((,|-)(SUN|MON|TUE|WED|THU|FRI|SAT))?
# ---Stop Parameter--- #
  StopMinutes:
    Type: Number
    Description: Specified minutes starting instances
    ConstraintDescription: Please enter a number of 0-59
    MinValue: 0
    MaxValue: 59
  StopHours:
    Description: Specified hours starting instances
    ConstraintDescription: Please enter a number of 0-23
    Type: Number
    MinValue: 0
    MaxValue: 23
  StopDayOfWeek:
    Type: String
    Description: The day of the week starting instances
    ConstraintDescription: Please enter the day of the week
    AllowedPattern: (\*|SUN|MON|TUE|WED|THU|FRI|SAT)?((,|-)(SUN|MON|TUE|WED|THU|FRI|SAT))?

Conditions:
  ExistInstanceId: !Not [!Equals [!Ref InstanceId, ""]]

  ExistStartSchedule:
    !And
      - !Or
        - !Not [!Equals [!Ref StartDayOfWeek, ""]]
        - !Not [!Equals [!Ref StartHours, ""]]
        - !Not [!Equals [!Ref StartMinutes, ""]]
      - !Condition ExistInstanceId

  ExistStopSchedule:
    !And
      - !Or
        - !Not [!Equals [!Ref StopDayOfWeek, ""]]
        - !Not [!Equals [!Ref StopHours, ""]]
        - !Not [!Equals [!Ref StopMinutes, ""]]
      - !Condition ExistInstanceId

Resources:
  ScheduleRole:
    Type: AWS::IAM::Role
    Condition: ExistInstanceId
    Properties: 
      RoleName: !Sub ${AWS::StackName}-ec2-schedule-role
      Path: /
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "scheduler.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: !Sub ${AWS::StackName}-ec2-schedule-role-policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement: 
              - Sid: "AllowExecutionOfEC2StartStop"
                Effect: "Allow"
                Action:
                  - "ec2:StartInstances"
                  - "ec2:StopInstances"
                Resource: "*"
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-ec2-schedule-role

  ScheduleGroup:
    Type: AWS::Scheduler::ScheduleGroup
    Condition: ExistInstanceId
    Properties: 
      Name: !Sub ${AWS::StackName}-ec2-schedule-group

  EC2StartSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: ExistStartSchedule
    DependsOn:
      - ScheduleGroup
      - ScheduleRole
    Properties: 
      Description: !Sub ${AWS::StackName}-Start EC2 Instance
      FlexibleTimeWindow: 
        Mode: "OFF"
      GroupName: !Ref ScheduleGroup
      Name: !Sub ${AWS::StackName}-ec2-start-schedule
      ScheduleExpression: !Sub "cron(${StartMinutes} ${StartHours} ? * ${StartDayOfWeek} *)"
      ScheduleExpressionTimezone: "Asia/Tokyo"
      State: "ENABLED"
      Target: 
        Arn: "arn:aws:scheduler:::aws-sdk:ec2:startInstances"
        Input: !Join
          - ""
          - - "{\"InstanceIds\": ["
            - !If [ExistInstanceId, !Sub "\"${InstanceId}\"", ""]
            - "]}"
        RoleArn: !GetAtt ScheduleRole.Arn
        RetryPolicy: 
          MaximumRetryAttempts: 0

  EC2StopSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: ExistStopSchedule
    DependsOn:
      - ScheduleGroup
      - ScheduleRole
    Properties: 
      Description: !Sub ${AWS::StackName}-Stop EC2 Instance
      FlexibleTimeWindow: 
        Mode: "OFF"
      GroupName: !Ref ScheduleGroup
      Name: !Sub ${AWS::StackName}-ec2-stop-schedule
      ScheduleExpression: !Sub "cron(${StopMinutes} ${StopHours} ? * ${StopDayOfWeek} *)"
      ScheduleExpressionTimezone: "Asia/Tokyo"
      State: "ENABLED"
      Target: 
        Arn: "arn:aws:scheduler:::aws-sdk:ec2:stopInstances"
        Input: !Join
          - ""
          - - "{\"InstanceIds\": ["
            - !If [ExistInstanceId, !Sub "\"${InstanceId}\"", ""]
            - "]}"
        RoleArn: !GetAtt ScheduleRole.Arn
        RetryPolicy: 
          MaximumRetryAttempts: 0

YAMLパラメーターの解説

パラメーター名 解説 備考
InstanceId 制御する EC2 のインスタンス ID
StartDayOfWeek 起動する曜日 *,-,SUN,MON,TUE,WED,THU,FRI,SAT
StartHours 起動する時 0 から 23
StartMinutes 起動する分 0 から 59
StopDayOfWeek 停止する曜日 *,-,SUN,MON,TUE,WED,THU,FRI,SAT
StopHours 停止する時 0 から 23
StopMinutes 停止する分 0 から 59

RDS の自動定期起動/停止

YAMLテンプレート

details rds-start-stop.yaml(折り畳んでます)
AWSTemplateFormatVersion: '2010-09-09'
Description: RDS instance start/stop schedule

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Resource Configuration
        Parameters:
          - InstanceId
          - StartDayOfWeek
          - StartHours
          - StartMinutes
          - StopDayOfWeek
          - StopHours
          - StopMinutes

Parameters:
  InstanceId:
    Type: String
    Description: DB Instance ID to start and stop
    ConstraintDescription: Please enter DB Instance ID
# ---Start Parameter--- #
  StartMinutes:
    Type: Number
    Description: Specified minutes starting instances
    ConstraintDescription: Please enter a number of 0-59
    MinValue: 0
    MaxValue: 59
  StartHours:
    Description: Specified hours starting instances
    ConstraintDescription: Please enter a number of 0-23
    Type: Number
    MinValue: 0
    MaxValue: 23
  StartDayOfWeek:
    Type: String
    Description: The day of the week starting instances
    ConstraintDescription: Please enter the day of the week
    AllowedPattern: (\*|SUN|MON|TUE|WED|THU|FRI|SAT)?((,|-)(SUN|MON|TUE|WED|THU|FRI|SAT))?
# ---Stop Parameter--- #
  StopMinutes:
    Type: Number
    Description: Specified minutes starting instances
    ConstraintDescription: Please enter a number of 0-59
    MinValue: 0
    MaxValue: 59
  StopHours:
    Description: Specified hours starting instances
    ConstraintDescription: Please enter a number of 0-23
    Type: Number
    MinValue: 0
    MaxValue: 23
  StopDayOfWeek:
    Type: String
    Description: The day of the week starting instances
    ConstraintDescription: Please enter the day of the week
    AllowedPattern: (\*|SUN|MON|TUE|WED|THU|FRI|SAT)?((,|-)(SUN|MON|TUE|WED|THU|FRI|SAT))?

Conditions:
  ExistInstanceId: !Not [!Equals [!Ref InstanceId, ""]]

  ExistStartSchedule:
    !And
      - !Or
        - !Not [!Equals [!Ref StartDayOfWeek, ""]]
        - !Not [!Equals [!Ref StartHours, ""]]
        - !Not [!Equals [!Ref StartMinutes, ""]]
      - !Condition ExistInstanceId

  ExistStopSchedule:
    !And
      - !Or
        - !Not [!Equals [!Ref StopDayOfWeek, ""]]
        - !Not [!Equals [!Ref StopHours, ""]]
        - !Not [!Equals [!Ref StopMinutes, ""]]
      - !Condition ExistInstanceId

Resources:
  ScheduleRole:
    Type: AWS::IAM::Role
    Condition: ExistInstanceId
    Properties: 
      RoleName: !Sub ${AWS::StackName}-rds-schedule-role
      Path: /
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "scheduler.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: !Sub ${AWS::StackName}-rds-schedule-role-policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement: 
              - Sid: "AllowExecutionOfRDSStartStop"
                Effect: "Allow"
                Action:
                  - rds:StartDBInstance
                  - rds:StopDBInstance
                Resource: "*"
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-rds-schedule-role

  ScheduleGroup:
    Type: AWS::Scheduler::ScheduleGroup
    Condition: ExistInstanceId
    Properties: 
      Name: !Sub ${AWS::StackName}-rds-schedule-group

  RDSStartSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: ExistStartSchedule
    DependsOn:
      - ScheduleGroup
      - ScheduleRole
    Properties: 
      Description: "Start RDS Instance"
      FlexibleTimeWindow: 
        Mode: "OFF"
      GroupName: !Ref ScheduleGroup
      Name: !Sub ${AWS::StackName}-rds-start-schedule
      ScheduleExpression: !Sub "cron(${StartMinutes} ${StartHours} ? * ${StartDayOfWeek} *)"
      ScheduleExpressionTimezone: "Asia/Tokyo"
      State: "ENABLED"
      Target: 
        Arn: "arn:aws:scheduler:::aws-sdk:rds:startDBInstance"
        Input: !Sub |-
          {
            "DbInstanceIdentifier": "${InstanceId}"
          }
        RoleArn: !GetAtt ScheduleRole.Arn
        RetryPolicy: 
          MaximumRetryAttempts: 0

  RDSStopSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: ExistStopSchedule
    DependsOn:
      - ScheduleGroup
      - ScheduleRole
    Properties: 
      Description: "Stop RDS Instance"
      FlexibleTimeWindow: 
        Mode: "OFF"
      GroupName: !Ref ScheduleGroup
      Name: !Sub ${AWS::StackName}-rds-stop-schedule
      ScheduleExpression: !Sub "cron(${StopMinutes} ${StopHours} ? * ${StopDayOfWeek} *)"
      ScheduleExpressionTimezone: "Asia/Tokyo"
      State: "ENABLED"
      Target: 
        Arn: "arn:aws:scheduler:::aws-sdk:rds:stopDBInstance"
        Input: !Sub |-
          {
            "DbInstanceIdentifier": "${InstanceId}"
          }
        RoleArn: !GetAtt ScheduleRole.Arn
        RetryPolicy: 
          MaximumRetryAttempts: 0

YAMLパラメーターの解説

パラメーター名 解説 備考
InstanceId 制御する RDS の DB 識別子
StartDayOfWeek 起動する曜日 *,-,SUN,MON,TUE,WED,THU,FRI,SAT
StartHours 起動する時 0 から 23
StartMinutes 起動する分 0 から 59
StopDayOfWeek 停止する曜日 *,-,SUN,MON,TUE,WED,THU,FRI,SAT
StopHours 停止する時 0 から 23
StopMinutes 停止する分 0 から 59

Aurora の自動定期起動/停止

YAMLテンプレート

details aurora-start-stop.yaml(折り畳んでます)
AWSTemplateFormatVersion: '2010-09-09'
Description: Aurora DB cluster start/stop schedule

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Resource Configuration
        Parameters:
          - ClusterId
          - StartDayOfWeek
          - StartHours
          - StartMinutes
          - StopDayOfWeek
          - StopHours
          - StopMinutes

Parameters:
  ClusterId:
    Type: String
    Description: Cluster ID to start and stop
    ConstraintDescription: Please enter Cluster ID
# ---Start Parameter--- #
  StartMinutes:
    Type: Number
    Description: Specified minutes starting instances
    ConstraintDescription: Please enter a number of 0-59
    MinValue: 0
    MaxValue: 59
  StartHours:
    Description: Specified hours starting instances
    ConstraintDescription: Please enter a number of 0-23
    Type: Number
    MinValue: 0
    MaxValue: 23
  StartDayOfWeek:
    Type: String
    Description: The day of the week starting instances
    ConstraintDescription: Please enter the day of the week
    AllowedPattern: (\*|SUN|MON|TUE|WED|THU|FRI|SAT)?((,|-)(SUN|MON|TUE|WED|THU|FRI|SAT))?
# ---Stop Parameter--- #
  StopMinutes:
    Type: Number
    Description: Specified minutes starting instances
    ConstraintDescription: Please enter a number of 0-59
    MinValue: 0
    MaxValue: 59
  StopHours:
    Description: Specified hours starting instances
    ConstraintDescription: Please enter a number of 0-23
    Type: Number
    MinValue: 0
    MaxValue: 23
  StopDayOfWeek:
    Type: String
    Description: The day of the week starting instances
    ConstraintDescription: Please enter the day of the week
    AllowedPattern: (\*|SUN|MON|TUE|WED|THU|FRI|SAT)?((,|-)(SUN|MON|TUE|WED|THU|FRI|SAT))?

Conditions:
  ExistClusterId: !Not [!Equals [!Ref ClusterId, ""]]

  ExistStartSchedule:
    !And
      - !Or
        - !Not [!Equals [!Ref StartDayOfWeek, ""]]
        - !Not [!Equals [!Ref StartHours, ""]]
        - !Not [!Equals [!Ref StartMinutes, ""]]
      - !Condition ExistClusterId

  ExistStopSchedule:
    !And
      - !Or
        - !Not [!Equals [!Ref StopDayOfWeek, ""]]
        - !Not [!Equals [!Ref StopHours, ""]]
        - !Not [!Equals [!Ref StopMinutes, ""]]
      - !Condition ExistClusterId

Resources:
  ScheduleRole:
    Type: AWS::IAM::Role
    Condition: ExistClusterId
    Properties: 
      RoleName: !Sub ${AWS::StackName}-aurora-schedule-role
      Path: /
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "scheduler.amazonaws.com"
            Action: "sts:AssumeRole"
      Policies:
        - PolicyName: !Sub ${AWS::StackName}-aurora-schedule-role-policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement: 
              - Sid: "AllowExecutionOfAuroraStartStop"
                Effect: "Allow"
                Action:
                  - rds:StartDBCluster
                  - rds:StopDBCluster
                Resource: "*"
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-aurora-schedule-role

  ScheduleGroup:
    Type: AWS::Scheduler::ScheduleGroup
    Condition: ExistClusterId
    Properties: 
      Name: !Sub ${AWS::StackName}-aurora-schedule-group

  AuroraStartSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: ExistStartSchedule
    DependsOn:
      - ScheduleGroup
      - ScheduleRole
    Properties: 
      Description: "Start Aurora Cluster"
      FlexibleTimeWindow: 
        Mode: "OFF"
      GroupName: !Ref ScheduleGroup
      Name: !Sub ${AWS::StackName}-aurora-start-schedule
      ScheduleExpression: !Sub "cron(${StartMinutes} ${StartHours} ? * ${StartDayOfWeek} *)"
      ScheduleExpressionTimezone: "Asia/Tokyo"
      State: "ENABLED"
      Target: 
        Arn: "arn:aws:scheduler:::aws-sdk:rds:startDBCluster"
        Input: !Sub |-
          {
            "DbClusterIdentifier": "${ClusterId}"
          }
        RoleArn: !GetAtt ScheduleRole.Arn
        RetryPolicy: 
          MaximumRetryAttempts: 0

  AuroraStopSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: ExistStopSchedule
    DependsOn:
      - ScheduleGroup
      - ScheduleRole
    Properties: 
      Description: "Stop Aurora Cluster"
      FlexibleTimeWindow: 
        Mode: "OFF"
      GroupName: !Ref ScheduleGroup
      Name: !Sub ${AWS::StackName}-aurora-stop-schedule
      ScheduleExpression: !Sub "cron(${StopMinutes} ${StopHours} ? * ${StopDayOfWeek} *)"
      ScheduleExpressionTimezone: "Asia/Tokyo"
      State: "ENABLED"
      Target: 
        Arn: "arn:aws:scheduler:::aws-sdk:rds:stopDBCluster"
        Input: !Sub |-
          {
            "DbClusterIdentifier": "${ClusterId}"
          }
        RoleArn: !GetAtt ScheduleRole.Arn
        RetryPolicy: 
          MaximumRetryAttempts: 0

YAMLパラメーターの解説

パラメーター名 解説 備考
ClusterId 制御する Aurora クラスター ID
StartDayOfWeek 起動する曜日 *,-,SUN,MON,TUE,WED,THU,FRI,SAT
StartHours 起動する時 0 から 23
StartMinutes 起動する分 0 から 59
StopDayOfWeek 停止する曜日 *,-,SUN,MON,TUE,WED,THU,FRI,SAT
StopHours 停止する時 0 から 23
StopMinutes 停止する分 0 から 59

Cron について

AWS の Cron は、Apache とお作法が違います。
このテンプレートでは、曜日、時、分のみ設定を可能としていますので、以下を参考に試してみてください。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/reference-cron-and-rate-expressions.html

Cron の設定値例

  • 月から金の 9:00 に起動したい
    cron(0 9 ? * MON-FRI *)
  • 月から金の 17:00 に停止したい
    cron(0 17 ? * MON-FRI *)
  • 該当のインスタンスが起動していたら、18:00 に停止したい
    cron(0 18 ? * * *)

確認方法

AWS 管理コンソールの Amazon EventBridge Scheduler で Cron の設定値を確認できます。
次回実行時間も確認できますので、設定値が予定した時間となっているかご確認ください。
設定がうまくいけば、EC2 および RDS、Aurora の起動/停止が制御できます!

注意

  • 例えば 9:00 に起動、9:01 に停止の設定を行った場合、インスタンスの起動に時間がかかり 9:01 時点で起動処理中だったとき、インスタンスの停止が行われませんでした。
    試したところ 10 分ぐらい間をあけて設定すると良さそうです。
    (こんな短時間に起動/停止することはないと思いますが・・・)
  • RDS と Aurora クラスタは 停止から 7 日経過すると自動で再起動する仕様のようです。

まとめ

検証環境は月から金の 9:00 から 17:00 までの利用としたい・・・
EC2 はバッチ処理利用で夜中に 1 時間だけ起動したい・・・
などあると思います。
そういった場合に活用できるかなと思いますので、参考にしてみてください!
この記事が、誰かの役に立てば幸いです。

参考サイト

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?