Amazon Bedrock RAG 環境用 AWS CloudFormation テンプレート series 1 VPC 編

本記事は 夏休みクラウド自由研究 8/1付の記事です

こんにちは、広野です。

以前、以下の記事で Amazon Bedrock や Agents for Amazon Bedrock を使用した最小構成 RAG 環境構築を紹介しておりました。当時はAmazon Bedrock 関連のリソースを一部 AWS CloudFormation ではデプロイできなかったのですが、今はサポートされたためにできるようになりました。

当時の構成を現在は変更しており、Knowledge Base に使用するデータベースを Amazon OpenSearch Serverless から Aurora Serverless v2 Postgresql に変更しています。

本シリーズ記事では、環境構築用の AWS CloudFormation のサンプルテンプレートを 3 記事に分けて紹介します。説明を分割するため、テンプレートを3つに分けていますのでご了承ください。

初回は VPC 編です。

本記事で取り扱う構成

RAG 環境全体の構成

以下のアーキテクチャで、RAG アプリケーションを構築しています。このうち、赤枠の部分が本シリーズ記事で取り扱う箇所です。series 1 VPC 編では、Amazon Aurora Serverless v2 Postgresql を構築する際に必要な VPC について説明します。

VPC の構成

Amazon Aurora Serverless v2 をデプロイするためには VPC が必要になります。サーバーレスなんですが、VPC リソースからアクセス可能にするためにそのような仕様にしているのだと思います。以下の VPC を用意します。

  • Aurora Serverless はプライベートサブネットに配置します。リーダーインスタンスやレプリカは設定していません。
  • Aurora Serverless を配置するときに、RDS サブネットグループが必要になります。任意の 2 つ以上のサブネットをグループに登録します。これが Aurora Serverless の設定で必要になるため、マルチ AZ 構成が必須になります。
  • データベースなので、プライベートサブネットに配置します。選択したサブネットに、VPC 内からアクセスするためのエンドポイントが作成されます。ただし Agents for Amazon Bedrock からは Data API 経由で接続するため、VPC は通りません。
  • エンドポイントにはセキュリティグループを関連付けます。ここでは、サブネットの CIDR から Postgresql に接続するためのデフォルトポート番号を開けておきます。
  • Agents for Amazon Bedrock が Aurora Serverless に接続するときのクレデンシャルは、Secrets Manager から取得します。これについては次回の記事で紹介します。
  • NAT ゲートウェイは本記事では省略しました。

AWS CloudFormation テンプレート

図に掲載している、Amazon Aurora Serverless、Agents for Amazon Bedrock、Secrets Manager は次回記事のテンプレートに含まれます。

Aurora Serverless で使用する RDS サブネットグループとセキュリティグループはここで作成し、次回のテンプレートで使用するためリソース情報をエクスポートしておきます。

AZ は仕様上、使用可能な 2 つの AZ をアルファベット順に前から選定します。東京リージョンだと b が使用できないため a と c が選定されますが、多くのリージョンでは a と b が選定されます。ここでは、東京リージョンでの使用を想定して a と c がリソースの名前に使用されています。ご注意ください。

AWSTemplateFormatVersion: 2010-09-09
Description: The CloudFormation template that creates A VPC, Subnets, an Internet Gateway and Routings. Additionally, a RDS subnet group and a security group for Aurora serverless.

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Parameters:
  SubName:
    Type: String
    Description: System sub name of sample. (e.g. test)
    Default: test
    MaxLength: 10
    MinLength: 1

  VPCCIDR:
    Type: String
    Description: IP Address range for your VPC (16 bit mask)
    Default: 192.168.0.0/16
    MaxLength: 14
    MinLength: 10
    AllowedPattern: ^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){2}0\.0/16$

  PublicSubnetACIDR:
    Type: String
    Description: IP Address range for your public subnet A (24 bit mask)
    Default: 192.168.1.0/24
    MaxLength: 16
    MinLength: 10
    AllowedPattern: ^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}0/24$

  PublicSubnetCCIDR:
    Type: String
    Description: IP Address range for your public subnet C (24 bit mask)
    Default: 192.168.2.0/24
    MaxLength: 16
    MinLength: 10
    AllowedPattern: ^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}0/24$

  PrivateSubnetACIDR:
    Type: String
    Description: IP Address range for your private subnet A (24 bit mask)
    Default: 192.168.101.0/24
    MaxLength: 16
    MinLength: 10
    AllowedPattern: ^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}0/24$

  PrivateSubnetCCIDR:
    Type: String
    Description: IP Address range for your private subnet C (24 bit mask)
    Default: 192.168.102.0/24
    MaxLength: 16
    MinLength: 10
    AllowedPattern: ^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}0/24$

Resources:
# ------------------------------------------------------------#
#  VPC
# ------------------------------------------------------------#
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: !Sub sample-VPC-${SubName}
        - Key: Cost
          Value: !Sub sample-${SubName}

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub sample-IGW-${SubName}
        - Key: Cost
          Value: !Sub sample-${SubName}

  InternetGatewayAttachment: 
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

