Aurora PostgreSQL DB クラスターから AWS Lambda 関数を呼び出す - Amazon Aurora

Aurora PostgreSQL DB クラスターから AWS Lambda 関数を呼び出す

AWS Lambda は、サーバーのプロビジョニングや管理を行わなくてもコードの実行が可能な、イベント駆動型のコンピューティングサービスです。この機能は、Aurora PostgreSQL を含む多くの AWS サービスで利用可能です。例えば、データベースからのイベント通知の処理や、新しいファイルが Amazon S3 にアップロードされるたびに行うファイルからのデータロードのために、Lambda を使用することができます。詳細については、「AWS Lambda デベロッパーガイドの「AWS Lambda とは」を参照してください。

注記

AWS Lambda 関数の呼び出しは Aurora PostgreSQL 11.9 以上のバージョンでサポートされています。

Aurora PostgreSQL で Lambda 関数を操作するためのセットアップは、AWS Lambda、IAM、VPC、および Aurora PostgreSQL DB クラスターが関係する複数ステップのプロセスとなります。以下に、必要なステップの概要を示します。

Lambda 関数の詳細については、「AWS Lambda デベロッパーガイド」の「Lambda の開始方法」および「AWS Lambda の基礎」を参照してください。

ステップ 1: Aurora PostgreSQL DB クラスターで、AWS Lambda へのアウトバウンド接続を設定する。

Lambda 関数は、常に AWS Lambda サービスが所有する Amazon VPC 内で実行されます。Lambda はこの VPC にネットワークアクセスとセキュリティルールを適用し、この VPC を自動的にモニタリングおよび維持します。Aurora PostgreSQL DB クラスターは、Lambda サービスの VPC にネットワークトラフィックを送信する必要があります。このための構成方法は、Aurora DB クラスターのプライマリDB インスタンスが、パブリックであるかプライベートであるかにより異なります。

  • Aurora PostgreSQL DB クラスターがパブリックの場合は、VPC からのアウトバウンドトラフィックを許可するための、セキュリティグループの設定のみが必要です。VPC のパブリックサブネット内に置かれた DB クラスターのプライマリ DB インスタンスで、「PubliclyAccessible」プロパティに true が設定されている場合、そのインスタンスはパブリックです。

    このプロパティの値は、AWS CLI コマンド describe-db-instances を使用して確認できます。または、AWS Management Console を使用して [Connectivity & security] (接続とセキュリティ) タブを開き、[Publicly accessible] (パブリックアクセス可能) が「はい」となっているかを確認します。また、インスタンスが VPC 内のパブリックサブネットにあることを確認する場合は、AWS Management Console あるいは AWS CLI を使用します。

  • Aurora PostgreSQL DB クラスターがプライベートの場合には、いくつかの選択肢があります。NAT (Network Address Translation) ゲートウェイもしくは、VPC エンドポイントのいずれかが使用できます。NAT ゲートウェイの詳細については、「NAT ゲートウェイ」を参照してください。VPC エンドポイントを使用するための手順の概要を以下に示します。

パブリック な DB インスタンスで AWS Lambda への接続を設定するには

  • Aurora PostgreSQL DB クラスターが実行される VPC で、アウトバウンド接続を許可するための設定を行います。これを行うには、ポート 443 および任意の IPv4 アドレス (0.0.0.0/0) への TCP トラフィックを許可するアウトバウンドルールを、VPC のセキュリティグループに作成します。

プライベートな DB インスタンスで AWS Lambda への接続を設定するには

  1. AWS Lambda 用に VPC エンドポイントを含む VPC を設定します。詳細については、「Amazon VPC ユーザーガイド」の「VPC エンドポイント」を参照してください。このエンドポイントは、Aurora PostgreSQL DB クラスターが Lambda 関数に対して発行した、呼び出しに対する応答を返します。

  2. VPC のルートテーブルにエンドポイントを追加します。詳細については、「Amazon VPC ユーザーガイド」の「ルートテーブルの使用」を参照してください。

