LoginSignup
1
0

More than 3 years have passed since last update.

AWS DocumentDBのステータスを通知するLambda関数

Last updated at Posted at 2021-04-15

タイトル通りのLambda関数を作ろうと思いましたがPythonだとrequestsモジュール等をレイヤーにして
読み込まないといけないとか色々面倒に感じたのでボツに。
(結局のところ、Rubyで書きました、aws-sdk読み込むだけで特に面倒な手順はないので・・・)

自分の思い出としてこちらに残します。

※動作確認はしていないので、参考程度にお願いします。
※ご指摘、改善点あればコメントください。

仕様

大雑把に説明するとDocumentDBクラスターとDocumentDBクラスターに紐づくDocumentDBインスタンスのステータスをチェックし、「available」以外のステータスのものがあればメールを送信します。

前提

監視対象のAWS DocumentDBクラスターが存在していること

事前準備

本筋ではないので割愛します。

  • Lambda関数の作成
  • Lambda関数のロールにポリシー追加(AmazonDocDBReadOnlyAccess, AmazonSNSFullAccess)
  • requestsモジュール等を動作させるためにレイヤーを作る(こちらの方の記事が参考になります)
  • Lambda関数の環境変数の設定(TOPIC_ARN, DB_CLUSTER_IDENTIFIER)
  • Amazon SNSのトピック作成
  • Amazon SNSのトピックにサブスクリプション追加(メールの送信先)

今時メールじゃなくてもSlackやTeams連携の方が利便性は高いかもしれませんね。

実際のソース

lambda_function.py

# -*- coding: utf-8 -*-

import os
import boto3
import requests
import logging

# Lambda関数の環境変数に設定した値を取得
# AWS SNSトピックのARN(メール送信先)
TOPIC_ARN = os.environ['TOPIC_ARN']
# DocumentDBクラスター識別子(ステータス取得対象のクラスターを指定)
DB_CLUSTER_IDENTIFIER = os.environ['DB_CLUSTER_IDENTIFIER']

def lambda_handler(event, context):
    # ロガーの設定
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    # DocumentDBのクライアント
    docdb_client = boto3.client('docdb')
    # AWS SNSのクライアント
    sns_client = boto3.client('sns')

    # ステータスの結果保存のための配列
    db_statuses = []

    try:
        logger.info('Start >>> get DocumentDB status.')
        # dbクラスターの情報取得
        cluster_info = docdb_client.describe_db_clusters(DBClusterIdentifier=DB_CLUSTER_IDENTIFIER)
        cluster_status = cluster_info['DBClusters'][0]['Status']
        db_statuses.append(
            {
                DB_CLUSTER_IDENTIFIER : cluster_status
            }
        )

        instances = cluster_info['DBClusters'][0]['DBClusterMembers']

        for instance in instances:
            instance_id = instance['DBInstanceIdentifier']
            instance_info = docdb_client.describe_db_instances(DBInstanceIdentifier=instance_id)
            status = instance_info['DBInstances'][0]['DBInstanceStatus']

            db_statuses.append(
                {
                    instance_id : status
                }
            )

        # 1件でも'available'以外の場合、通知処理実行
        # ※'available'以外にも通知しないステータスを追加する場合は、in以降の配列にステータスの文字列を追加する
        is_notify = not all(list(i.values())[0] in ['available'] for i in db_statuses)

        if is_notify:
            # 通知処理の実行

            # メールに記載する内容を作成
            subject = '【AWS DocumentDB】An instance with an abnormal status has been detected.'
            message = ''
            for status_info in db_statuses:
                key = list(status_info.keys())[0]
                value = status_info[key]
                message += f'{key}: {value}\n'

            # メール送信
            sns_client.publish(
                TopicArn = TOPIC_ARN,
                Subject = subject,
                Message = message,
            )

            logger.info('DocumentDB status list↓')
            logger.info(message)
            logger.info('Completed successfully.')

    except Exception as e:
        logger.error(e)

    finally:
        logger.info('End >>> get DocumentDB status.')



※作成したレイヤーの追加は忘れずに!

あとはCloudWatch Eventsにルール追加

例えばcron式に「*/10 * * * ? *」を設定することで10分毎にDocumentDBのステータスをチェックします。
もし異常があればメールが飛んでくるはずです。

ターゲットとして、監視対象のクラスター識別子を渡してあげるようにすれば、Lambda関数内の引数eventで参照することができるのでLambda関数はそのままにルールを追加して環境毎に監視することも可能です。

「available」以外の監視でいいのか?

「available」以外という条件では、定期メンテナンスの場合もメールが飛んでくることがあると思うので
定期メンテナンスの場合の「maintenance」も足して

is_notify = not all(list(i.values())[0] in ['available', 'maintenance'] for i in db_statuses)

とするのもいいかもしれません。

参考

Amazon DocumentDB インスタンスのステータスのモニタリング
Boto3/Docs/Available services/DocDB
Boto3/Docs/Available services/SNS

1
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
1
0