Amazon DocumentDBの変更ストリームをイベントソースとしてAWS Lambdaを実行させてみた

こんにちは。サービス部の武田です。AWS Lambdaはイベントソースマッピングを使用することで、イベントソースの変更をトリガーにLambda関数を実行できます。DocumentDBも対応したため試してみました。
2023.03.30

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

こんにちは。サービス部の武田です。

AWS Lambdaはイベントソースマッピングを使用することで、イベントソースの変更をトリガーにLambda関数を実行できます。先日イベントソースとしてDocumentDBがサポートされたため、試してみました。

やってみた

作業を進めるにあたって、次の2つの環境は構築済みという前提で進めます。

  • VPC
  • Cloud9

DocumentDBはユーザーVPCで動作します。また一般的にはプライベートサブネットに配置しますので、それらはあるものとします。一般的なデフォルトVPCで要件としては十分です。

またDocumentDBへのアクセスには、同じVPC内にEC2などを用意する必要があります。SSHトンネリングでローカルからアクセスもできますが、今回はCloud9のターミナルを前提とします。

DocumentDBクラスター作成

まずはDocumentDBクラスターを作成します。いきなりですが、次の制限事項があります。

  • エンジンバージョンは 4.0のみ サポート
    • 3.6と5.0はサポート外
  • Elasticクラスターおよびグローバルクラスターはサポート外
  • ペイロードのサイズは6MBまで

つまりエンジンバージョン4.0の、リージョナルクラスターのみが対象ということになります。利用を検討している方は注意してください。

はじめてクラスターを作成する場合は、先にサブネットグループを作成します(defualtが使えるならそれでもOK)。

使用するVPCのプライベートサブネットを指定します。

次にインスタンスベースのクラスターを作成します。

マスターユーザーの設定をします。

残りはデフォルト設定で進め、クラスターを作成します。

ChangeStreams有効化

クラスターが作成できたら、ChangeStremasを有効化しましょう。Cloud9のターミナルからアクセスします。Cloud9へのmongo Shellのインストールなどは、参考URLのGet Startedを参考にしてください。

ChangeStremasの有効化は次のコマンドを実行します。今回は、有効化するデータベースとしてeventsを指定しています。

db.adminCommand({modifyChangeStreams: 1,
    database: "events",
    collection: "",
    enable: true});

Secrets Managerでシークレット作成

クラスター作成時に設定した認証情報をSecrets Managerのシークレットとして登録します。これはLambda関数がDocumentDBへアクセスするために使用されます。

シークレットのタイプは「Amazon DocumentDB データベースの認証情報」です。

データベースとして、先ほど作成したクラスターを選びます。

シークレットの名前として任意の名前を付けます。

残りはデフォルトで問題ありません。

VPCエンドポイント追加

Lambda関数からVPC内のリソースであるDocumentDBにアクセスするため、VPC Lambdaとして作成します。VPC Lambdaは特に設定をしないとVPC外のリソースにアクセスできません。具体的にはVPCエンドポイントかNATゲートウェイを用意する必要があります。

今回はVPCエンドポイントを作成しました。VPCエンドポイントの場合は、次の3つのサービスをサポートする必要があります。

  • STS
  • Lambda
  • Secrets Manager

Lambda関数作成

イベントハンドラとなるLambda関数を作成します。言語はなんでもよいですが、今回はJavaScriptにしました。また処理は単に受け取ったデータをログに出力するだけです。 VPC を有効化 にチェックを入れることを忘れないでください。

export const handler = async(event) => {
    console.log(event);
    console.log(event.events[0]);
};

IAMロールにポリシー追加

作成したLambda関数に紐付けられているIAMロールにポリシーを追加します。CloudWatch Logsなどの基本的なポリシーはすでにアタッチされているはずですので、差分となる次の権限を追加しましょう。余談ですが、DocumentDBって内部的にはRDSの扱いなんですね。知りませんでした。

ec2:DescribeSecurityGroups
ec2:DescribeSubnets
ec2:DescribeVpcs
kms:Decrypt
rds:DescribeDBClusterParameters
rds:DescribeDBClusters
rds:DescribeDBSubnetGroups
secretsmanager:GetSecretValue

Lambda関数のトリガー設定

先ほど作成したLambda関数にトリガーを追加します。ソースとしてDocumentDB、データベース名にはeventsを指定しています。

認証情報としてBASIC_AUTHを選択し、Secrets Managers キーに、先ほど追加したシークレットを指定します。

作成したら、有効化されるまで少し待ちましょう。

実行してみる

これで準備が整いました。mongo Shellで次のスニペットを実行します。

use events

[...Array(2)].map((_, i) => db.collection.insert({"name":`events_${i}`}))

CloudWatch Logsに次のようなログが出力されました。

{
  eventSourceArn: 'arn:aws:rds:ap-northeast-1:123456789012:cluster:docdb-2023-03-29-08-51-34',
  events: [ { event: [Object] }, { event: [Object] } ],
  eventSource: 'aws:docdb'
}

{
  event: {
    _id: { _data: '016424dd5c000000060100000006000041f0' },
    clusterTime: { '$timestamp': [Object] },
    documentKey: { _id: [Object] },
    fullDocument: { _id: [Object], name: 'events_0' },
    ns: { db: 'events', coll: 'collection' },
    operationType: 'insert'
  }
}

まとめ

DocumentDBのChangeStreamsをLambda関数で処理させてみました。DocumentDBのバージョンや、VPC Lambda特有の罠がいくつかあるように感じました。

Lambda関数で処理できるとアーキテクチャ選択にも幅ができますのでとてもいいですね。DocumentDBを利用している方は、ぜひ導入を検討してみてください。

参考URL