AWS Lambda トリガーを作成して、DynamoDB テーブルからのストリームを処理して確認する

2021.03.31

こんにちは、yagiです。

本日は、AWS Lambda トリガーを作成して、DynamoDB テーブルからのストリームを処理して確認するまでを実施しました。

DynamoDB ストリームとは?

DynamoDB ストリーム はDynamoDB、テーブル内の項目レベルの変更の時系列シーケンスをキャプチャし、この情報を最大 24 時間ログに保存します。アプリケーションは、このログにアクセスし、データ項目の変更前および変更後の内容をほぼリアルタイムで参照できます。

DynamoDB ストリーム は以下のことを確認するのに役立ちます。

・各ストリームレコードは、ストリームに 1 回だけ出現します。

・DynamoDB テーブルで変更された各項目について、ストリームレコードは項目に対する実際の変更と同じ順序で出現します。

DynamoDB ストリーム は、ストリームレコードをほぼリアルタイムで書き込むため、これらのストリームを使用し、内容に基づいてアクションを実行するアプリケーションを構築できます。

(公式ドキュメントからの引用)

上記について、公式ドキュメントのチュートリアルを使用して試してみました。

設定してみた

チュートリアル: DynamoDB ストリーム および Lambdaを使用して新しい項目を処理する

上記公式ドキュメントのチュートリアルにしたがって進めて行きましたが、途中でエラーとなり対応したポイントがありましたのでご紹介しようと思います。 なお、以下のステップで進めました。

Step 1. ストリームが有効になった DynamoDB テーブルを作成する

Step 2. Lambda 実行ロールを作成する

Step 3. Amazon SNS トピックを作成する

Step 4. Lambda 関数を作成してテストする

Step 5. トリガーを作成してテストする

Step 1に入る前に、AWS CLIのインストール及び設定を行います。 AWS CLIのインストール、更新、およびアンインストール

なおスイッチロールを使う場合に、スイッチ元でMFAの設定をされている場合は、mfa_serialの設定が必要です。 【小ネタ】AWS CLIでスイッチロールして作業を行うための設定をやってみた

設定できたら動作確認します。試しにS3のフォルダをlsしてみます。MFAの設定をしている場合はパスワードを聞いてくるので入力します。

(例)

% aws s3 ls --profile **********
Enter MFA code for arn:aws:iam::XXXXXXXXXXXX:mfa/**********: 
2021-03-19 14:44:44 **********cloudfront-test
2021-03-19 08:53:22 **********test-elb
2021-03-19 08:54:45 **********test-elb1
2021-03-16 15:25:46 **********opsworks-cookbook-test
2021-03-08 10:17:01 elasticbeanstalk-ap-northeast-1-XXXXXXXXXXXX
```

このように参照できれば設定OKです。

Step 1. ストリームが有効になった DynamoDB テーブルを作成する

チュートリアルにしたがって、テーブルを作成します。

aws dynamodb create-table \
    --table-name BarkTable \
    --attribute-definitions AttributeName=Username,AttributeType=S AttributeName=Timestamp,AttributeType=S \
    --key-schema AttributeName=Username,KeyType=HASH  AttributeName=Timestamp,KeyType=RANGE \
    --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
    --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES

作成したテーブルを確認します。

% aws dynamodb describe-table \
    --table-name BarkTable
{

```
        "TableName": "BarkTable",
        "KeySchema": [
            {
                "AttributeName": "Username",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "Timestamp",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": "2021-03-30T14:33:10.745000+02:00",
```

確認できました。

Step 2. Lambda 実行ロールを作成する

チュートリアルに従って実行ロールを作成します。作成した実行ロールWooferLambdaRoleを参照して確認します。

% aws iam get-role --role-name WooferLambdaRole
{
    "Role": {
        "Path": "/service-role/",
        "RoleName": "WooferLambdaRole",
        "RoleId": "*********************",
        "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/service-role/WooferLambdaRole",
        "CreateDate": "2021-03-29T13:03:11+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        },
        "MaxSessionDuration": 3600,
        "RoleLastUsed": {
            "LastUsedDate": "2021-03-31T07:11:13+00:00",
            "Region": "ap-northeast-1"
        }
    }
}

Step 3. Amazon SNS トピックを作成する

チュートリアルにしたがって、Amazon SNS トピック (wooferTopic) を作成し、そのトピックに E メールアドレスをサブスクライブします。 すると確認メールが来るので、Confirm subscription を押下します。

Confirmされたことを確認して、次に進めます。

Step 4. Lambda 関数を作成してテストする

チュートリアルにしたがって進めていきますが、自分は以下のコマンドを入力した際に、リージョンを指定する必要がありました。(最初リージョンを指定せずに実行したらバージニア北部にLambda関数が作成されていました。)

aws lambda create-function \
    --region us-east-1 \
    --function-name publishNewBark \
    --zip-file fileb://publishNewBark.zip \
    --role roleARN \
    --handler publishNewBark.handler \
    --timeout 5 \
    --runtime nodejs10.x \
    --region ap-northeast-1

上記の通りリージョンを指定してLambda関数を作成します。 以下のコマンドでLambda関数を実行してテストしたところ、Invalid base64 エラーとなりました。

% aws lambda invoke  --function-name publishNewBark --payload file://payload.json output.txt

Invalid base64: "{

 ```
 
}"

こちらはコマンドラインに --cli-binary-format raw-in-base64-out を加えることで解消できます。詳しくはこちらに記載があります。 重要な変更 – AWS CLI バージョン 1 からバージョン 2 への移行

 % aws lambda invoke  --function-name publishNewBark --payload file://payload.json output.txt --cli-binary-format raw-in-base64-out
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

無事確認できました。 メールも届きました。

Step 5. トリガーを作成してテストする

トリガーを作成します。

% aws lambda create-event-source-mapping \
    --region ap-northeast-1 \
    --function-name publishNewBark \
    --event-source arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/BarkTable/stream/2021-03-30T12:33:10.745 \
    --batch-size 1 \
    --starting-position TRIM_HORIZON
{
    "UUID": "******-****-****-****-********",
    "BatchSize": 1,
    "MaximumBatchingWindowInSeconds": 0,
    "ParallelizationFactor": 1,
    "EventSourceArn": "arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/BarkTable/stream/2021-03-30T12:33:10.745",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:publishNewBark",
    "LastModified": "2021-03-31T10:27:38.747000+02:00",
    "LastProcessingResult": "No records processed",
    "State": "Creating",
    "StateTransitionReason": "User action",
    "DestinationConfig": {
        "OnFailure": {}
    },
    "MaximumRecordAgeInSeconds": -1,
    "BisectBatchOnFunctionError": false,
    "MaximumRetryAttempts": -1
}

トリガーをテストします。

aws dynamodb put-item \
    --table-name BarkTable \
    --item Username={S="Jane Doe"},Timestamp={S="2016-11-18:14:32:17"},Message={S="Testing...1...2...3"}

メールが来たことを確認します。

結論

AWS Lambda トリガーを作成して、DynamoDB テーブルからのストリームを処理して確認するまでを実施しました。 AWS CLI v2でのLambdaのInvalid base64エラーなども調査しましたのでその内容もあわせて記載しました。どこかでどなたかのお役にたてば嬉しいです。

参考リンク

Amazon DynamoDB とは

AWS Lambda とは