ご使用の VPC は、ネットワークレベルで AWS Lambda VPC とやり取りできるようになります。ただし、まだ、IAM を使用してアクセス許可を設定する必要があります。

ステップ 2: Aurora PostgreSQL DB クラスターおよび AWS Lambda のために IAM を設定する

Aurora PostgreSQL DB クラスターからの Lambda 関数の呼び出しには、特定の権限が必要です。必要な権限を設定するには、Lambda 関数の呼び出しを許可する IAM ポリシーを作成し、そのポリシーをロールに割り当てた上で、そのロールを DB クラスターに適用することをお勧めします。このアプローチでは、指定された Lambda 関数をユーザーに代わって呼び出すための権限を、DB クラスターに対し付与します。以下のステップで、AWS CLI を使用してこれを行う方法を示します。

クラスターで Lambda を使用するために IAM のアクセス許可を設定するには

  1. AWS CLI コマンド create-policy を実行して、指定された Lambda 関数を、Aurora PostgreSQL DB クラスターが呼びだすことを許可する、IAM ポリシーを作成します。(ステートメント ID (Sid) は、ポリシーステートメントのオプションの記述であり、使用には影響しません。) このポリシーは、Aurora DB クラスターに対し、指定された Lambda 関数を呼び出すための最小限のアクセス許可を付与します。

    aws iam create-policy --policy-name rds-lambda-policy --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowAccessToExampleFunction", "Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:aws-region:444455556666:function:my-function" } ] }'

    または、任意の Lambda 関数の呼び出しを許可する、事前定義済みの AWSLambdaRole ポリシーを使用することもできます。詳細については、「Lambda のアイデンティティベースの IAM ポリシー」を参照してください。

  2. AWS CLI コマンド create-role を使用して、実行時にポリシーが引き受けることができる IAM ロールを作成します。

    aws iam create-role --role-name rds-lambda-role --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "rds.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }'
  3. AWS CLI コマンド attach-role-policy を使用して、このポリシーをロールに適用します。

    aws iam attach-role-policy \ --policy-arn arn:aws:iam::444455556666:policy/rds-lambda-policy \ --role-name rds-lambda-role --region aws-region
  4. AWS CLI コマンド add-role-to-db-cluster を使用して、このロールを Aurora PostgreSQL DB クラスターに適用します。この最後のステップにより、DB クラスターのデータベースユーザーに対し、Lambda 関数の呼び出しを許可します。

    aws rds add-role-to-db-cluster \ --db-cluster-identifier my-cluster-name \ --feature-name Lambda \ --role-arn arn:aws:iam::444455556666:role/rds-lambda-role \ --region aws-region

VPC と IAM の設定が完了したので、ここで aws_lambda 拡張をインストールできます。(拡張機能は任意のタイミングでインストールできますが、先に VPC サポートと IAM 権限を適切に設定する必要があります。aws_lambda 拡張機能は、Aurora PostgreSQL DB クラスターの機能に対し何も追加しません。)

ステップ 3: Aurora PostgreSQL DB クラスター用に aws_lambda 拡張機能をインストールする

Aurora PostgreSQL DB クラスターで AWS Lambda を使用し、Aurora PostgreSQL に対し PostgreSQL の aws_lambda 拡張機能を使用するには この拡張機能は、Aurora PostgreSQL DB クラスターに対し、PostgreSQL からの Lambda 関数呼び出し機能を追加します。

Aurora PostgreSQL DB クラスターaws_lambda 拡張機能をインストールするには

