![]() |
こんにちは、広野です。
以前、以下の記事で 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 のデプロイがテーマです。
本記事が皆様のお役に立てれば幸いです。