Lambda: CloudWatch アラームで DB インスタンスを再起動する

2016.03.09

Bildschirmfoto 2016-03-08 um 18.09.32

こんにちは、ももんが大好きの小山です。きょうは、なんらかの理由によって接続数の増えすぎてしまった DB インスタンスを自動的に再起動する方法についてご紹介しようと思います。

目標

DB インスタンスの CloudWatch メトリクス「DB Connections」に対してアラームを設定し、アラームの SNS メッセージを Lambda で受け取ることによって DB インスタンスの再起動を実行します。

ビフォー

Bildschirmfoto 2016-03-08 um 11.19.41

Before

Ohne Titel2 Ohne Titel

アフター

Bildschirmfoto 2016-03-08 um 11.19.41

After

lambda Ohne Titel

ステップ1: CloudWatch アラームの作成

Bildschirmfoto 2016-03-08 um 14.39.57

Amazon RDS コンソールで設定したい DB インスタンスを見つけて、Show Monitoring をクリックします。

Bildschirmfoto 2016-03-08 um 14.49.16

表示されたグラフの中から、DB Connections を選択しましょう。

Bildschirmfoto 2016-03-08 um 14.51.50

右下の Create Alarm をクリックして...

Bildschirmfoto 2016-03-08 um 13.08.30

赤枠の create topic をクリックして新しい SNS トピックを作成します。With these recipients ではメールアドレスを入力できますが、バカンスに水を差されたくない方は空欄のまま進みましょう。アラームとしたい条件を指定したら Create Alarm をクリックします。

Bildschirmfoto 2016-03-08 um 15.34.00

CloudWatch アラームが設定できました!

ステップ2: Lambda 関数の作成

Bildschirmfoto 2016-03-08 um 16.01.36

AWS Lambda コンソールを開いて、Create a Lambda function をクリックします。Select blueprint のページが表示されたら、右下の Skip を選択します。

Bildschirmfoto 2016-03-08 um 10.54.36

Configure function のページでは、ランタイムとして Python 2.7 を選択して以下のコードを貼り付けます。

from __future__ import print_function

import boto3
import json
import logging

client = boto3.client('rds')
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    logger.info("From SNS: " + event['Records'][0]['Sns']['Message'])
    message = json.loads(event['Records'][0]['Sns']['Message'])
    instance_to_reboot = message['Trigger']['Dimensions'][0]['value']
    logger.info("Instance to Reboot: " + str(instance_to_reboot))

    try:
        client.reboot_db_instance(
        DBInstanceIdentifier=instance_to_reboot,
        ForceFailover=False
        )
        logger.info("Rebooting...")
    except:
        logger.info("Something went wrong.")

Bildschirmfoto 2016-03-08 um 10.54.55

Role から * Basic execution role を選択すると、IAM ロールの作成ページへ移動できます。

Bildschirmfoto 2016-03-08 um 11.02.04

Role Name を任意の名称に書き換えて、View Policy Document > Edit から以下のポリシーを貼り付けます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1457431087000",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "Stmt1457431134000",
            "Effect": "Allow",
            "Action": [
                "rds:RebootDBInstance"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Allow をクリックして Lambda 関数の作成ページへ戻ったら、Next で進みましょう。

Bildschirmfoto 2016-03-08 um 11.02.29 1

内容を確かめたら、Create function で完了します。

ステップ3: イベントソースの作成

初出時にステップ3の手順が欠落しており、これに沿って操作すると Lambda 関数が動作しない状態でした。お詫びして追記いたします (2016-03-10)

Bildschirmfoto 2016-03-08 um 11.03.01

作成した Lambda 関数のページへ移動し、Event sources > Add event sourceの順にクリックします。

Bildschirmfoto 2016-03-08 um 11.04.10

Event source type として SNS、SNS topic としてステップ1で作成した SNS トピックを指定します。Enable event source では Enable now を選択し、Submit ボタンを押せば完了です。おつかれさまでした!

テスト

Bildschirmfoto 2016-03-08 um 10.34.01

古典的な方法を用いて、設定した条件まで DB Connections を増やしてみます。

Bildschirmfoto 2016-03-08 um 16.36.28

アラームだぞ!!

Bildschirmfoto 2016-03-08 um 16.39.56

心配いりません。作成した Lambda 関数が通知を受け取って、DB インスタンスの再起動を実行しました。

Bildschirmfoto 2016-03-08 um 16.40.36

やった!

Bildschirmfoto 2016-03-08 um 16.48.12

きちんとアラームが止んで、DB インスタンスのステータスも available に戻っています。

おわりに

いかがでしたか? きょうご紹介したように、Lambda や CloudWatch、SNS といった AWS の先進的なサービスを使うだけで難しそうなことも手軽に実現できることがあります。皆で知恵を絞りあって、システムが自律的に動作し続けるような明るい未来を切り開きましょう!