PostgreSQL の psql コマンドライン、または pgAdmin ツールを使用して、Aurora PostgreSQL DB クラスターに接続します。

  1. Aurora PostgreSQL DB クラスターに、rds_superuser 権限を持つユーザーとして接続します。例では、デフォルトの postgres ユーザが示されています。

    psql -h cluster-instance.444455556666.aws-region.rds.amazonaws.com -U postgres -p 5432
  2. aws_lambda 拡張機能をインストールします。aws_commons 拡張機能も必要です。これは、aws_lambda や、他の多数の PostgreSQL向け Aurora 拡張機能にヘルパー関数を提供します。この拡張機能が、Aurora PostgreSQL DB クラスター上で見つからない場合は、次のように aws_lambda を使用してインストールされています。

    CREATE EXTENSION IF NOT EXISTS aws_lambda CASCADE; NOTICE: installing required extension "aws_commons" CREATE EXTENSION

aws_lambda 拡張機能は、Aurora PostgreSQL DB クラスターのプライマリ DB インスタンスにインストールされています。この段階で、Lambda 関数を呼び出すための、使いやすい構造を作成することが可能です。

ステップ 4: Aurora PostgreSQL DB クラスターで Lambda のヘルパー関数を使用する (オプション)

aws_commons 拡張機能のヘルパー関数を使用すると、PostgreSQL からより簡単に呼び出すことができるエンティティを準備することができます。これを行うには、Lambda 関数に関する以下の情報が必要です。

  • [Function name] (関数名) – Lambda 関数の名前、Amazon リソースネーム (ARN)、バージョンまたはエイリアス。ステップ 2: クラスターおよび Lambda のために IAM を設定する で作成された IAM ポリシーは ARN を必要とするため、関数の ARN を使用することをお勧めします。

  • [AWS Region] – (オプション) Lambda 関数が Aurora PostgreSQL DB クラスターと同じリージョンに存在しない場合、Lambda 関数がある AWS リージョン。

Lambda 関数名の情報を保持するには、aws_commons.create_lambda_function_arn 関数を使用します。このヘルパー関数は、呼び出し関数に必要な詳細を含む aws_commons._lambda_function_arn_1 複合構造を作成します。以下に、この複合構造を設定するための 3 つの代替手段を説明します。

SELECT aws_commons.create_lambda_function_arn( 'my-function', 'aws-region' ) AS aws_lambda_arn_1 \gset
SELECT aws_commons.create_lambda_function_arn( '111122223333:function:my-function', 'aws-region' ) AS lambda_partial_arn_1 \gset
SELECT aws_commons.create_lambda_function_arn( 'arn:aws:lambda:aws-region:111122223333:function:my-function' ) AS lambda_arn_1 \gset

これらの値はいずれも、aws_lambda.invoke 関数の呼び出し時に使用されます。例については、「ステップ 5: Aurora PostgreSQL DB クラスターから Lambda 関数を呼びだす」を参照してください。

ステップ 5: Aurora PostgreSQL DB クラスターから Lambda 関数を呼びだす

aws_lambda.invoke 関数は、invocation_type に応じて同期または非同期的で動作します。以下のように、このパラメーターには 2 つの選択肢、RequestResponse (デフォルト) と Event があります。

  • RequestResponse – この呼び出しタイプは同期です。これは、呼び出しタイプを指定せずに呼び出しが行われた場合のデフォルトの動作です。レスポンスペイロードには、aws_lambda.invoke 関数の結果が含まれます。処理を続行する前に Lambda 関数から結果を受け取る必要があるワークフローの場合は、この呼び出しタイプを使用します。

  • Event – この呼び出しタイプは非同期です。この場合の応答には、結果を含むペイロードは含まれません。この呼び出しタイプは、処理を続行するために Lambda 関数の結果を必要としないワークフローで使用します。

セットアップの簡単なテストとして、psql を使用して DB インスタンスに接続し、コマンドラインからサンプル関数を起動します。今、次のスクリーンショットに示すシンプルな Python 関数のような基本的関数の 1 つが、Lambda サービスに設定されているとします。


            AWS Lambda の AWS CLI 内に表示された Lambda 関数の例

