目次
はじめに
こんにちは、omkです。
EventBridge Scheduler、いいですよね。
EventBridge RuleからLambdaをキックしてAWS SDKで……という従来のやり方から変わってLambdaを管理せずに多くのAWSリソースを操作出来るようになった点でかなりありがたく思っています。
コードの品質とかランタイムの期限とか面倒ですからねぇ。
そんなわけでCFnでSchedulerを作っていこうと思ったのですが、2022年12月16日現在のドキュメントではまだ充実しておらず、サンプルも無くて具体的にどんな値を入れたらよいのかというイメージがしづらく感じました。
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-scheduler-schedule.html
とりあえずCLIのhelpから紐解いて作ってみました。あとこの辺参考にしてます。
https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-schedule-flexible-time-windows.html
https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-schedule-state.html
他にも困っている方がいるかもしれませんのでドキュメントにサンプルが追加されるまで参考にしてもらえるものを用意できたらと思います。
CFnテンプレート上でやること
- AWS SDK(ユニバーサルターゲット)でEC2を起動する・停止する2種類のスケジュールを作成
- スケジュールグループを作成
- スケジュールで利用するIAMロール・ポリシーを作成
できたもの
AWSTemplateFormatVersion: '2010-09-09'
Description: Scheduler Template
Parameters:
InstanceId:
Type: String
Mappings:
EventSchedule:
EC2:
StartCron: "cron(0 9 * * ? *)"
StopCron: "cron(0 19 * * ? *)"
Resources:
ScheduleRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "scheduler.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
RoleName: blog-schedule-ec2-role
ScheduleRolePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": !Sub "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/${InstanceId}"
}
]
}
PolicyName: "blog-schedule-ec2-role-policy"
Roles:
- !Ref ScheduleRole
ScheduleGroup:
Type: AWS::Scheduler::ScheduleGroup
Properties:
Name: "blog-schedule-group"
EC2StartSchedule:
Type: AWS::Scheduler::Schedule
Properties:
Description: "Start EC2 Instance"
FlexibleTimeWindow:
Mode: "OFF"
GroupName: !Ref ScheduleGroup
Name: "blog-ec2-start-schedule"
ScheduleExpression: !FindInMap [ EventSchedule, EC2, StartCron ]
ScheduleExpressionTimezone: "Asia/Tokyo"
State: "ENABLED"
Target:
Arn: "arn:aws:scheduler:::aws-sdk:ec2:startInstances"
Input: !Sub "{ \"InstanceIds\": [ \"${InstanceId}\" ] }"
RoleArn: !GetAtt ScheduleRole.Arn
RetryPolicy:
MaximumRetryAttempts: 0
EC2StopSchedule:
Type: AWS::Scheduler::Schedule
Properties:
Description: "Stop EC2 Instance"
FlexibleTimeWindow:
Mode: "OFF"
GroupName: !Ref ScheduleGroup
Name: "blog-ec2-stop-schedule"
ScheduleExpression: !FindInMap [ EventSchedule, EC2, StopCron ]
ScheduleExpressionTimezone: "Asia/Tokyo"
State: "ENABLED"
Target:
Arn: "arn:aws:scheduler:::aws-sdk:ec2:stopInstances"
Input: !Sub "{ \"InstanceIds\": [ \"${InstanceId}\" ] }"
RoleArn: !GetAtt ScheduleRole.Arn
RetryPolicy:
MaximumRetryAttempts: 0
ポイント
まずはスケジュールで利用するIAMロールについて、信頼されたエンティティに入れるサービス名は「scheduler.amazonaws.com」です。
次に本題ですがスケジュールについてです。
「FlexibleTimeWindow」の「Mode」で取る値ですが、フレックスタイムウィンドウを利用する場合は「FLEXIBLE」、利用しない場合は「OFF」を取ります。
上では「Mode: "OFF"」と入れていますが、OFFをダブルクォーテーションで囲っておかないとCFn実行時にエラーが出るので注意です。
「State」の値は「ENABLED」「DISABLED」のいずれかです。全大文字なので注意(ドキュメントには小文字で書かれているが取る値として書かれているわけではない)です。
あと「Target」の「Arn」は何を入れるんだというところですが、今回はAWS SDKのユニバーサルターゲットを作成するのでSDKのARNが入ります。
ここの書き方が全然載っていないように思えたのでちょっと苦労しました。
「Input」はSDKが取る引数(コンパネでいうところのペイロード)が入ります。
「RetryPolicy」はデフォルトで「イベントの最大保持時間: 1日」、「最大再試行回数: 185 回」の設定が入ります。
再試行しない場合は明記する必要があります。
その際は、「MaximumRetryAttempts」に0を入れる必要があり、「MaximumEventAgeInSeconds」は指定しない必要があります(入れるとエラーでます)。
おわりに
分かりづらかったところはこんな感じかなと思いますがもし他にもありましたらコメントに書いていただけると分かる範囲で回答します。
最後までお付き合いありがとうございました。
アーキテクト課のomkです。
AWSについて雑多に取り組んだ内容を発信しています!!