Redshiftクラスターのサイズ変更完了を通知する

Redshiftのクラスターのサイズ変更にはそれなりに時間がかかります。 時間がかかるというのであれば、サイズ変更の完了を通知してほしいので、Redshiftのサイズ変更の完了を通知する方法を考えたので紹介します。
2020.07.27

Redshiftでは、コンピューティングリソースやディスク容量が不足している場合、あとからクラスターのサイズ変更ができて便利です。

しかし、Redshiftのクラスターのサイズ変更にはそれなりに時間がかかります。

公式ドキュメントにもこう記載されています。

これに要する時間は、小さい方のクラスターにあるデータの量とノードの数によって異なります。数時間で終わることもあれば、2~3 日、またはそれ以上かかる可能性もあります。

参考: Amazon Redshift でのクラスター管理の概要 - Amazon Redshift

それだけ時間がかかるというのであれば、サイズ変更の完了を通知してほしいです。 というわけで、Redshiftのサイズ変更を通知する方法を考えたので紹介します。

AWS構成図

こんな感じのAWS環境を構築します。

Redshiftクラスターに対して、Redshiftのイベントサブスクリプションを設定しておき、SNSに通知します。

Redshiftのイベント通知機能については、こちらの弊社ブログで解説しています。詳細はこちらを御覧ください。

SNSからLambdaを起動して、LambdaでRedshiftのイベントIDを確認します。 サイズ変更完了のイベント(イベントID:REDSHIFT-EVENT-3002)だった場合、別のSNSに通知します。

そのSNSを起点にして、後続処理を実行します。今回は、E-mailで通知します。

前提条件

次のような環境は構築されていることを前提として、説明を省きます。

  • ローカルマシンに AWS CLI v2 がインストールされていること
  • Redshiftクラスターは、 sample-redshift-cluster という名前ですでに作成されていること

構築手順

SNSの作成

まずは、2つのSNSを作成します。

マネジメントコンソールのSNSの画面を開いてトピックを作成します。

次の2つの名前でSNSトピックを作成します。

  • RedshiftNotification(Redshiftのイベントサブスクリプションを受信する用)
  • ResizeClusterCompletedNotification(クラスターサイズ変更完了の通知をLambdaから受信する用)

作成できたら、 ResizeClusterCompletedNotification の方のARNをメモしておいてください。後ほどLambdaの環境変数設定時に利用します。

Redshiftイベントサブスクリプションの作成

次にRedshiftのイベントを通知する、イベントサブスクリプションを作成します。

マネジメントコンソールのRedshiftの画面を開いてイベントサブスクリプションを作成します。

名前は sample-redshift-event とします。

各項目を次のとおり設定して、イベントサブスクリプションを作成します。

項目名 設定値 備考
ソースタイプ クラスター
クラスター sample-redshift-cluster Redshiftクラスターはあらかじめ作成しておく
カテゴリ モニタリング
重要度 情報、エラー

項目名 設定値 備考
SNSトピック通知 RedshiftNotification 先ほど作成したRedshiftのイベントサブスクリプションを受信する用のSNSを選択
サブスクリプションのアクティベーション 無効化 余計な通知を受け取らないよう、サイズ変更直前に有効化する

IAM Roleの作成

次に、Lambda実行用のIAM Roleを作成します。

マネジメントコンソールのIAMの画面を開いてロールを作成します。

Lambda用のRoleですので、ユースケースはLambdaを選択します。

Lambdaの基本的な実行権限をつけたいので、 **AWSLambdaBasicExecutionRoleポリシーを追加します。 他の権限はインラインポリシーで設定します。

最後に、名前を ResizeClusterCompletedNotifierRole としてロールの作成をします。

Roleが作成できたら次のポリシーをインラインポリシーに追加し、SNSにパブリッシュする権限とRedshiftのイベントサブスクリプションを変更する権限をつけます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sns:Publish",
                "redshift:ModifyEventSubscription"
            ],
            "Resource": "*"
        }
    ]
}

Lambdaの作成

次にサイズ変更完了のイベント(イベントID:REDSHIFT-EVENT-3002)だけフィルタリングするLambdaを作成します。

マネジメントコンソールのLambdaの画面を開いて関数を作成します。

名前は、 ResizeClusterCompletedNotifier とします。 ランタイムは Node.js 12.x を選択してください。 IAM Roleは先ほど作成した ResizeClusterCompletedNotifierRole を指定します。

関数が作成できたら、次のプログラムを関数コードにコピー&ペーストしてください。

const AWS = require('aws-sdk');

