プライベートサブネットからDynamoDBにアクセスする2つの方法

目次

プライベートサブネットからDynamoDBにアクセスする2つの方法

プライベートサブネット内のEC2インスタンスからDynamoDBにアクセスするための方法は、以下の2つがあります。

  • NATゲートウェイ
  • VPC Endpoint(ゲートウェイタイプ)

本ページでは、上記の2つを経由してDynamoDBテーブルにアクセスする方法を確認します。

構築する環境

Diagram of two ways to access DynamoDB from private subnet.

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に関する基本的な事項に関しては、以下のページもご確認ください。

あわせて読みたい
DynamoDB入門 – レビューデータ用DB構築 【DynamoDBでシンプルなレビューデータ用DBを構築する】 AWS DVAの出題範囲の1つでもある、AWSのサービスによる開発に関する内容です。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スタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • インスタンス1:i-01fc2da5b7f33df18
  • インスタンス2:i-0eebb182d0fe97317
  • DynamoDBテーブル:saa-03-004-Music
  • NATゲートウェイ:nat-0568dd9fb3f9fa0ff
  • VPCエンドポイント:vpce-0ec6434db586081b9

AWS Management Consoleから各リソースを確認します。

NATゲートウェイを確認します。

Detail of VPC Endpoint 1.

正常に作成されています。
CloudFormationで作成したEIPが正常にアタッチされていることもわかります。

VPCエンドポイントを確認します。

Detail of VPC Endpoint 2.

確かに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の詳細につきましては、以下のページをご確認ください。

あわせて読みたい
LinuxインスタンスにSSM Session Manager経由でアクセスする 【LinuxインスタンスにSSM Session Manager経由でアクセスする】 EC2インスタンスにSSM Session Manager経由でアクセスする構成を確認します。 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エンドポイント)を確認しました。

目次