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?

EventBridge Scheduler だけで Aurora を自動起動・停止する

0
Posted at

背景・目的

開発・検証用の Aurora クラスタを常時稼働させていると、夜間や休日など使っていない時間帯にもコストが発生します。Aurora は停止しておけばコンピューティング料金がかからないため、業務時間外は停止しておくことでコスト最適化できます。

ただし、手動での停止・起動は忘れがちで、運用負荷にもなります。また、Aurora は停止後 7 日経つと自動的に再起動されるため、手動での停止を繰り返す運用は現実的ではありません。
これまでは EventBridge Scheduler から Lambda を経由して RDS API を呼び出す方法で運用していましたが、EventBridge Scheduler の Universal Target Parameter(UTP)を使えば Lambda なしで RDS API を直接呼び出せることを知り、試してみました。

本記事では、UTP を使って Aurora クラスタを平日の業務時間帯のみ自動で起動・停止する仕組みをCloudFormation で構築します。

まとめ

下記に特徴をまとめます。

特徴 説明
ユニバーサルターゲット カスタマイズ可能なパラメータセット
多くの AWS サービスに対して幅広い API オペレーションを呼び出すことができる
UTP ユニバーサルターゲットパラメータ
EventBridgeスケジューラーのUTP 下記を指定する。
・RoleArn
・Arn
・Input
EventBridgeスケジューラーがサポートしてないUTP 基本的には、読み取り専用APIアクションをサポートしてない

概要

下記の記事を基に整理します。

ユニバーサルターゲットはカスタマイズ可能なパラメータセットで、多くの AWS サービスに対して幅広い API オペレーションを呼び出すことができます。例えば、ユニバーサルターゲットパラメータ (UTP) を使用して、CreateQueue オペレーションを使用して新しい Amazon SQS キューを作成できます。

  • ユニバーサルターゲットは、カスタマイズ可能なパラメータセット
  • APIオペレーションを呼び出すことができる
  • UTPは、ユニバーサルターゲットパラメータのこと
  • 例:UTPのCreateQueue オペレーションを使用して新しい Amazon SQS キューを作成できる

AWS CLI または EventBridge スケジューラのいずれかの SDK を使用してスケジュールにユニバーサルターゲットを設定するには、次の情報を指定する必要があります。

  • RoleArn — ターゲットに使用したい実行ロールの ARN。指定する実行ロールには、スケジュールの対象とする API オペレーションを呼び出す権限が必要です。
  • Arn — ターゲットとする API オペレーションを含むサービス ARN 全体を、次の形式で示します: arn:aws:scheduler:::aws-sdk:service:apiAction
    例えば、Amazon SQS の場合、指定するサービス名は arn:aws:scheduler:::aws-sdk:sqs:sendMessage です。
  • Input — EventBridge スケジューラがターゲット API に送信するリクエストパラメータで指定する、正しい形式の JSON。Input に設定する JSON のパラメータと形状は、スケジュールが呼び出すサービス API によって決まります。この情報については、対象とするサービスの API リファレンスをご覧ください。
  • CLIまたは、EventBridgeスケジューラのいずれかのSDKを使用してスケジュールにユニバーサルターゲットを設定するには、下記の情報を指定する必要がある

  • RoleArn

    • ターゲットを使用した実行ロールのARN
  • Arn

    • ターゲットとするAPIオペレーションを含むサービスARN全体を指定する
  • Input

    • EventBridgeスケジューラがターゲットAPIに送信するリクエストパラメータで指定する
    • JSON形式

EventBridge スケジューラは、以下のプレフィックスのリストで始まる一般的な GET オペレーションなどの読み取り専用 API アクションをサポートしていません。

  • 読み取り専用APIアクションをサポートしてない

実装

前提

すでに作成していた、Auroraクラスタを使用します。
image.png

IaC (Cfn)の作成

1.下記のようにテンプレートを作成します

  • パラメータ
    • ClusterName:Auroraクラスタ名
    • Environment:環境を指定
  • リソース
    • Role:Auroraの起動と停止ができるロール
  • スケジューラー
    • 起動:平日の8:50
    • 停止:平日の20:00
AWSTemplateFormatVersion: '2010-09-09'
Description: Aurora Cluster Start/Stop Scheduler (UTP Direct)

Parameters:
  ClusterName:
    Type: String
    Description: Aurora DB Cluster Identifier
  Environment:
    Type: String
    AllowedValues: [dev]

Conditions:
  IsDev: !Equals [!Ref Environment, dev]

