Amazon Aurora のスロークエリを Slack に通知する

スロークエリを簡単に確認できるようにしたかったので、Lambda を使って Aurora でスロークエリが発生するたびに Slack に通知するようにしてみました。

ログのエクスポート設定

まずは、クラスターの変更から Amazon CloudWatch Logs にスロークエリログを発行するようにします。

f:id:enomotodev:20181212212733p:plain

パラメータグループを編集

デフォルトのパラメータグループでは slow_query_log が OFF になっており、スロークエリが出力されないようになっているので、パラメータグループを編集して slow_query_log1 にして有効にしましょう。

ついでにデフォルトでは long_query_time10 になっており、10 秒以上のクエリではないとスロークエリに出力されないので、long_query_time1 など小さい数値に変更します。

IAM ロールの作成

Lambda 用の IAM ロールを作成します。

  • ロール名:slowquery-to-slack-role
  • このロールを使用するサービスを選択:Lambda
  • ポリシー:AWSLambdaBasicExecutionRole

として作成します。

Webhook URL の発行

Slack の Webhook URL を用意していない場合は Slack の Incoming Webhooks のページから Webhook URL を発行してください。

次の Lambda を作成する際に Slack の Webhook URL を使用します。

Lambda の作成

IAM ロールと Slack の Webhook URL が作成できたら Lambda 関数を作成します。

一から作成を選択し、

  • 名前:slowquery-to-slack
  • ランタイム:Python 3.7
  • ロール:既存のロールを選択
  • 既存のロール:slowquery-to-slack-role

として作成します。

関数コードは下記をそのままコピペして使用してください。

import os
import base64
import gzip
import json
import logging
from io import BytesIO
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError

Slack_Webhook_URL = os.environ['SLACK_WEBHOOK_URL']

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

def lambda_handler(event, context):
    buffer = BytesIO(base64.b64decode(json.dumps(event['awslogs']['data'])))
    with gzip.GzipFile(mode='rb', fileobj=buffer) as sb:
        data = sb.read()

    log = json.loads(data.decode('utf-8'))
    message = str(log['logEvents'][0]['message'])

    slack_message = {
        'text': '*New Slow Query Alert*',
        'attachments': [
            {
                'color': '#36464f',
                'text': message,
                'footer': 'Amazon RDS'
            }
        ]
    }

    req = Request(Slack_Webhook_URL, json.dumps(slack_message).encode('utf-8'))
    try:
        response = urlopen(req)
        response.read()
        logger.info('Message posted to %s', Slack_Webhook_URL)
    except HTTPError as e:
        logger.error('Request failed: %d %s', e.code, e.reason)
    except URLError as e:
        logger.error('Server connection failed: %s', e.reason)

コードをコピペしたら環境変数を設定します

f:id:enomotodev:20181212214809p:plain

上のようにキーを SLACK_WEBHOOK_URL にし、値には先ほど発行した Slack の Webhook URL を設定します。

これで Lambda の作成は完了です。

ストリーミングの設定

次に CloudWatch に移動し、ログを選択して、ロググループ一覧画面を表示させます。

1度でもスロークエリを発生させているとロググループに /aws/rds/cluster/クラスター名/slowquery があると思うので、チェックを付け、アクションから『Lambda サービスへのストリーミング開始』を選択します。

(まだスロークエリを発生させていない場合は select sleep(3); などのクエリを発行して、故意にスロークエリを発生させて、ロググループを作成させましょう)

Lambda 関数では先ほど作成した slowquery-to-slack を選択し、ログの形式はどれを選んでも良いので、サブスクリプションフィルタのパターンを空にして、ストリーミングを開始します。

動作確認

これで設定はすべて完了したので select sleep(3); などのクエリを発行して、Slack にスロークエリが通知されるか確認してみましょう。

f:id:enomotodev:20181212223032p:plain

無事 Slack に通知されました!

まとめ

AWS の RDS(Aurora), IAM, Lambda, CloudWatch と 4 つのサービスを連携させてスロークエリを Slack に通知させてみました。

AWS は色々なサービスがありますが、それらをうまく連携させることでさらに便利になると思うので、まだ触ったことのないサービスも積極的に触れていきたいと思います!

Amazon Web Services エンタープライズ基盤設計の基本

Amazon Web Services エンタープライズ基盤設計の基本

Kubernetes完全ガイド impress top gearシリーズ

Kubernetes完全ガイド impress top gearシリーズ