Amazon Aurora PostgreSQLからLambda関数を呼び出せるようになりました #reinvent

2020.12.13

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

Amazon Aurora MysQLからLambdaを呼べるようになってからはや4年、ようやくAurora PostgreSQLからもLambdaを呼べるようになりました。

さっそく試してみました。

Amazon Aurora PostgreSQL Integrates with AWS Lambda

Amazon Aurora with PostgreSQL compatibility can now make calls to AWS Lambda functions. AWS Lambda lets you run code without provisioning or managing servers, and without worrying about scalability.

Amazon Aurora PostgreSQL からの外部サービスの呼び出しに Lambda が追加

Aurora PostgreSQL 内部からは様々な形で外部サービスを呼び出すことができます。

PostgreSQL に備わっている Foreign Data Wrapper(postgres_fdw) はもちろんのこと、 AWS とのシームレスな連携として S3 や最近では SageMaker や Comprehend といった機械学習系サービスとも連携しています。

今回のアップデートにより、AWS Lambda もその仲間に追加されました。

図は 「re:Invent 2020 : [DAT301]Deep dive on Amazon Aurora with PostgreSQL compatibility」から

手順概要

構成イメージ

  1. Lambda関数の作成
  2. IAM ポリシー・ロールの作成
  3. Aurora PostgreSQL の起動とIAMロールの紐付け
  4. Lambda用エクステンションの有効化
  5. Aurora PostgreSQL から Lambda 関数の呼び出し

前提

Aurora PostgreSQL 11.9 以降に対応

Aurora PostgreSQL を起動しようとすると、デフォルトではバージョン 11.7 が選択されます。 このバージョンは Lambda に対応していません。

$ aws rds add-role-to-db-cluster \
--db-cluster-identifier test  \
--feature-name Lambda \
--role-arn arn:aws:iam::123:role/rds-aurora-pg-role 

An error occurred (InvalidParameterValue) when calling the AddRoleToDBCluster operation: 
  The feature name Lambda is not valid for the Aurora PostgreSQL (Compatible with PostgreSQL 11.7) engine.

より新しい 11.9 以降を利用しましょう。

1. Lambda 関数の作成

任意のランタイムで Lambda 関数を作成してください。

2. IAM ポリシー・ロールの作成

PostgreSQL 向け Lambda 関数を呼び出す IAM ポリシーを作成します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAuroraToExampleFunction",
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "arn:aws:lambda:<region>:<123456789012>:function:example_function"
        }
    ]
}

次に、このポリシーを含んだ RDS 向け IAM ロールを作成します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": "rds.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
        }
    ] 
}

3. Aurora PostgreSQL の起動とIAMロールの紐付け

Aurora PostgreSQL を起動します。

現時点でデフォルトで選択されるバージョン 11.7 は Lambda 連携に対応していません。 11.9 以降を選択してください。

クラスター起動完了後、Feature : Lambda としてIAM ロールを紐付けます。

4. Lambda用エクステンションの有効化

RDS インスタンスに接続し、Lambda 用エクステンションを有効化します。

$ psql -h $HOST -U postgres
Password for user postgres:
psql (11.5, server 11.9)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=> \dx
                 List of installed extensions
  Name   | Version |   Schema   |         Description
---------+---------+------------+------------------------------
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
(1 row)


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

postgres=> \dx
                        List of installed extensions
    Name     | Version |   Schema   |              Description
-------------+---------+------------+---------------------------------------
 aws_commons | 1.2     | public     | Common data types across AWS services
 aws_lambda  | 1.0     | public     | AWS Lambda integration
 plpgsql     | 1.0     | pg_catalog | PL/pgSQL procedural language
(3 rows)

postgres=> \d aws_commons._lambda_function_arn_1;
  Composite type "aws_commons._lambda_function_arn_1"
    Column     | Type | Collation | Nullable | Default
---------------+------+-----------+----------+---------
 function_name | text |           |          |
 region        | text |           |          |

5. Aurora PostgreSQL から Lambda 関数の呼び出し

aws_lambda.invoke関数 で Lambda 関数を呼び出します。

aws_lambda.invoke関数のfunction_name に aws_commons.create_lambda_function_arn関数の実行結果を利用

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

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

aws_lambda.invoke関数のfunction_name に Lambda 関数の ARN を利用

postgres=> SELECT * FROM aws_lambda.invoke(
  'arn:aws:lambda:us-west-2:12345:function:my-function',
  '{"body": "Hello from Postgres!"}'::json);

非同期

Lambda:Invoke API と同じく、invocation typeEvent を指定すると、非同期呼び出しになります。

postgres=> SELECT * FROM aws_lambda.invoke(
  'arn:aws:lambda:us-west-2:12345:function:my-function',
  '{"body": "Hello from Postgres!"}'::json,
  'us-west-2',
  'Event');

 status_code | payload | executed_version | log_result
-------------+---------+------------------+------------
         202 |         |                  |
(1 row)

権限の付与

非マスターユーザーにはデフォルトでは aws_lambda の権限が付与されていないため、 ERROR: permission denied for schema aws_lambda エラーが発生します。

マスターユーザで各ユーザーに権限を付与してください。

GRANT USAGE ON SCHEMA aws_lambda TO <ユーザ名>;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA aws_lambda TO <ユーザ名>;

最後に

Aurora PostgreSQL から Lambda 関数を呼び出す方法を紹介しました。

PostgreSQL からは S3 や Comprehend など、特定の機能に特化したモジュールは提供されてきましたが、Lambda 関数用モジュールも提供されるようになり、より柔軟に外部サービスと連携できるようになりました。

Lambda は自由度が高いため、くれぐれもやりすぎにはご注意ください。

それでは。

参考