EventBridge Schedulerを使ったVMの自動on/off設定をCloudFormationを使って設定するには以下のClassmethodさんの記事を見れば一通り実装できます。
ここではTerraformを使った実装についてのまとめ。
こうしたらうまくいった、という感じの内容なので、コードの解説はほぼ無いです。
※ 実際に使ってるコードをコピペして変数をblog用に更新してるので、辻褄が合ってない箇所がもしあったらゴメンナサイ
EventBridgeスケジューラ用IAMロールの作成
CloudFormationだとこんな感じ(YAML)
SchedulerEC2StopStartRole: # Start/Stop by EventBridge用IAMロール 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: - "*"
これをTerraformで書くとこんな感じ。
使うのはaws_iam_role
リソース。
resource "aws_iam_role" "stopstart_role" { name = "ec2-stop-start-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "scheduler.amazonaws.com" } }, ] }) path = "/" inline_policy { name = "start_stop_policy" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = ["ec2:StartInstances", "ec2:StopInstances"] Effect = "Allow" Resource = "*" }, ] }) } }
name
はドキュメントにはOptional
と書かれてて実際無くてもTerraform的にデプロイはできるんだけど、リソースが作られなかったので実質必須。
自動停止のスケジューラ設定
EC2を自動停止するスケジューラ設定。
CloudFormationだとこんな感じ。(YAML)
InstanceIds
に対象EC2を指定。
毎日17時25分に停止するには以下の通り。
ScheduleEC2Stop: # EC2の停止EventBridge Type: AWS::Scheduler::Schedule Properties: Name: ec2-stop Description: Stop EC2 Instance ScheduleExpression: cron(25 17 * * ? *) ScheduleExpressionTimezone: Japan FlexibleTimeWindow: Mode: "OFF" State: ENABLED Target: Arn: arn:aws:scheduler:::aws-sdk:ec2:stopInstances Input: !Sub |- { "InstanceIds": ["${Server1}", "${Server2}", "${Server3}"] } RoleArn: Fn::GetAtt: - SchedulerEC2StopStartRole - Arn
これをTerraformで書くとこんな感じ。
使うのはaws_scheduler_schedule
リソース。
resource "aws_scheduler_schedule" "schedule_stop" { name = "ec2-stop" group_name = "default" flexible_time_window { mode = "OFF" } schedule_expression = "cron(25 17 * * ? *)" schedule_expression_timezone = "Japan" target { arn = "arn:aws:scheduler:::aws-sdk:ec2:stopInstances" role_arn = aws_iam_role.stopstart_role.arn input = jsonencode({ InstanceIds = ["${aws_instance.server1.id}", "${aws_instance.server2.id}", "${aws_instance.server3.id}"] }) } }
自動起動のスケジューラ設定
最後にEC2を自動起動するスケジューラ設定。
CloudFormationだと(ry
毎朝8時45分に起動する設定。
ScheduleEC2Start: # EC2の開始EventBridge Type: AWS::Scheduler::Schedule Properties: Name: ec2-start Description: Start EC2 Instance ScheduleExpression: cron(45 8 * * ? *) ScheduleExpressionTimezone: Japan FlexibleTimeWindow: Mode: "OFF" State: ENABLED Target: Arn: arn:aws:scheduler:::aws-sdk:ec2:startInstances Input: !Sub |- { "InstanceIds": ["${Server1}", "${Server2}", "${Server3}"] } RoleArn: Fn::GetAtt: - SchedulerEC2StopStartRole - Arn
これをTerraformで書くとこんな感じ。
使うのは停止と同様にaws_scheduler_schedule
リソース。
resource "aws_scheduler_schedule" "schedule_start" { name = "ec2-start" group_name = "default" flexible_time_window { mode = "OFF" } schedule_expression = "cron(45 8 * * ? *)" schedule_expression_timezone = "Japan" target { arn = "arn:aws:scheduler:::aws-sdk:ec2:startInstances" role_arn = aws_iam_role.stopstart_role.arn input = jsonencode({ InstanceIds = ["${aws_instance.server1.id}", "${aws_instance.server2.id}", "${aws_instance.server3.id}"] }) } }
(おまけ)cron式で「平日のみ」にする場合
業務で使う場合だと、毎日起動でなく平日だけ起動にしたい場合がほとんどだと思う。
その場合はこのように書けば「月曜から金曜」になる。
cron(45 8 ? * MON-FRI *)