プライベートサブネットからDynamoDBにアクセスする2つの方法
プライベートサブネット内のEC2インスタンスからDynamoDBにアクセスするための方法は、以下の2つがあります。
- NATゲートウェイ
- VPC Endpoint(ゲートウェイタイプ)
本ページでは、上記の2つを経由してDynamoDBテーブルにアクセスする方法を確認します。
構築する環境
2つのAZに1つずつプライベートサブネットを作成します。
各サブネットにEC2インスタンスを配置します。
インスタンスは最新のAmazon Linux 2とします。
NATゲートウェイおよびゲートウェイタイプのVPCエンドポイントを作成します。
各インスタンスにそれらを通じてDynamoDB向けに通信できるように、セキュリティグループやルートテーブル等を設定します。
なお今回の構成はap-northeast-1(東京)リージョンで構築します。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-saa/tree/main/03/004
テンプレートファイルのポイント解説
NATゲートウェイ
Resources:
IGW:
Type: AWS::EC2::InternetGateway
IGWAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref IGW
EIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NATGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt EIP.AllocationId
SubnetId: !Ref PublicSubnet
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp1
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone1}"
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp2
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone1}"
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
RouteToInternet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IGW
PublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref PublicRouteTable
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
RouteToNATGateway:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NATGateway
PrivateSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable1
Code language: YAML (yaml)
パブリックサブネット上にNATゲートウェイを作成します。
プライベートサブネット上のインスタンスが、NATゲートウェイを経由してDynamoDBバケットと通信できるように、ルートテーブルを以下の通りに設定します。
- プライベートサブネット用のルートテーブル:NATゲートウェイ向けにデフォルトルートを設定
- パブリックサブネット用のルートテーブル:インターネットゲートウェイ向けにデフォルトルートを設定
DynamoDB用のVPCエンドポイント
Resources:
GatewayDynamoDBEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PrivateRouteTable2
ServiceName: !Sub "com.amazonaws.${AWS::Region}.dynamodb"
VpcEndpointType: Gateway
VpcId: !Ref VPC
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp3
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone2}"
PrivateRouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
PrivateSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable2
Code language: YAML (yaml)
ゲートウェイタイプのエンドポイントを作成する場合は、RouteTableIdsプロパティにルートテーブルを指定します。
ルートテーブルは特別なルートは指定する必要はありません。
VPCエンドポイントに関連づけることで、自動的にルートが登録されます。
(参考) DynamoDBテーブル
Resources:
Table:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: Artist
AttributeType: S
- AttributeName: SongTitle
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: Artist
KeyType: HASH
- AttributeName: SongTitle
KeyType: RANGE
TableClass: STANDARD
TableName: !Sub "${Prefix}-Music"
Code language: YAML (yaml)
特別な設定は行いません。
以下のAWS公式ページで紹介されている構成を、CloudFormationテンプレートに書き出しました。
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/getting-started-step-1.html
DynamoDBに関する基本的な事項に関しては、以下のページもご確認ください。
(参考) EC2インスタンス
Resources:
Instance1:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref InstanceProfile
ImageId: !Ref ImageId
InstanceType: !Ref InstanceType
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref PrivateSubnet1
GroupSet:
- !Ref InstanceSecurityGroup
Instance2:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref InstanceProfile
ImageId: !Ref ImageId
InstanceType: !Ref InstanceType
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref PrivateSubnet2
GroupSet:
- !Ref InstanceSecurityGroup
Code language: YAML (yaml)
各プライベートサブネットにEC2インスタンスを1台配置します。
以下がインスタンス用のIAMロールです。
Resources:
InstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- ec2.amazonaws.com
Policies:
- PolicyName: AccessS3Policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- dynamodb:*
Resource:
- !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${Table}"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Code language: YAML (yaml)
先述のDynamoDBテーブルに対する全アクションを許可する内容です。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- インスタンス1:i-01fc2da5b7f33df18
- インスタンス2:i-0eebb182d0fe97317
- DynamoDBテーブル:saa-03-004-Music
- NATゲートウェイ:nat-0568dd9fb3f9fa0ff
- VPCエンドポイント:vpce-0ec6434db586081b9
AWS Management Consoleから各リソースを確認します。
NATゲートウェイを確認します。
正常に作成されています。
CloudFormationで作成したEIPが正常にアタッチされていることもわかります。
VPCエンドポイントを確認します。
確かにDynamoDB向けにゲートウェイタイプのVPCエンドポイントが作成されていることがわかります。
動作確認
NATゲートウェイを経由してDynamoDBテーブルにアクセス
準備が整いましたので、インスタンス1にアクセスします。
アクセスはSSM Session Managerを使用します。
% aws ssm start-session --target i-01fc2da5b7f33df18
...
sh-4.2$
Code language: Bash (bash)
SSM Session Managerの詳細につきましては、以下のページをご確認ください。
DynamoDBにテスト用アイテムを保存後、テーブル内のデータを確認します。
sh-4.2$ aws dynamodb put-item \
--table-name saa-03-004-Music \
--item '{"Artist": {"S": "aaa"}, "SongTitle": {"S": "AAA"}}' \
--region ap-northeast-1
sh-4.2$ aws dynamodb scan \
--table-name saa-03-004-Music \
--region ap-northeast-1
{
"Count": 1,
"Items": [
{
"SongTitle": {
"S": "AAA"
},
"Artist": {
"S": "aaa"
}
}
],
"ScannedCount": 1,
"ConsumedCapacity": null
}
Code language: Bash (bash)
確かにNATゲートウェイ経由で、DynamoDBテーブルにアクセスすることができました。
VPCエンドポイント経由でDynamoDBテーブルにアクセス
同様にSSM Session Managerを使用して、インスタンス2にアクセスします。
% aws ssm start-session --target i-0eebb182d0fe97317
...
sh-4.2$
Code language: Bash (bash)
先ほどと同様にテストデータの保存と確認を行います。
sh-4.2$ aws dynamodb put-item \
--table-name saa-03-004-Music \
--item '{"Artist": {"S": "bbb"}, "SongTitle": {"S": "BBB"}}' \
--region ap-northeast-1
sh-4.2$ aws dynamodb scan \
--table-name saa-03-004-Music \
--region ap-northeast-1
{
"Count": 2,
"Items": [
{
"SongTitle": {
"S": "BBB"
},
"Artist": {
"S": "bbb"
}
},
{
"SongTitle": {
"S": "AAA"
},
"Artist": {
"S": "aaa"
}
}
],
"ScannedCount": 2,
"ConsumedCapacity": null
}
Code language: Bash (bash)
確かにVPCエンドポイント経由で、DynamoDBテーブルにアクセスすることができました。
まとめ
プライベートサブネットからS3にアクセスする2つの方法(NATゲートウェイ、ゲートウェイタイプのVPCエンドポイント)を確認しました。