💡

cronやEventBridge Schedulerとは別の方法で休日祝日のカレンダーに応じたEC2の起動/停止をやってみた

2024/12/24に公開

はじめに

AWSなどのクラウドを利用する際、リソースを必要な時だけ使いたいといった要望があるかと思います。例えば、EC2を使い社内システムを運用している場合、EC2を会社の営業日にあわせて起動/停止したいというケースはありませんか?
定期実行であればcronやAmazon EventBridge Schedulerの使用が考えられます。この場合、規則的な繰り返しは簡単に設定できますが、祝日や会社の休日に配慮した例外的な対応を考慮すると、定義の作成に工夫が必要です(※)。
※例えばAWS Step FunctionsとAWS Systems Manager Change Calendarを連携する方法がありますが、ジョブを“実行する”ためのカレンダーと“実行しない”ためのカレンダーの作成や、ワークフローの設計が必要になります。
[AWS Step Functions] AWS Systems Manager Change Calendarと連携して定期実行処理のイレギュラーケースに対応してみた | DevelopersIO (classmethod.jp)

クラウド型ジョブスケジューラーサービスを使うと、GUIから簡単にカレンダーを作成し、業務の実行予定に合わせてスケジューリングすることができます。
スケジュールにしたがってAmazon EventBridgeにイベントを送信することで、クラウド上の業務アプリケーションなどの自動実行が可能になります。
ZennPic1_gaiyou.png
実際に、以下のケースを試してみました。
- EC2を毎日10時に起動、17時に停止する。
- 週末(土日)や、祝日、年末年始などの長期休みは、利用しない(起動しない)。
ZennPic2_case.png

やること

クラウド型ジョブスケジューラーサービスでやること

  • カレンダーの作成
  • イベント送信先の作成
  • ジョブの作成とスケジューリング

AWSでやること

  • Amazon EventBridgeの設定

カレンダーの作成

まず始めに、クラウド型ジョブスケジューラーサービスにサインインして、祝日や会社の休日を反映したカレンダーを設定していきます。カレンダーは[カレンダー作成]画面から作成します。
休業日は、チェックボックスによる曜日や日本の祝日の一括設定や、日付クリックによる個別設定が可能です。サンプルでは、土日や、日本の祝日、年末年始などの長期休み(12/30~1/3)を休業日に設定します。
ZennPic3_Calendar.png

スケジューリングと実行

作成したカレンダーを使い、業務の実行予定に合わせてスケジューリングします。
具体的には、クラウド型ジョブスケジューラーサービスでは「イベント送信先」と「ジョブ」の作成、AWSではEventBridgeの設定をします。

イベント送信先の作成

使用中のAWS環境をクラウド型ジョブスケジューラーサービスと連携するため、イベント送信先を設定していきます。イベント送信先は[イベント送信先作成]画面から作成します。
作成にはアカウントIDとリージョン情報が必要です。サンプルでは、イベント送信先としてEC2eventを作成します。
ZennPic4_ETarget.png

Amazon EventBridgeの設定

AWSコンソールにサインインして、EC2の起動/停止をするために、作成したイベント送信先(EC2event)をアクティブ化しイベントバスとルールを設定していきます。

  1. パートナーイベントソースのページを開き、作成したパートナーイベントソースを選択する
    ZennPic5_EB1.png
  2. イベントバスとの関連付けをする
    ZennPic6_EB2.png
    ZennPic7_EB3.png
    パートナーイベントソースがイベントバスに関連付けされ、アクティブになりました。
    ZennPic8_EB4.png
  3. ルールのページを開き、[イベントバス]に関連付けたイベントバスを選択し、ルールを作成する
    ZennPic9_EB5.png
  4. ルールを設定する
    サンプルでは、EC2の起動/停止をするため、ルールを2件作成します。ルールでは以下の項目を設定します。
  • イベントバス:関連付けたイベントバスを選択する
    1件目(起動)の設定値:aws.partner/hitachi-solutions.co.jp/JobSaaS/customer-test.EC2event
    2件目(停止)の設定値:aws.partner/hitachi-solutions.co.jp/JobSaaS/customer-test.EC2event
    ZennPic10_EB6.png

  • イベントパターンの定義:"source"と"jobName"に、イベントバスとジョブ名を入力する。ジョブ名は、後ほど「ジョブ」の作成で使用する
    1件目(起動)の設定値:

        {
          "source": ["aws.partner/hitachi-solutions.co.jp/JobSaaS/customer-test.EC2event"],
          "detail-type": ["execJob"],
          "detail": {
            "jobName": ["EC2Start"]
          }
        }
    

    2件目(停止)の設定値:

        {	
          "source": ["aws.partner/hitachi-solutions.co.jp/JobSaaS/customer-test.EC2event"],
          "detail-type": ["execJob"],
          "detail": {
            "jobName": ["EC2Stop"]
          }
        }
    

    ZennPic11_EB7.png

  • ターゲット:実行対象を選択する
    1件目(起動)の設定値:StartEC2(Lambda関数)※
    2件目(停止)の設定値:EC2 StopInstances API 呼び出し
    ※EC2を起動するLambda関数の作成方法については、補足を参照してください。
    ZennPic12_EB8.png
    ルールを2件作成したら、Amazon EventBridgeの設定は完了です。
    ZennPic13_EB9.png