Resources:
  SchedulerExecutionRole:
    Type: AWS::IAM::Role
    Condition: IsDev
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: scheduler.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: AuroraStartStop
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - rds:StartDBCluster
                  - rds:StopDBCluster
                Resource: !Sub arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:${ClusterName}

  StartSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: IsDev
    Properties:
      Name: !Sub ${ClusterName}-start
      ScheduleExpression: cron(50 8 ? * MON-FRI *)
      ScheduleExpressionTimezone: Asia/Tokyo
      FlexibleTimeWindow:
        Mode: 'OFF'
      Target:
        Arn: arn:aws:scheduler:::aws-sdk:rds:startDBCluster
        RoleArn: !GetAtt SchedulerExecutionRole.Arn
        Input: !Sub '{"DbClusterIdentifier": "${ClusterName}"}'
        RetryPolicy:
          MaximumRetryAttempts: 0

  StopSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: IsDev
    Properties:
      Name: !Sub ${ClusterName}-stop
      ScheduleExpression: cron(0 20 ? * MON-FRI *)
      ScheduleExpressionTimezone: Asia/Tokyo
      FlexibleTimeWindow:
        Mode: 'OFF'
      Target:
        Arn: arn:aws:scheduler:::aws-sdk:rds:stopDBCluster
        RoleArn: !GetAtt SchedulerExecutionRole.Arn
        Input: !Sub '{"DbClusterIdentifier": "${ClusterName}"}'
        RetryPolicy:
          MaximumRetryAttempts: 0

デプロイ

1.下記のコマンドでデプロイします

aws cloudformation create-stack --stack-name aurora-cluster-scheduler --template-body file://XXXX/aurora-cluster-scheduler.yaml --parameters file://XXXX/params/dev/aurora-cluster-scheduler.json --capabilities CAPABILITY_IAM

2.完了しました
image.png

リソースの確認

  1. EventBridgeに移動します
  2. ナビゲーションペインのスケジューラー>スケジュールをクリックします
  3. 2つのスケジューラーが作成されていました
    image.png

起動スケジューラーの確認

  1. dms-target-aurora-startをクリックします

  2. ターゲットタブをクリックします。想定通りのAPIおよび、対象となるAuroraクラスタ名が設定されていました image.png

  3. スケジュールタブをクリックします。月〜金の8:50に起動します。想定通りです
    image.png

停止スケジューラーの確認

  1. dms-target-aurora-stopをクリックします
  2. ターゲットタブをクリックします。想定通りのAPIおよび、対象となるAuroraクラスタ名が設定されていました
    image.png
  3. スケジュールタブをクリックします。月〜金の20:00に停止します。想定通りです
    image.png

停止の動作確認

動作確認するため、停止スケジューラーを修正します。

起動確認はしていません

実行前の確認

  1. Auroraクラスタは、起動されています
    image.png

修正とデプロイ

1.スケジューラーを修正します(月〜金:20:00から、毎日17:35 に変更しました)

  StopSchedule:
    Type: AWS::Scheduler::Schedule
    Condition: IsDev
    Properties:
      Name: !Sub ${ClusterName}-stop
      ScheduleExpression: cron(35 17 ? * * *)

2.スタックを更新します

aws cloudformation update-stack --stack-name aurora-cluster-scheduler --template-body file://XXXX/aurora-cluster-scheduler.yaml --parameters file://XXXX/params/dev/aurora-cluster-scheduler.json --capabilities CAPABILITY_IAM

3.スケジュールが変更されました
image.png

動作確認

停止を設定した時刻の17:35になったので確認します。

1.Auroraが停止中になりました
image.png

2.CloudTrailでAPI実行を確認します

aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=StopDBCluster --max-results 1 --output json

3.StopDBClusterが、dms-target-auroraに対して、AmazonEventBridgeSchedulerから実行されたことが確認できました(必要な箇所のみ抜粋しています)

{
    "Events": [
        {
            "EventName": "StopDBCluster",
            "EventTime": "2026-03-29T17:35:24+09:00",
            "EventSource": "rds.amazonaws.com",
            "CloudTrailEvent": "{・・・
            "userAgent\":\"AmazonEventBridgeScheduler XXXXX"
            ・・・・
            requestParameters": {"dBClusterIdentifier": "dms-target-aurora"} 

4.Auroraクラスタのステータスが「一時的に停止済み」になりました
image.png

5.Auroraクラスタのログとイベントをクリックします
6.「最近のイベント」では17:47に、システムノートに「DB cluster stopped」が記録されました。
image.png

考察

UTP は Lambda が不要でリソース数が少なくシンプルですが、運用面で今回の検証で気になったいくつかの留意点があります。

  • EventBridge Scheduler 自体の実行履歴を確認する API がなく、CloudTrail の userAgent から間接的に確認する必要がある(確認方法が複雑)
  • RetryPolicy はエラーの種類で分岐できない。既に停止済みのエラーも、一時的なネットワークエラーも同じ扱いになると考えられる(柔軟性がない)
  • Lambda 経由と比べて、通知や条件分岐などの拡張がしにくい(柔軟性がない)

Lambda 経由との比較

以下に Lambda 経由との比較と、運用上のポイントを整理します。

項目 UTP (今回) Lambda 経由
リソース数の少なさ
Scheduler × 2 + IAM Role

Scheduler × 2 + Lambda + IAM Role × 2
実行時の確認
CloudTrail から間接的に確認

LambdaでCloudWatch Logs に出力する
エラーハンドリング
RetryPolicy のみ

Lambda 内で自由に実装可能
拡張性
API 呼び出しのみ

通知・条件分岐など追加しやすい

運用上のポイント

UTP と Lambda 経由のどちらを採用するかは、運用要件次第と考えます。

  • 開発・検証環境のコスト削減が目的であれば、UTP 直接パターンで十分
  • 失敗時の即時通知や、停止前の接続確認などが必要な場合は Lambda 経由を検討する

参考

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?