Redshift Serverless を EventBridge と Lambda で定期バックアップをしてみた

# はじめに

Redshift Serverless の定期バックアップについての記事です。Redshift Serverless の復旧ポイントは、デフォルトで 30 分ごとに作成され、24 時間保存されます。

引用 : https://docs.aws.amazon.com/ja_jp/redshift/latest/mgmt/serverless-snapshots-recovery.html

> Amazon Redshift サーバーレスの復旧ポイントは 30 分ごとに作成され、24 時間保存されます。



データのバックアップが 24 時間の保存で十分な場合は、何も気にしないで Redshift Serverless を利用頂ければ良いです。対して、1 か月データをバックアップしたい、といった要望がある場合は、EventBridge と Lambda を組み合わせて、定期的な自動バックアップを構成できます。

この記事では、Redshift Serverless の自動バックアップの設定方法を紹介します。



# 構成図

ざっくりとした概要図です。

- EventBridge Scheduler で、後続の Lamnda 関数を定期的に実行
- Lambda 関数として、独自の Python プログラムを動かす。AWS SDK を同梱していて、Redshift Serverless に Snapshot 作成の命令を出す
- retentionPeriod の指定で、保持期間を指定。何も指定しないと無期限に保持する。

![image-20230328222713326.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c2c28f71-7a91-7304-4235-86bc85c0fb8f.png)



この構成を作っていきましょう。



# Lambda 関数の作成

この手順では、AWS Serverless Application Model (AWS SAM) で Lambda 関数を作っていきます。手元の環境にインストールされていない場合は、適当にインストールしましょう。

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/install-sam-cli.html



プロジェクトを作成します。

```
sam init
```



出来上がったプロジェクトディレクトリ内にある requirements.txt に boto3 を追加します。

```
requests
boto3
```



Lambda 関数のソースコードを以下のように指定します。異常系の処理は気にせず、シンプルなつくりにしています。本番環境では、より丁寧な実装をしていきましょう。

```python
import json
import boto3
import datetime
from logging import getLogger, INFO

logger = getLogger(__name__)
logger.setLevel(INFO)

# Redshift Serverless のクライアントを生成
client = boto3.client('redshift-serverless')

# スナップショットを取りたい Redshift Serverless の Namespace 名を指定
namespaceName = "snapshot-test01"

def lambda_handler(event, context):
    print("============ print event ============")
    logger.info(json.dumps(event))

    # スナップショットの名前に、日付を付与
    dt_now = datetime.datetime.now()
    snapshotName = "snapshot-" + dt_now.strftime('%Y-%m-%d-%H-%M')

    # スナップショットを取得
    response = client.create_snapshot(
        namespaceName=namespaceName,
        retentionPeriod=2,
        snapshotName=snapshotName
    )

    print("============ print response ============")
    print(response)

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello this is response",
        }),
    }
```



sam cli を使ってデプロイをします。

```
sam build
sam deploy --no-confirm-changeset
```



Lambda 関数が作成されました。

![image-20230328204712354.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/4515f03c-b72e-8948-b2a4-009b56ab0514.png)



# IAM Role の権限変更

SAM で作成した状態だと、Lambda 関数の IAM Role に権限が不足しているため、追加をします。IAM Role をクリックします。

![image-20230328211946143.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/22915645-6af5-aee7-714c-f6436e182162.png)



Attach policies を押します。

![image-20230328212021861.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/2ed06527-d1f7-301f-0755-910d6a84eede.png)



AmazonRedshiftFullAccess を指定して、Add permissions を押します。

![image-20230328212113259.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/7bd82239-aa41-d8a4-dd25-2bc1374c381f.png)





# EventBridge による定期実行

次に、定期実行のために EventBridge Scheduler を作成します。

![image-20230328205248615.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/45d0e3a9-f298-44ab-10fd-fff0f1074b09.png)



適当に名前を指定します。

![image-20230328205533240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e3dff088-23d8-eb8c-904f-a7c8d444a540.png)



10 分に 1 回動くように、Cron ライクな指定をします。
※ Redshift の Service Quota に書かれている Snapshot の上限はデフォルトで 20 までです。上限緩和は可能ですが、実際の本番環境では、1 日 1 回みたいなタイミングで取得されると思います。
https://docs.aws.amazon.com/redshift/latest/mgmt/amazon-redshift-limits.html

![image-20230328220040342.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/d1629d86-f183-fa42-3430-c583ec0ac4d6.png)



このまま Next を押します。

![image-20230328205618159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/8a7945a8-a649-6194-c42b-12a9d4d364ff.png)



動かすターゲットを指定します。色々あるのですが、今回は Lambda 関数を動かしたいので、Lambda の invoke を指定します。

![image-20230328210522725.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/a1dac8f4-7330-28d1-5ea1-dd36b4f6a1c7.png)



動かしたい Lambda 関数の名前を指定して、Next を押します。

![image-20230328210547092.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/0bbec4a0-577a-5822-29a0-51e11ae3a639.png)



デフォルトのまま Next

![image-20230328210613025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/3d6e455a-f2bc-ba26-228f-dbe6279896b6.png)



Create Schedule を押します。

![image-20230328210627636.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/d6306710-7d29-7b73-6188-18dd1985dc9b.png)



Schedule が作成されました

![image-20230328211755989.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/b59007ff-cce2-a669-009a-f71e6e447412.png)



# 動作確認

EventBridge 経由で、Lambda が稼働し、Snapshot が定期作成されている様子が見えます。

![image-20230328224206460.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/685288b9-b23e-f57c-bd07-509fcd7ed74b.png)



Lambda 側の実行ログを見ると、定期実行されている様子が見えます。

![image-20230328224315065.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/89299652-f183-9548-3f03-07f9ff6668b8.png)



# 付録1: AWS CLI でバックアップ取得

AWS CLI の取得コマンドも載せておきます。



無期限にデータを保持

```
aws redshift-serverless create-snapshot \
--namespace-name default \
--snapshot-name test1
```



7 日間でデータ削除

```
aws redshift-serverless create-snapshot \
--namespace-name default \
--snapshot-name test2 \
--retention-period 7
```



# わかったこと

- SAM でデフォルトで入っている boto3 のバージョンはちょっと古い
  - 確認方法 : https://dev.classmethod.jp/articles/lambda-boto3-update202108/
  - この記事の環境だと boto3 vertion: 1.20.32 だった。
- データ容量に応じて、初回 Snapshot の作成時間に違いがある。700 MB ほどだったら 5 分くらいで出来上がる。データ容量が多い環境の場合は、時間がかかることもあるのでゆっくり待機する。
- Redshift の Snapshot の個数が Service Quota で定められている。20 個がデフォルトの上限になっている。



# 参考 URL

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/redshift-serverless/client/create_snapshot.html