こんにちは、つくぼし(tsukuboshi0755)です!
以前以下のブログで、マルチモーダルAIであるChatGPT V4を利用して、AWSの構成図からIaCコードを生成する方法を紹介しました。
そして最近、BedrockにもついにマルチモーダルAIを備えたClaude 3がリリースされました!
これにより、AWSのみでマルチモーダルAIを利用したシステムを完結させる事が可能になっています。
そこで今回は、S3にアップロードしたAWS構成図をCloudFormationテンプレートに変換し、別のS3にアップロードするシステムを作ってみたので紹介してみたいと思います。
なお変換したテンプレートは、CloudFormationスタック作成時にオブジェクトURLで指定する事でそのまま使用可能です!
前提条件
今回は下記ソフトウェアの使用を前提としています。
項目 | バージョン |
---|---|
AWS CLI | 2.4 |
AWS SAM CLI | 1.111 |
Python | 3.11 |
構成図
今回の構成図は以下になります。
今回構築するシステムが実施する処理は以下の通りです。
1. インプット用S3バケットにAWS構成図をアップロード
2. LambdaがS3にアップロードされた構成図を取得
3. Lambdaが構成図をloudFormationテンプレートに変換するようBedrock Claude 3にリクエスト
4. Lambdaが変換したテンプレートに対してValidateTemplateを用いて検証し、問題がある場合はテンプレート名にerrorを付与
5. テンプレート名に実行時刻をつけた上でアウトプット用S3バケットにテンプレートをアップロード
コード
今回使用するコードは以下のリポジトリにアップロードしています。
構築の流れ
事前準備
2023年3月現在では、Bedrock Claude 3 (Sonnet)はバージニア及びオレゴンでのみ利用可能です。
今回はオレゴンリージョンを利用するため、以下のリンクを参考にオレゴンでモデルアクセスを有効化します。
以下の通り、対象リージョンでBedrock Claude 3 (Sonnet)が有効化されていればOKです。
デプロイ
リポジトリをクローン後、SAMアプリをビルド及びデプロイします。
ここで構成図には記載されていないがテンプレート生成時に考慮して欲しい情報がある場合、補足プロンプトであるprompt.txt
に補足情報を記載します。
例えば今回以下のWeb3層構成図sample.png
をアップロードするとします。
その場合、構成図に記載されていない補足情報を以下のように記載します。
prompt.txt
- VPC及びサブネット含めて新規で作成してください
- EC2のAMI IDには`ami-039e8f15ccb15368a`を使用してください
- EC2のキーペアは使用せず、SSM Session Managerでアクセスできるようにしてください
- ALBのセキュリティグループは、HTTP及びHTTPSのみ受け付けるようにしてください
- EC2のセキュリティグループは、ALBのセキュリティグループからのHTTP及びHTTPSのみ許可するようにしてください
- RDSのセキュリティグループは、EC2のセキュリティグループからのMySQLのみ許可するようにしてください
補足情報の記載が完了したら、以下コマンドでSAMアプリをビルドします。
sam build
ビルド完了後に以下のコマンドを実行すると、S3バケット×2、Lambda関数、及び関連するリソースがデプロイされます。
sam deploy
なおBedrockのリージョン、モデルID、及び補足プロンプトファイルのパスは変更できるようにパラメータ化しています。
パラメータを上書きしたい場合は、以下のようにデプロイ時に--parameter-overrides
オプションを付与し、対象のパラメータに値を指定してください。
sam deploy --parameter-overrides \
BedrockRegion=us-west-2 \
BedrockModelId=anthropic.claude-3-sonnet-20240229-v1:0 \
PromptPath=prompt.txt
使い方
以下の通り、convert-diagram-to-cfn-input-diagram-bucket-<アカウントID>
バケットに対して構成図をアップロードしてください。
なお構成図の形式は現状png
しか対応していないため、jpeg
等の形式の場合は変換してからアップロードをお願いします。
アップロードするとS3イベント通知によりLambda関数が発火され、構成図及び元にClaudeにテンプレートを生成するようリクエストを投げます。
Claudeからレスポンスが返ってくると、Lambda関数がテンプレートの検証を実施し、問題がなければ以下のようにconvert-diagram-to-cfn-output-template-bucket-<アカウントID>
バケットに実行時刻のファイル名を持つテンプレートをアップロードします。
今回アップロードした構成図sample.png
から生成されたテンプレートの中身は以下のようになっていました。
テンプレート
20240312105138.yaml
# VPC設定
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
InstanceTenancy: default
Tags:
- Key: Name
Value: ap-northeast-1
PublicSubnetA1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: Public subnet A1
PublicSubnetC1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1c
CidrBlock: 10.0.2.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: Public subnet C1
PrivateSubnetA1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.3.0/24
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: Private subnet A1
PrivateSubnetC1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1c
CidrBlock: 10.0.4.0/24
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: Private subnet C1
InternetGateway:
Type: AWS::EC2::InternetGateway
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: Public Route Table
PublicRoute:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetA1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetA1
RouteTableId: !Ref PublicRouteTable
PublicSubnetC1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetC1
RouteTableId: !Ref PublicRouteTable
# セキュリティグループ設定
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP/HTTPS
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
VpcId: !Ref VPC
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP/HTTPS from ALB
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ALBSecurityGroup
- IpProtocol: tcp
FromPort: 443
ToPort: 443
SourceSecurityGroupId: !Ref ALBSecurityGroup
VpcId: !Ref VPC
RDSSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow MySQL from EC2
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref EC2SecurityGroup
VpcId: !Ref VPC
# ALB設定
ALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing
SecurityGroups:
- !Ref ALBSecurityGroup
Subnets:
- !Ref PublicSubnetA1
- !Ref PublicSubnetC1
ALBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref ALBTargetGroup
LoadBalancerArn: !Ref ALB
Port: 80
Protocol: HTTP
ALBTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckPath: /
Name: ALB-TargetGroup
Port: 80
Protocol: HTTP
TargetType: instance
VpcId: !Ref VPC
# EC2設定
EC2Instance1:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-039e8f15ccb15368a
InstanceType: t2.micro
SubnetId: !Ref PublicSubnetA1
SecurityGroupIds:
- !Ref EC2SecurityGroup
IamInstanceProfile: !Ref EC2InstanceProfile
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
yum install -y httpd
systemctl start httpd
systemctl enable httpd
EC2Instance2:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-039e8f15ccb15368a
InstanceType: t2.micro
SubnetId: !Ref PublicSubnetC1
SecurityGroupIds:
- !Ref EC2SecurityGroup
IamInstanceProfile: !Ref EC2InstanceProfile
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
yum install -y httpd
systemctl start httpd
systemctl enable httpd
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref EC2Role
EC2Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- "sts:AssumeRole"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
# RDS設定
RDS:
Type: AWS::RDS::DBInstance
Properties:
DBName: mydb
Engine: MySQL
MasterUsername: rootuser
MasterUserPassword: rootpassword
DBInstanceClass: db.t2.micro
AllocatedStorage: 20
PubliclyAccessible: false
VPCSecurityGroups:
- !Ref RDSSecurityGroup
DBSubnetGroupName: !Ref RDSSubnetGroup
RDSSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: RDS Subnet Group
SubnetIds:
- !Ref PrivateSubnetA1
- !Ref PrivateSubnetC1
# その他設定
Outputs:
VPCID:
Description: VPC ID
Value: !Ref VPC
Export:
Name: VPCID
PublicSubnetA1ID:
Description: Public Subnet A1 ID
Value: !Ref PublicSubnetA1
Export:
Name: PublicSubnetA1ID
PublicSubnetC1ID:
Description: Public Subnet C1 ID
Value: !Ref PublicSubnetC1
Export:
Name: PublicSubnetC1ID
PrivateSubnetA1ID:
Description: Private Subnet A1 ID
Value: !Ref PrivateSubnetA1
Export:
Name: PrivateSubnetA1ID
PrivateSubnetC1ID:
Description: Private Subnet C1 ID
Value: !Ref PrivateSubnetC1
Export:
Name: PrivateSubnetC1ID
ALBEndpoint:
Description: ALB Endpoint
Value: !GetAtt ALB.DNSName
Export:
Name: ALBEndpoint
なおテンプレートの検証でエラーが発生した場合は、以下の通りアップロードされるテンプレート名の末尾にerror
が付与されます。
この場合は、Lambda関数のCloudWatch Logsのロググループである/aws/lambda/convert-diagram-to-cfn-function
にて、検証エラー内容を確認します。
その上でテンプレートを修正するか、補足プロンプトを修正し再度デプロイした上で構成図をアップロードし直してください。
さらに生成されたテンプレートのオブジェクトURIを以下の通りCloudFormationのスタック作成時のAmazon S3 URL
に指定する事で、そのままスタックをデプロイする事が可能です。
今回出力されたテンプレートでは、以下のようなリソースが正常に作成されました!
なお、テンプレートの検証が正常に通った場合でも、デプロイに失敗する場合があります。
その場合もデプロイエラー内容を確認し、テンプレートを修正するか、補足プロンプトを修正し再度デプロイした上で構成図をアップロードし直してください。
最後に
今回は、S3にアップロードしたAWS構成図をCloudFormationテンプレートに変換し、別のS3にアップロードするシステムを作ってみました。
BedrockでClaude 3 Sonnetを利用できるようになった事で、外部のAPIを利用する事なく今回のようなAWSのみでマルチモーダルAIを利用したシステムを構築する事が可能になりました。
ただ生成されたテンプレートは正確性を欠いたり、必要なリソースが不足している場面が度々見られたため、もし本番利用したい場合はその辺りの欠点を補う手法を別途検討するべきかと思います。
とはいえ検証用途としては十分に利用できますので、気になる方は是非試してみてください!
以上、つくぼし(tsukuboshi0755)でした!