# ------------------------------------------------------------#
#  Subnet
# ------------------------------------------------------------#
  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select
        - 0
        - Fn::GetAZs: !Ref AWS::Region
      CidrBlock: !Ref PublicSubnetACIDR
      MapPublicIpOnLaunch: true
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub sample-Public-a-${SubName}
        - Key: Cost
          Value: !Sub sample-${SubName}

  PublicSubnetC:
    Type: AWS::EC2::Subnet
    Properties: 
      AvailabilityZone: !Select
        - 1
        - Fn::GetAZs: !Ref AWS::Region
      CidrBlock: !Ref PublicSubnetCCIDR
      MapPublicIpOnLaunch: true
      VpcId: !Ref VPC 
      Tags:
        - Key: Name
          Value: !Sub sample-Public-c-${SubName}
        - Key: Cost
          Value: !Sub sample-${SubName}
                    
  PrivateSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select
        - 0
        - Fn::GetAZs: !Ref AWS::Region
      CidrBlock: !Ref PrivateSubnetACIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub sample-Private-a-${SubName}
        - Key: Cost
          Value: !Sub sample-${SubName}

  PrivateSubnetC: 
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select
        - 1
        - Fn::GetAZs: !Ref AWS::Region
      CidrBlock: !Ref PrivateSubnetCCIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub sample-Private-c-${SubName}
        - Key: Cost
          Value: !Sub sample-${SubName}

# ------------------------------------------------------------#
#  Subnet Group for RDS
# ------------------------------------------------------------#
  PrivateSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupName: !Sub sample-${SubName}
      DBSubnetGroupDescription: !Sub Subnet Group for KB database for sample-${SubName}
      SubnetIds:
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetC
      Tags:
        - Key: Cost
          Value: !Sub sample-${SubName}

# ------------------------------------------------------------#
#  Security Group for RDS
# ------------------------------------------------------------#
  AuroraSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub bedrock-rag-kb-sample-${SubName}
      GroupDescription: !Sub Allow Aurora PostgreSQL for sample-${SubName}
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 5432
          ToPort: 5432
          CidrIp: !Ref PrivateSubnetACIDR
        - IpProtocol: tcp
          FromPort: 5432
          ToPort: 5432
          CidrIp: !Ref PrivateSubnetCCIDR
      Tags:
        - Key: Cost
          Value: !Sub sample-${SubName}
        - Key: Name
          Value: !Sub sg-bedrock-rag-kb-sample-${SubName}

# ------------------------------------------------------------#
#  RouteTable
# ------------------------------------------------------------#
  PublicRouteTableA:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
          
  PublicRouteTableC:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

  PrivateRouteTableA:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

  PrivateRouteTableC:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

# ------------------------------------------------------------#
# Routing to Internet
# ------------------------------------------------------------#
  PublicRouteA:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTableA
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicRouteC:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTableC
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

# ------------------------------------------------------------#
# RouteTable Associate
# ------------------------------------------------------------#
  PublicSubnetARouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTableA

  PublicSubnetCRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetC
      RouteTableId: !Ref PublicRouteTableC
                
  PrivateSubnetARouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetA
      RouteTableId: !Ref PrivateRouteTableA

  PrivateSubnetCRouteTableAssociation: 
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetC
      RouteTableId: !Ref PrivateRouteTableC

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# Subnet
  PrivateSubnetGroupName:
    Value: !Ref PrivateSubnetGroup
    Export:
      Name: !Sub sample-${SubName}-PrivateSubnetGroupName
# Security Group
  AuroraSecurityGroupId:
    Value: !Ref AuroraSecurityGroup
    Export:
      Name: !Sub sample-${SubName}-AuroraSecurityGroupId

まとめ

いかがでしたでしょうか?

VPC 作成テンプレートはどこにでもある情報だと思いますし、マネジメントコンソールでも以前より簡単に作れるようになっているので必要性は低いかもしれませんが、私は普段からこのテンプレートを活用して VPC をデプロイしています。

次回は Knowledge Base 用 Aurora Serverless のデプロイがテーマです。

本記事が皆様のお役に立てれば幸いです。

著者について
広野 祐司

AWS サーバーレスアーキテクチャを駆使して社内クラウド人材育成アプリとコンテンツづくりに勤しんでいます。React で SPA を書き始めたら快適すぎて、他の言語には戻れなくなりました。サーバーレス & React 仲間を増やしたいです。AWSは好きですが、それよりもフロントエンド開発の方が好きでして、バックエンド構築を簡単にしてくれたAWSには感謝の気持ちの方が強いです。
取得資格:AWS 認定は13資格、ITサービスマネージャ、ITIL v3 Expert 等
2020 - 2024 Japan AWS Top Engineer 受賞
2022 - 2024 AWS Ambassador 受賞
2023 当社初代フルスタックエンジニア認定
好きなAWSサービス:AWS Amplify / AWS AppSync / Amazon Cognito / AWS Step Functions / AWS CloudFormation

広野 祐司をフォローする

クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(AWS)は、企業価値の向上につながるAWS 導入を全面支援するオールインワンサービスです。AWS最上位パートナーとして、多種多様な業界のシステム構築実績を持つSCSKが、お客様のDX推進を強力にサポートします。

AI・MLAWSクラウドソリューションデータベース
シェアする
タイトルとURLをコピーしました