はじめに
検証環境など限られた予算で実行しなければいけない場合、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 時間だけ起動したい・・・
などあると思います。
そういった場合に活用できるかなと思いますので、参考にしてみてください!
この記事が、誰かの役に立てば幸いです。