ジョブの作成とスケジューリング

クラウド型ジョブスケジューラーサービスに戻り、EC2の起動/停止を実行するため、ジョブを2件設定していきます。ジョブは[ジョブ作成]画面から作成します。
[イベント送信先]と[参照するカレンダー]に作成済みのものを設定することで、祝日や会社の休日を考慮した、ジョブのスケジューリングと実行ができます。
ZennPic14_Job1.png
[ジョブの実行予定の作成]でスケジューリングの設定をします。サンプルでは、毎日10時実行で設定します。
[カレンダーの休業日とジョブの実行予定が重なった場合の動作]で[休業日は予定を実行しない]を選択することで、業務カレンダーで定めた休業日は、ジョブが実行されなくなります。
ZennPic15_Job2.png
[作成]をクリックするとジョブが作成されます。同様に、ジョブ名と開始時刻を変更し、EC2の停止を実行するジョブを作成します。
ZennPic16_Job3.png

実行結果の確認

ジョブの実行結果は、ジョブ一覧画面で確認できます。
ZennPic17_Result1.png
ジョブが正常終了したため、実際にAWSコンソールに戻り、EC2を確認すると、起動/停止できていました。
ZennPic18_Result2.png
さらに、クラウド型ジョブスケジューラーサービスでジョブをクリックし[ジョブ詳細]画面を開くと、マンスリーカレンダーで結果と予定を確認できます。正常終了の場合は、黄緑色のアイコンが表示されます。
ZennPic19_Result3.png

まとめ

祝日や会社の休日に配慮した例外的な対応も、クラウド型ジョブスケジューラーサービスを使うと、GUIから簡単に設定できます。
本記事では、実際に休日祝日のカレンダーに応じたEC2の起動/停止をやってみました。手順をまとめると、以下のようになります。

  1. 祝日や会社の休日を反映したカレンダーを作成する
  2. イベント送信先を作成し、Amazon EventBridgeの設定をする
  3. ジョブを作成し、業務の実行予定に合わせてスケジューリングを設定する

おわりに

いかがでしたでしょうか?EC2の管理について自動化する機会がありましたので、記事を作成しました。みなさんのお役に立てればと思います。

参考リンク

補足

EC2を起動するLambda関数の作成方法
以下の設定でLambda関数を作成します。

  1. 設定値に以下を入力し、[関数の作成]をクリックする
    • オプション: 一から作成
    • 関数名: StartEC2
    • ランタイム: python3.12
  2. 作成されたLambda(StartEC2)を開く
  3. [コード]タブを開き、以下を入力(regionは環境に合わせて変更)し、[Deploy]をクリックする
    import boto3
    import os
    
    region = 'ap-northeast-1'
    instances = [os.environ['INSTANCE_ID']]
    ec2 = boto3.client('ec2', region_name=region)
    
    def lambda_handler(event, context):
        ec2.start_instances(InstanceIds=instances)
        print('started your instances: ' + str(instances))
    
  4. [設定]タブ-[環境変数]を開き、以下を追加する
    • キー:INSTANCE_ID
    • 値:起動対象EC2のインスタンスID
  5. [設定]タブ-[アクセス権限]を開き、[ロール名]に表示されているロールをクリックし、ロール画面を開く
  6. [許可を追加]をクリックし、AmazonEC2FullAccessを追加する

以上で、関数の作成は完了です。
作成されたLambda(StartEC2)を開き、[テスト]タブから、以下を入力し[テスト]を実行します。正常終了したら正しく作成できています。

  • イベント名:test
  • EventJSON: {"Action": "Start"}

Discussion