const REGION = process.env.AWS_REGION;
const SNS_ARN = process.env.SNS_ARN;
const SUBSCRIPTION_NAME = process.env.SUBSCRIPTION_NAME;

const sns = new AWS.SNS({
   apiVersion: '2010-03-31',
   region: REGION,
});

const redshift = new AWS.Redshift({
    apiVersion: '2012-12-01',
    region: REGION,
});

exports.handler = async (event) => {
    console.log(JSON.stringify(event));
    
    const message = event.Records[0].Sns.Message;
    const subject = event.Records[0].Sns.subject;
    
    const parsedMessage = JSON.parse(message);
    
    if(parsedMessage['About this Event'].includes('REDSHIFT-EVENT-3002')){
        await redshift.modifyEventSubscription({
            SubscriptionName: SUBSCRIPTION_NAME,
            Enabled: false,
        }).promise();
        await sns.publish({
            Message: message,
            Subject: subject,
            TopicArn: SNS_ARN,
        }).promise();
    }
    
    return null;
};

そして、次の2つの環境変数を設定します。

キー 値(例) 備考
SNS_ARN arn:aws:sns:ap-northeast-1:123456789012:ResizeClusterCompletedNotification メモしておいたクラスターサイズ変更完了の通知をLambdaから受信する用SNSのARN
SUBSCRIPTION_NAME sample-redshift-event 先ほど作成したRedshiftイベントサブスクリプションの名前

ちなみに、SNSからLambdaを実行する際のEventのMessageには、 次のようなJSON文字列がエスケープ処理された形で送られてきます。

{
  "Event Source": "cluster",
  "Resource": "sample-redshift-cluster",
  "Event Time": "2020-07-27 08:22:10.158",
  "Identifier Link": "https://console.aws.amazon.com/redshift/home?region=ap-northeast-1#cluster-details:cluster=sample-redshift-cluster ",
  "Severity": "INFO",
  "Category": [ "Monitoring" ],
  "About this Event": "http://docs.aws.amazon.com/redshift/latest/mgmt/working-with-event-notifications.html#REDSHIFT-EVENT-3002 ",
  "Event Message": "The resize for Amazon Redshift cluster 'sample-redshift-cluster' completed at 2020-07-27 08:22 UTC, and the cluster is available for reads and writes. The resize was initiated at 2020-07-27 07:56 UTC and took 0 hours 25 minutes to complete."
}

LambdaでこのMessageを読み込んで処理して、SNSにパブリッシュするかどうかを判定しています。

SNSサブスクリプションの作成

最後に、SNSサブスクリプションを作成します。

RedshiftNotification の方は、プロトコルにAWS Lambda、 先ほど作成した ResizeClusterCompletedNotifier を選択して、サブスクリプションを作成します。

ResizeClusterCompletedNotification の方は、プロトコルにEメール、 受信可能なE-mailアドレスを入力して、サブスクリプションを作成します。

作成すると、E-mailアドレス宛に確認メールが飛ぶのでリンクをクリックして確認を完了してください。

ここまでの作業で環境構築は完了です。

Redshiftのサイズ変更をやってみる

実際に通知を受け取ることができるかやってみます。

AWS CLIを使って、Redshiftのサイズ変更をしてみます。 サイズ変更をする前に次の aws redshift modify-event-subscription を実行してRedshiftイベント通知を有効にします。

$ aws redshift modify-event-subscription \
  --subscription-name sample-redshift-event \
  --enabled

このコマンドを実行することで、先ほど無効にしていたサブスクリプションアクションが有効化されます。

次に、 aws redshift resize-cluster を実行してRedshiftのサイズ変更をします。

$ aws redshift resize-cluster \
  --cluster-identifier sample-redshift-cluster \
  --number-of-nodes 4 \
  --classic

このコマンドを実行することで、Redshiftクラスターのサイズ変更が始まります。

しばらく待つ(今回は30分ほどかかりました)と、SNSからE-mailが飛んできました。

マネジメントコンソールでRedshiftクラスターの状況を確認してみると、ノードが4つに増えており、クラスターのサイズ変更をE-mailで通知できています。

Redshiftのイベントサブスクリプションも無効化されています。

CloudWatch Logsでログを確認してみると、いくつか他のRedshiftイベントが発生していますが、クラスターのサイズ変更の完了(イベントID:REDSHIFT-EVENT-3002)だけフィルタリングして通知できました。

終わりに

Redshiftのクラスターサイズ変更の完了通知をやってみました。

今回はE-mail通知でやってみましたが、SNSに通知をしているのでLambdaを使ってSlackに通知したり、サイズ変更後に後続処理のLambdaを起動するなんて使い方もできると思います。