この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
サーバーレス開発部改め、CX事業本部の佐藤です。
概要
VPC LambdaからDynamoDBにアクセスするユースケースがあったため、実際にやってみました。
VPCにあるRDSなどにアクセスする際は、VPC Lambdaにする必要があります。VPC Lambdaにした場合はLambdaのインターネットアクセスが失われるため、VPC以外のAWSリソースにはアクセスできません(DynamoDBなど)。VPC Lambdaがインターネットにアクセスする際は、AWSの制約でLambdaをプライベートサブネットに配置し、パブリックサブネットにNAT ゲートウェイを配置する必要があります。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/internet-access-lambda-function/
以前は、VPC LambdaからDynamoDBなどにアクセスする際は、この記事のようにNATゲートウェイを配置する必要があったんですが、VPC エンドポイントがDynamoDBに対応したため、VPCエンドポイント経由でアクセスすることが可能になりました。
https://aws.amazon.com/jp/blogs/news/new-vpc-endpoints-for-dynamodb/
実際に動かしていきたいと思います。
VPC、プライベートサブネット、セキュリティグループを作成する
VPCとプライベートサブネット、セキュリティーグループを作成します。マネージメントコンソールやCloudFormationで作成できます。今回は、CloudFormationで作成していきます。テスト用のDynamoDBテーブルも一緒に作成しています。
以下の内容でスタックを作成します。
AWSTemplateFormatVersion: 2010-09-09
Description: "Create VPC"
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
InstanceTenancy: default
Tags:
- Key: Name
Value: "blog"
PrivateSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.0.0/24
AvailabilityZone: ap-northeast-1a
Tags:
- Key: Name
Value: "Private Subnet A"
PrivateSubnetC:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: ap-northeast-1c
Tags:
- Key: Name
Value: "Private Subnet C"
VPCPrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
VPCPrivateSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetA
RouteTableId: !Ref VPCPrivateRouteTable
VPCPrivateSubnetCRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetC
RouteTableId: !Ref VPCPrivateRouteTable
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Lambda Security Group
VpcId: !Ref VPC
BlogTestTable:
Type: "AWS::DynamoDB::Table"
Properties:
AttributeDefinitions:
- AttributeName: "id"
AttributeType: "N"
KeySchema:
- AttributeName: "id"
KeyType: "HASH"
BillingMode: PAY_PER_REQUEST
CLIでスタックを作成します
aws cloudformation create-stack --stack-name 任意のスタック名 --template-body file://上記の保存したファイル名
VPC Lambdaを作成する
テスト用のVPC Lambdaを作成します。さきほど作ったVPCとサブネットを割り当てていきます。事前に、Lambdaに割り当てるIAMロールに適切なポリシーをアタッチしておいてください。
Lambdaを作成
- マネージメントコンソールからLambdaを選択します
-
関数の作成をクリックし、適当な名前を入力し、ランタイムにPython3.7を選択し、関数の作成をクリックします
- テスト用のコードを書きます。DynamoDBから1レコード取得して返すだけのものです
import json
import boto3
client = boto3.resource('dynamodb')
def lambda_handler(event, context):
table = client.Table(cloudformationで作成されたテーブル名)
res = table.get_item(Key={ "id": 1 })
item = res['Item']
return item
- Lambdaの設定画面のネットワークの項目で「非VPC」となっているところをさきほど作ったVPC、サブネット、セキュリティーグループを選択します
- 保存をクリックします
これでVPC Lambdaが作成できました。
VPC エンドポイントなしで実行してみる
VPCエンドポイントなしで、実行してみます。
DynamoDBのテーブルに適当なデータを一行追加して、先ほど作ったVPC Lambdaを実行してみます。実行すると以下のように、Lambdaがタイムアウトしてエラーになりました。インターネットアクセスがないため、DynamoDBにアクセスできていないようです。
VPCエンドポイントを設定する
プライベートサブネットに配置したLambdaからDynamoDBにアクセスするためにVPCエンドポイントを作成します。
- マネージメントコンソールからVPCを選択します
-
左側のメニューからエンドポイントを選択します
-
エンドポイントの作成をクリックします
- エンドポイントのサービス名の中から
com.amazonaws.リージョン名.dynamodb
を選択します
- VPC欄に先ほど作ったVPCを選択します。ルートテーブル欄で、VPC Lambdaが割り当てられているプライベートサブネットのルートテーブルを選択します
- エンドポイントの作成をクリックします
簡単にエンドポイントを作成できました。
VPCエンドポイントありで実行してみる
VPCエンドポイントを作成しましたので、Lambdaを再度実行してみます。さきほどはタイムアウトになっていましたが、今回はDynamoDBからデータが取得されました。
まとめ
VPCエンドポイントにより、簡単にVPC LambdaからAWSリソースにアクセスすることができるようになりました。VPC LambdaからVPC外のAWSリソースにアクセスする場合に参考にしてみてください。