RDS for PostgreSQL DB インスタンスから AWS Lambda 関数を呼び出す - Amazon Relational Database Service

RDS for PostgreSQL DB インスタンスから AWS Lambda 関数を呼び出す

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

注記

RDS for PostgreSQL では、以下のバージョンで AWS Lambda 関数の呼び出しがサポートされています。

  • 14.1 以降のマイナーバージョン

  • 13.2 以降のマイナーバージョン

  • 12.6 以降のマイナーバージョン

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

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

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

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

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

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

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

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

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

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

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

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

  3. VPC エンドポイントは、独自のプライベートな DNS 解決を使用します。rds.custom_dns_resolution の値がデフォルトの 0 (有効化されていない) から 1 に変更されない限り、RDS for PostgreSQL は、Lambda VPC エンドポイントを使用することはできません。

    1. カスタム DB パラメータグループを作成します。

    2. rds.custom_dns_resolution パラメータの値を、デフォルトの 0 から 1 に変更します。

    3. カスタムの DB パラメータグループを使用するように DB インスタンスを変更します。

    4. 修正されたパラメータを反映させるために、インスタンスを再起動します。

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

ステップ 2: RDS for PostgreSQL DB インスタンスおよび AWS Lambda のために IAM を設定する

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

Amazon RDS インスタンスで Lambda を使用するために IAM のアクセス許可を設定するには

  1. AWS CLI コマンド create-policy を実行して、指定された Lambda 関数を、RDS for PostgreSQL DB インスタンスが呼びだすことを許可する、IAM ポリシーを作成します。(ステートメント ID (Sid) は、ポリシーステートメントのオプションの記述であり、使用には影響しません。) このポリシーは、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-instance を使用して、このロールを RDS for PostgreSQL DB インスタンスに適用します。この最後のステップにより、DB インスタンスのデータベースユーザーに対し、Lambda 関数の呼び出しを許可します。

    aws rds add-role-to-db-instance \ --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 拡張機能は、RDS for PostgreSQL DB インスタンスの機能に対し何も追加しません。)

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

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

RDS for PostgreSQL DB インスタンスaws_lambda 拡張機能をインストールするには

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

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

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

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

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

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

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

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

  • [AWS Region] (リージョン) – (オプション) Lambda 関数が RDS for 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: RDS for PostgreSQL DB インスタンスから Lambda 関数を呼びだす」を参照してください。

ステップ 5: RDS for 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 instance.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 instance.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;

例: RDS for PostgreSQL DB インスタンスから Lambda 関数を呼びだす

以下に、aws_lambda.invoke 関数の呼び出し例をいくつか示します。ほとんどの例では、関数の詳細を簡単に渡せるように、ステップ 4: RDS for 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: RDS for 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 に接続できるようになっていることを確認します。

    プライベートの DB インスタンスを使用している場合は、VPC のプライベート DNS 設定を確認します。rds.custom_dns_resolution パラメータには 1 が設定されており、AWS PrivateLink は ステップ 1: RDS for PostgreSQL DB インスタンスで、AWS Lambda へのアウトバウンド接続を設定する。 での概説どおりにセットアップされていることを確認します。詳細については、「インターフェイス VPC エンドポイント (AWS PrivateLink)」を参照してください。

  • 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 アプリケーションの中でエラーに対処します。