BeeX Technical BlogRedshiftスケジュール起動・停止で発生する不要なアラートを抑止する

はじめに

今回はAWS Lambdaを使用してAmazon Redshiftのスケジュール停止・再開を制御するという内容です。

背景として、Redshiftクラスタの停止・再開タイミングでCloudWatchアラームが不要なアラートメールを送信してしまうという状況がありました。
Lambdaでクラスタ停止・再開とCloudWatchアラーム無効化・有効化を制御することで、アラートを抑止したいというのが目的です。

設計

・Lambda関数を1つ用意します。
・CloudWatchルールはRedshiftクラスタ1つにつき最低2つ用意し、ターゲットとしてLambdaを指定します。(ルールはRedshiftクラスタ停止、再開でそれぞれ1つずつ)

設定手順

1. IAMポリシーの作成

まずは、IAMポリシーを作成します。
このポリシーは、Lambdaで使用するIAMロールにアタッチします。

JSONは以下の記載内容を参考にしてください。
ポリシー名は「redshift-alert-reduction_policy」としました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid":"AllowRedshiftClusterManagement",
      "Action": [
        "redshift:ResumeCluster",
        "redshift:PauseCluster"
      ],
      "Resource": [
        "arn:aws:redshift:ap-northeast-1:[アカウントID]:cluster:[クラスタ名]"
      ],
      "Effect": "Allow"
    },
    {
      "Sid":"AllowCWAlarmManagement",
      "Action": [
        "cloudwatch:DisableAlarmActions",
        "cloudwatch:EnableAlarmActions"
      ],
      "Resource": [
        "arn:aws:cloudwatch:ap-northeast-1:[アカウントID]:alarm:*"
      ],
      "Effect": "Allow"
    }
  ]
}

2. IAMロールの作成

続いて、IAMロールを作成します。
ここではロール名を「lambda-alert-reduction-role」としました。

ロール作成時の「ユースケースの選択」でLambdaを選択してください。
ポリシーは以下の2つをアタッチします。

・AWSLambdaBasicExecutionRole
・redshift-alert-reduction_policy

3. Lambda関数の作成

Lambda関数を作成します。ランタイムはPython3.8です。
関数名は「redshift_alert_reduction」としました。

関数には作成したロール「lambda-alert-reduction-role」を設定します。
タイムアウトを15分に設定してください。

ソースコード

import json
import boto3
import logging
import time

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

def control_cloudwatch_alarm(cluster_name, action):
    client = boto3.client('cloudwatch')

    alarm_disk = f'Redshift ALERT {cluster_name} - Disk Space Used'
    alarm_health = f'Redshift ALERT {cluster_name} - Health Status'
    alarm_cpu = f'Redshift ALERT {cluster_name} - CPU Utilization'

    if (action):
        try:
            client.enable_alarm_actions(
                AlarmNames=[
                    alarm_disk,
                    alarm_health,
                    alarm_cpu
                ]
            )
            logger.info("Enabling CloudWatch Alarm")
        except Exception as e:
            logger.error("Exception: {}".format(e))
    else:
        try:
            client.disable_alarm_actions(
                AlarmNames=[
                    alarm_disk,
                    alarm_health,
                    alarm_cpu
                ]
            )
            logger.info("Disabling CloudWatch Alarm")
        except Exception as e:
            logger.error("Exception: {}".format(e))

def control_redshift_cluster(cluster_name, action):
    client = boto3.client('redshift')

    if (action):
        try:
            client.resume_cluster(
                ClusterIdentifier=cluster_name
            )
            logger.info("Resuming Redshift cluster")
        except Exception as e:
            logger.error("Exception: {}".format(e))
    else:
        try:
            client.pause_cluster(
                ClusterIdentifier=cluster_name
            )
            logger.info("Pausing Redshift cluster")
        except Exception as e:
            logger.error("Exception: {}".format(e))

def lambda_handler(event, context):
    #redshift cluster name
    cluster_name = event['cluster_name']
    #if action is true, resume cluster and enable cloudwatch alram
    action = event['action']

    if action == True:
        control_redshift_cluster(cluster_name, action)
        #wait until redshift cluster becomes available
        time.sleep(840)
        control_cloudwatch_alarm(cluster_name, action)
    elif action == False:
        control_cloudwatch_alarm(cluster_name, action)
        #wait until cloudWatch alarm becomes disabled
        time.sleep(60)
        control_redshift_cluster(cluster_name, action)

ソースコードの補足

・12~14行目でCloudWatchのアラーム名を指定しています。これらのアラームを抑止しますので、適宜変更してください。
・70行目に”time.sleep(840)”とありますが、Redshiftクラスタ再開から14分待機し、クラスタがavailableになるまで待ってCloudWatchアラームを有効化します。
14分とする理由は、Lambdaのタイムアウトが最長で15分であり、最大限に待機時間を延ばすためです。もし普段クラスタが5分程度で起動するのであれば、sleepの値は短くしても大丈夫です。

4. CloudWatchルール設定

設計の説明でも記載した通り、Redshiftクラスタ1つにつき、ルールは最低2つ設定します。
停止・再開タイミングが複数ある場合は、その分だけルール設定が必要となります。

ターゲットには作成したLambda関数を指定します。
入力の設定で「定数 (JSONテキスト)」を選択し、以下のJSONを入力します。

jsonで指定するactionがTrueの場合 :Redshiftを起動、CloudWatchアラームを有効化
jsonで指定するactionがFalseの場合:Redshiftを停止、CloudWatchアラームを無効化

●定数に入力するJSON(クラスタ起動の場合)

{ "cluster_name": "クラスタ名", "action": true}

●定数に入力するJSON(クラスタ停止の場合)

{ "cluster_name": "クラスタ名", "action": false}

ルール名は以下のようにしました。
ルール①:redshift_[クラスタ名]_resume
ルール②:redshift_[クラスタ名]_pause

以上で設定は完了です。

おわりに

今回はLambdaを使用して、RedshiftやCloudWatchを制御することでアラートを抑止し、重要なアラートを見落とさないようにするという対応を実施しました。
記事投稿時点ではCloudWatchにアラートを抑止するための機能が組み込まれていないため、ここに記載した内容が少しでもお役に立てれば幸いです。

カテゴリ

タグ

BeeX Technical Blogについてのお問い合わせ

BeeX Technical Blogのエントリにご質問が御座いましたらお気軽にお問合せください。

お電話でのお問い合わせ

☎ 03-6260-6240

受付時間 平日9:30〜18:00

フォームでのお問い合わせ

お問い合わせフォーム