サンプル関数を呼び出すには

  1. psql または pgAdmin を使用して、プライマリ DB インスタンスに接続します。

    psql -h cluster.444455556666.aws-region.rds.amazonaws.com -U postgres -p 5432
  2. ARN を使用して関数を呼びだします。

    SELECT * from aws_lambda.invoke(aws_commons.create_lambda_function_arn('arn:aws:lambda:aws-region:444455556666:function:simple', 'us-west-1'), '{"body": "Hello from Postgres!"}'::json );

    この応答は次のようになります。

    status_code | payload | executed_version | log_result -------------+-------------------------------------------------------+------------------+------------ 200 | {"statusCode": 200, "body": "\"Hello from Lambda!\""} | $LATEST | (1 row)

呼び出しが成功しなかった場合は、「Lambda 関数のエラーメッセージ 」を参照してください。

ステップ 6: 他のユーザーに Lambda 関数を呼び出す許可を付与する

手順のこの時点では、rds_superuser であるユーザーだけが Lambda 関数を呼び出すことができます。作成した関数の呼び出しを他のユーザーに許可するには、許可を付与する必要があります。

Lambda 関数を呼び出す許可を付与するには

  1. psql または pgAdmin を使用して、プライマリ DB インスタンスに接続します。

    psql -h cluster.444455556666.aws-region.rds.amazonaws.com -U postgres -p 5432
  2. 次の SQL コマンドを実行します。

    postgres=> GRANT USAGE ON SCHEMA aws_lambda TO db_username; GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA aws_lambda TO db_username;

例: Aurora PostgreSQL DB クラスターから Lambda 関数を呼びだす

以下に、aws_lambda.invoke 関数の呼び出し例をいくつか示します。ほとんどの例では、関数の詳細を簡単に渡せるように、ステップ 4: Aurora PostgreSQL DB クラスターで Lambda のヘルパー関数を使用する (オプション) で作成した複合構造 aws_lambda_arn_1 を使用しています。非同期呼び出しの例については、「例: Lambda 関数の (Event による) 非同期呼び出し」を参照してください。ここに示されたその他の例はすべて、同期呼び出しを使用します。

Lambda 呼び出しタイプの詳細については、「AWS Lambdaデベロッパーガイド」の「Lambda 関数を呼び出す」を参照してください。aws_lambda_arn_1の詳細については、「aws_commons.create_lambda_function_arn」を参照してください。

例: Lambda 関数の (RequestResponse による) 同期呼び出し

以下に、Lambda 関数の同期呼び出しの例を 2 つ示します。これらの aws_lambda.invoke 関数呼び出しの結果は同じです。

SELECT * FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json);
SELECT * FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'RequestResponse');

パラメータの説明は次のとおりです。

  • :'aws_lambda_arn_1' – このパラメータは、ヘルパー関数 aws_commons.create_lambda_function_arn を使用して、ステップ 4: Aurora PostgreSQL DB クラスターで Lambda のヘルパー関数を使用する (オプション) で作成される複合構造を識別します。この構造は、次のように aws_lambda.invoke 呼び出しの中で、インラインで作成することもできます。

    SELECT * FROM aws_lambda.invoke(aws_commons.create_lambda_function_arn('my-function', 'aws-region'), '{"body": "Hello from Postgres!"}'::json );
  • '{"body": "Hello from PostgreSQL!"}'::json - Lambda関数に渡す JSON ペイロード。

  • 'RequestResponse'-Lambda 呼び出しタイプ。

例: Lambda 関数の (Event による) 非同期呼び出し

以下は、Lambda 関数の非同期呼び出しの例です。Event 呼び出しタイプは、指定された入力ペイロードを使用して Lambda 関数の呼び出しをスケジュールし、すぐに返します。Lambda 関数の結果に依存しない特定のワークフローでは、Event 呼び出しタイプを使用します。

SELECT * FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'Event');

例: 関数レスポンスからの Lambda 実行ログのキャプチャリング

