EventBridgeスケジューラでRedshift Serverlessのスナップショットを作成するCloudFromationテンプレートを作成してみた

2023.07.20

データアナリティクス事業本部のueharaです。

今回は、EventBridgeスケジューラでRedshift Serverlessのスナップショットを作成するCloudFromationテンプレートを作成してみたいと思います。

はじめに

Redshift Serverlessはデフォルトで復旧ポイントが30分ごとに作成されますが、保持期間は24時間となっています。

したがって、例えば「バックアップを7日間保持したい」というケースであれば定期バックアップの仕組みを自前で用意する必要があります。

今回はEventBridgeスケジューラを利用した非常にシンプルな構成で、定期バックアップを設定する方法をご紹介したいと思います。(※Lambda不要)

CloudFormationテンプレートの作成

コード

早速ですが、実行するCloudFormationのテンプレートは以下の通りです。

eventbridge-scheduler.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description: "EventBridge Scheduler for snapshot of Redshift Serverless"

Parameters:
  NamespaceName:
    Type: String
  SnapshotName:
    Type: String
  RetentionPeriod:
    Type: Number
    Default: 7
  ScheduleSnapTime:
    Type: String
    Default: "cron(0 21 * * ? *)"
  ScheduleTimezone:
    Type: String
    Default: Japan

Resources:
  # ------------------------------------------------------------#
  # EventBridge Scheduler
  # ------------------------------------------------------------# 
  ScheduleRedShiftServerlessSnap:
    Type: AWS::Scheduler::Schedule
    Properties:
      Name: !Sub '${NamespaceName}-snap-schedule'
      Description: Redshift Serverless Snapshot
      ScheduleExpression: !Ref ScheduleSnapTime
      ScheduleExpressionTimezone: !Ref ScheduleTimezone
      FlexibleTimeWindow:
        Mode: "OFF"
      State: ENABLED
      Target:
        Arn: arn:aws:scheduler:::aws-sdk:redshiftserverless:createSnapshot
        Input: !Sub |-
          {
            "NamespaceName": "${NamespaceName}",
            "RetentionPeriod": ${RetentionPeriod},
            "SnapshotName": "${SnapshotName}-<aws.scheduler.execution-id>"
          }
        RoleArn:
          Fn::GetAtt:
            - SchedulerRedshiftServerlessSnapRole
            - Arn

  # ------------------------------------------------------------#
  # IAM Role
  # ------------------------------------------------------------#   
  SchedulerRedshiftServerlessSnapRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${NamespaceName}-snap-role"
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - scheduler.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      Policies:
        - PolicyName: redshift-serverless-snap
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "redshift-serverless:ConvertRecoveryPointToSnapshot"
                  - "redshift-serverless:CreateSnapshot"
                  - "redshift-serverless:DeleteSnapshot"
                  - "redshift-serverless:GetSnapshot"
                  - "redshift-serverless:ListSnapshots"
                  - "redshift-serverless:UpdateSnapshot"
                Resource:
                  - "*"

パラメーターについて

スタック作成時に設定するパラメーターは以下の通りです。

パラメーター 設定値
NamespaceName スナップショットを作成したいRedshift Serverlessの名前空間(Namespace)を設定
SnapshotName 作成するスナップショットの名前を設定
RetentionPeriod スナップショットを保持する期間(日)を設定
ScheduleSnapTime スナップショットを作成するタイミングをcron形式で設定
ScheduleTimezone スケジュールする時間のTimezoneを設定

デフォルト値としてテンプレートに記載しているRetentionPeriod7で、ScheduleSnapTime"cron(0 21 * * ? *)"であれば、毎晩21時に7日間保持するスナップショットを作成するという挙動になります。

動作確認

CloudFormation実行すると、EventBridgeとその実行ロールの2つのリソースが作成されます。

指定時間になると、設定した保持期間でしっかりスナップショットが作成されていることを確認できました。

ハマったところ

Targetの設定について

Redshift ServerlessのユニバーサルターゲットのService integration ARNは、こちらのページに記載の通り arn:aws:scheduler:::aws-sdk:redshiftserverless:[apiAction] となっています。

Redshift Serverlessでスナップショットを作成するAPIは CreateSnapshot になるのですが、 arn:aws:scheduler:::aws-sdk:redshiftserverless:CreateSnapshot をTargetに設定するとCloudFormation実行時に以下のようなエラーが発生します。

Invalid request provided: Invalid RequestJson provided. Reason The api CreateSnapshot is not valid for the service aws-sdk:redshiftserverless. (Service: Scheduler, Status Code: 400, Request ID: xxx)

どうやら、実行するAPIは CreateSnapshot ですが、 createSnapshot と頭文字を小文字で指定する必要があるようです。

スナップショット名について

CreateSnapshotでスナップショットを作成する際に、既に同名のスナップショットがある場合は ConflictException が発生します。

EventBridgeとRedshift Serverlessの間にLamndaを挟んでいればスナップショット名をLamnda内で任意に設定してAPIに渡すことができるのですが、今回はLamndaを利用しない構成にしているので、スナップショット名を一意にするために以下のように設定しています。

${SnapshotName}-<aws.scheduler.execution-id>

aws.scheduler.execution-id はEventBridge Schedulerで利用てきるコンテキスト属性で、EventBridge SchedulerがTargetの起動の際に割り当てる一意のIDになります。

これにより、スナップショット名は ${SnapshotName}-3f64b7b8-5898-4fbc-b239-abe5f3f4eab9 のような形となり、一意にすることができます。

※参考

最後に

今回は、EventBridgeスケジューラでRedshift Serverlessのスナップショットを作成するCloudFromationテンプレートを作成してみました。

参考になりましたら幸いです。

参考文献