話題の記事

【新機能】Amazon AuroraからLambdaを呼べるようになりました

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ウィスキー、シガー、パイプをこよなく愛する大栗です。

本日Auroraで新しい機能が発表されました。なんとAuroraの中からLambdaを呼び出す事ができるようになりました!さっそく試してみました。

2017年2月現在AuroraがPrivate Subnetに有ってもLambdaをcallすることが可能になっています。

Amazon Aurora Update – Call Lambda Functions From Stored Procedures; Load Data From S3 Release: Amazon RDS on 2016-10-18

どういう機能?

一言で書くと、『AuroraのストアドプロシージャでLambdaをInvokeできる』機能です。

ドキュメントによると、ストアドプロシージャは以下の通りです。

シンタックス

 CALL mysql.lambda_async (
  lambda_function_ARN,
  lambda_function_input
)

パラメータ

  • lambda_function_ARN 呼び出すLambdaファンクションのARN
  • lambda_function_input Lambfaファンクションを呼び出すJSON形式の入力文字列

なお、Aurora上でmysql.lambda_asyncの定義を確認すると以下のようになっています。

mysql> show create procedure mysql.lambda_async \G
*************************** 1. row ***************************
           Procedure: lambda_async
            sql_mode: NO_ENGINE_SUBSTITUTION
    Create Procedure: CREATE DEFINER=`rdsadmin`@`localhost` PROCEDURE `lambda_async`(IN functionName VARCHAR(1600), IN inputPayload VARCHAR(65535))
    READS SQL DATA
    DETERMINISTIC
BEGIN
   AWSLAMBDA(functionName,inputPayload,'0');
END
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: latin1_swedish_ci

Lambda呼出しを試してみる

AuroraからLambdaを呼出して、SNS経由でメールを送信してみます。リージョンは東京で構築しています。

Auroraを起動する

今回は、以下のようにAuroraを起動しました。なお、既存のAuroraインスタンスでLambdaを実行する場合には、バージョンを1.8に上げる必要があるのでご注意ください。

  • リージョン:東京
  • インスタンスクラス:db.r3.large
  • マルチAZ:No
  • サブネットグループ:Default(デフォルトVPC)
  • パブリックアクセス可能:いいえ
  • Availability Zone:ap-northeast-1a
  • パラメータグループ:新規で作成したもの

RDS_·_AWS_Console

SNSトピックを作成する

SNSトピックを作成して、Subscriptionをメールで作成します。登録メールでConfirmします。

sns-confirm

IAM Roleを作成する

Lambda用Role

以下の内容でIAM Roleを作成します。

  • ロール名:(任意に設定してください)
  • AWS サービスロール:AWS Lambda
  • アタッチするポリシー:AmazonSNSFullAccess

RDS用Role

一度、以下の内容でRoleを作成します。

  • ロール名:(任意に設定してください)
  • AWS サービスロール:Amazon RDS
  • アタッチするポリシー:無し

作成した後に、アクセス許可でAWSLambdaRole管理ポリシーをアタッチします。

Lambdaファンクションを作成する

SNSを呼び出すLambdaファンクションを作成します。 ここでは、以下の内容で作成しています。

  • Runtime:Python 2.7
  • Handler:lambda_function.lambda_handler
  • Role:先程作成したLambda用Role

スクリプト内のTopicArnの中身はSNSトピックのARNに置換します。

import boto3

sns = boto3.client('sns')

def lambda_handler(event, context):
    
    return sns.publish(
        TopicArn='arn:aws:sns:ap-northeast-1:123456789012:AuroraLambda',
        Message=event['message'],
        Subject=event['subject'],
        MessageStructure='string'
    )

AuroraにIAM Roleを設定する

AuroraへIAM Roleを設定するには、AuroraクラスタとDBクラスタパラメータグループの2箇所で設定する必要があります。

Auroraクラスタの設定

作成したAuroraのクラスタの画面にIAM ロールの管理というボタンが増えているので、クリックします。

RDS_·_AWS_Console

先程作成したRDS用Roleを選択します。

RDS_·_AWS_Console

DBクラスタパラメータグループの設定

aws_default_lambda_roleで先程作成したRDS用RoleのARNを入力して変更を保存します。設定後にAuroraインスタンスのDBクラスタパラメータグループがpending-rebootになっていた場合はインスタンスの再起動を行ってください。

RDS_·_AWS_Console

Lambdaを起動する

Auroraにログインして、以下のコマンドを実行してみます。(第一引数は作成したLambdaファンクションをARNに変更してください)

mysql> CALL mysql.lambda_async('arn:aws:lambda:ap-northeast-1:123456789012:function:tosns', '{"subject" : "Aurora", "message" : "Test Aurora Invoke"}');

しかし、以下のエラーメッセージが表示されてしまいます。

ERROR 1873 (HY000): Lambda API returned error: Network Connection. Unable to connect to endpoint

Lambdaを実行するAuroraインスタンスは、VPC経由でLambdaエンドポイントへアクセスできるネットワーク環境が必要のようです。今回はデフォルトVPCに配置しているためパブリックアクセス可能にするだけで済みますが、Privateサブネットに配置している場合にはPublicサブネットへ移行するかRoute Tableでパブリックにする必要があります。ご注意ください。

Auroraインスタンスをパブリックアクセス可能にして再度実行します。(第一引数は作成したLambdaファンクションをARNに変更してください)

2017年2月現在AuroraがPrivate Subnetに有ってもLambdaをcallすることが可能になっています。

mysql> CALL mysql.lambda_async('arn:aws:lambda:ap-northeast-1:123456789012:function:tosns', '{"subject" : "Aurora", "message" : "Test Aurora Invoke"}');
Query OK, 0 rows affected (0.12 sec)

この様にメールが届きます。

Aurora_-_oguri_hajime_classmethod_jp_-_Classmethod_jp_メール

さいごに

いかがでしょうか。ストアドプロシージャとしてLambdaを呼べるため、トリガーに設定することでAuroraで更新したデータをDynamoDBに保存したりSNSで通知したりすることができます。データ更新の確認をPullではなくPushで出来るようになったのでリアクティブなアーキテクチャを構築する事ができます。

しかし、既存のAuroraインスタンスでLambdaを実行させたい場合には、ネットワーク構成を変更する必要があるかもしれません。Privateサブネットでも、既存の拡張モニタリングなどはCloudWatch Logsにデータを保存できましたが、今回の機能はネットワーク環境を考慮する必要があるので既存の環境をよく確認してから適用しましょう。