関数レスポンスに実行ログの最後の 4 KB を含めるには、log_type パラメーターを使用しながら aws_lambda.invoke 関数を呼び出します。デフォルトでは、このパラメータには None が設定されています。レスポンス内の Lambda 実行ログの結果をキャプチャする場合は、以下のように Tail を指定します。

SELECT *, select convert_from(decode(log_result, 'base64'), 'utf-8') as log FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'RequestResponse', 'Tail');

aws_lambda.invoke 関数の log_type パラメータを Tail に設定して、実行ログをレスポンスに含めます。この log_type パラメータのデフォルト値は None です。

返された log_result は、base64 エンコードされた文字列です。このコンテンツは、decodeconvert_from PostgreSQL 関数の組み合わせを使用してデコードできます。

log_typeの詳細については、「aws_lambda.invoke」を参照してください。

例: Lambda 関数にクライアントコンテキストを含める

aws_lambda.invoke 関数では、次に示すとおり context パラメータを使用して、ペイロードとは別の情報を渡すことができます。

SELECT *, convert_from(decode(log_result, 'base64'), 'utf-8') as log FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'RequestResponse', 'Tail');

クライアントコンテキストを含めるときは、aws_lambda.invoke 関数の context パラメータに JSON オブジェクトを使用します。

context パラメータの詳細については、「aws_lambda.invoke」でリファレンスを参照してください。

例: Lambda 関数の特定のバージョンの呼び出し

aws_lambda.invoke 呼び出しに qualifier パラメータを含めることで、Lambda 関数の特定のバージョンを指定することが可能です。以下は、'custom_version' をバージョンのエイリアスに使用してこれを行う場合の例です。

SELECT * FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json, 'RequestResponse', 'None', NULL, 'custom_version');

代わりに、Lambda 関数名の詳細により、次のように関数の修飾子を指定することもできます。

SELECT * FROM aws_lambda.invoke(aws_commons.create_lambda_function_arn('my-function:custom_version', 'us-west-2'), '{"body": "Hello from Postgres!"}'::json);

qualifier および他のパラメータの詳細については、「aws_lambda.invoke」でリファレンスを参照してください。

Lambda 関数のエラーメッセージ

次のリストに、エラーメッセージに関する情報と、考えられる原因と解決策を示します。

  • VPC 設定の問題

    VPC の設定の問題により、接続しようとすると、次のエラーメッセージが表示されることがあります。

    ERROR: invoke API failed DETAIL: AWS Lambda client returned 'Unable to connect to endpoint'. CONTEXT: SQL function "invoke" statement 1

    このエラーの一般的な原因は、VPC セキュリティグループが不適切に設定されていることです。VPC セキュリティグループのアウトバウンドルールで、ポート 443 が TCP に対して開いており、VPC が Lambda VPC に接続できるようになっていることを確認します。

  • Lambda 関数を呼び出すために必要な許可がない

    次のいずれかのエラーメッセージが表示された場合、関数を呼び出しているユーザー (ロール) に適切な許可がありません。

    ERROR: permission denied for schema aws_lambda
    ERROR: permission denied for function invoke

    Lambda 関数を呼び出すには、ユーザー (ロール) に特定の許可を付与する必要があります。詳細については、「ステップ 6: 他のユーザーに Lambda 関数を呼び出す許可を付与する」を参照してください。

  • Lambda 関数での不適切なエラー処理

    リクエストの処理中に Lambda 関数が例外をスローした場合、aws_lambda.invoke は、次のように PostgreSQL エラーで失敗します。

    SELECT * FROM aws_lambda.invoke(:'aws_lambda_arn_1', '{"body": "Hello from Postgres!"}'::json); ERROR: lambda invocation failed DETAIL: "arn:aws:lambda:us-west-2:555555555555:function:my-function" returned error "Unhandled", details: "<Error details string>".

    Lambda 関数または PostgreSQL アプリケーションの中でエラーに対処します。