[アップデート] Amazon Q Developer IDE のコンテキスト機能がイメージをサポートしたので AWS アーキテクチャ構成図から CloudFormation テンプレートを作成させてみた
いわさです。
少し前ですが Amazon Q Developer IDE がアップデートされコンテキスト機能がイメージファイルをサポートしました。v1.83.0 以降で使うことができます。
この機能を使うことで、画像を含めた指示が出来るようになるので、例えば UI のイメージやシーケンス図などからコードを生成したり、構成図などからインフラテンプレートなどを作成することが出来るようになります。
あるいは私は AWS のアーキテクチャ構成図ベースでのレビューなどを行うことも多いので、構成図を与えて Q Developer を活用したレビューなども出来そうです。とても良さそうです。
使い方
使い方は非常に簡単で、今回のアップデートでコンテキスト機能に「Image」が追加されています。
こちらを選択すると次のようにファイル選択ダイアログが表示されるのでローカル上の画像ファイルを指定します。
そうするとコンテキストとして認識されるようになります。
もちろん少し前にアップデートされたコンテキストのピン留めにも対応しています。[1]
AWS アーキテクチャ構成図から CloudFormation テンプレートを作成してみた
今回は AWS の builders.flash の記事の中にある適当な AWS アーキテクチャ構成図から CloudFormation テンプレートを作成させてみました。
先ほどの流れで以下の画像をコンテキストとして追加します。
AWS のアーキテクチャ図を描きたい ! でもどうすれば良いの ? - 変化を求めるデベロッパーを応援するウェブマガジン | AWSより
そして、CloudFormation テンプレートを作成するよう指示します。
すると、構成図を読み込んでそれを基にテンプレートを作成してくれそうですね。
VPC、EC2、RDS、ALB、S3 については含んでくれていそうです。ただ、Route53 や CloudFront が含まれていないですね。おやおや。
と思ったら、テンプレートの初版作成後に勝手にブラッシュアップしはじめまして、Route 53、CloudFront を追加し、更に VPN Gateway まで追加しようとしてくれています。ちゃんと細かいところまで見てますね。
それっぽいテンプレートをさっと作成して終わるのではなく、その後も作っては検証を行って細かい調整を繰り返してくれます。
最終的に出来上がったテンプレートは以下です。私が確認した限りではかなり高品質なテンプレートが出来上がっていると思いました。これが特に設定なしですぐに使えるのはすごい。
作成された CloudFormation テンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Enterprise web application infrastructure with Route 53, CloudFront, VPC, EC2, RDS, Elastic Load Balancing, S3, and VPN Gateway'
Parameters:
KeyPairName:
Type: AWS::EC2::KeyPair::KeyName
Description: EC2 Key Pair for SSH access
DBPassword:
Type: String
NoEcho: true
MinLength: 8
Description: RDS database password
DomainName:
Type: String
Description: Domain name for the application
Default: example.com
CustomerGatewayIP:
Type: String
Description: Public IP address of the customer gateway
AllowedPattern: '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
Resources:
# VPC
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: MainVPC
# Internet Gateway
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: MainIGW
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# Public Subnets
PublicSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet-A
PublicSubnetB:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: !Select [1, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet-B
# Private Subnets
PrivateSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: PrivateSubnet-A
PrivateSubnetB:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.4.0/24
AvailabilityZone: !Select [1, !GetAZs '']
Tags:
- Key: Name
Value: PrivateSubnet-B
# Route Tables
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PublicRouteTable
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetA
RouteTableId: !Ref PublicRouteTable
PublicSubnetBRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetB
RouteTableId: !Ref PublicRouteTable
# Security Groups
ELBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Elastic Load Balancer
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Description: HTTP access from internet
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Description: HTTPS access from internet
Tags:
- Key: Name
Value: ELB-SecurityGroup
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Amazon EC2 instances
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ELBSecurityGroup
Description: HTTP access from ELB
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 10.0.0.0/16
Description: SSH access from VPC
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 192.168.0.0/16
Description: SSH access from corporate network
Tags:
- Key: Name
Value: EC2-SecurityGroup
RDSSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Amazon RDS database
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref EC2SecurityGroup
Description: MySQL access from EC2 instances
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: 192.168.0.0/16
Description: MySQL access from corporate network
Tags:
- Key: Name
Value: RDS-SecurityGroup
# Elastic Load Balancing
ElasticLoadBalancer:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
LoadBalancerName: WebApp-ELB
Scheme: internet-facing
Subnets:
- !Ref PublicSubnetA
- !Ref PublicSubnetB
SecurityGroups:
- !Ref ELBSecurityGroup
Listeners:
- LoadBalancerPort: 80
InstancePort: 80
Protocol: HTTP
HealthCheck:
Target: HTTP:80/
HealthyThreshold: 3
UnhealthyThreshold: 5
Interval: 30
Timeout: 5
Instances:
- !Ref EC2InstanceA
- !Ref EC2InstanceB
Tags:
- Key: Name
Value: Elastic-Load-Balancing
# EC2 Instances
EC2InstanceA:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0d52744d6551d851e # Amazon Linux 2023 (Tokyo region)
InstanceType: t3.micro
KeyName: !Ref KeyPairName
SubnetId: !Ref PrivateSubnetA
SecurityGroupIds:
- !Ref EC2SecurityGroup
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Web Server A - Tokyo Region</h1>" > /var/www/html/index.html
Tags:
- Key: Name
Value: WebServer-A
EC2InstanceB:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0d52744d6551d851e # Amazon Linux 2023 (Tokyo region)
InstanceType: t3.micro
KeyName: !Ref KeyPairName
SubnetId: !Ref PrivateSubnetB
SecurityGroupIds:
- !Ref EC2SecurityGroup
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Web Server B - Tokyo Region</h1>" > /var/www/html/index.html
Tags:
- Key: Name
Value: WebServer-B
# RDS Subnet Group
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for RDS database
SubnetIds:
- !Ref PrivateSubnetA
- !Ref PrivateSubnetB
Tags:
- Key: Name
Value: DBSubnetGroup
# RDS Primary Database (Availability Zone A)
RDSPrimaryDatabase:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: webapp-db-primary
DBInstanceClass: db.t3.micro
Engine: mysql
EngineVersion: '8.0'
AllocatedStorage: 20
MasterUsername: admin
MasterUserPassword: !Ref DBPassword
VPCSecurityGroups:
- !Ref RDSSecurityGroup
DBSubnetGroupName: !Ref DBSubnetGroup
BackupRetentionPeriod: 7
MultiAZ: false
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: WebAppDatabase-Primary
- Key: Location
Value: Availability-Zone-A
# RDS Read Replica (Secondary) - Availability Zone B
RDSSecondaryDatabase:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: webapp-db-secondary
SourceDBInstanceIdentifier: !Ref RDSPrimaryDatabase
DBInstanceClass: db.t3.micro
AvailabilityZone: !Select [1, !GetAZs '']
VPCSecurityGroups:
- !Ref RDSSecurityGroup
Tags:
- Key: Name
Value: WebAppDatabase-Secondary
- Key: Location
Value: Availability-Zone-B
# S3 Bucket
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub 'webapp-bucket-${AWS::AccountId}-${AWS::Region}'
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: false
IgnorePublicAcls: false
RestrictPublicBuckets: false
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: error.html
# S3 Bucket Policy for CloudFront
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref S3Bucket
PolicyDocument:
Statement:
- Sid: AllowCloudFrontAccess
Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}'
Action: 's3:GetObject'
Resource: !Sub '${S3Bucket}/*'
# CloudFront Origin Access Identity
CloudFrontOriginAccessIdentity:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: !Sub 'OAI for ${AWS::StackName}'
# CloudFront Distribution
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- Id: S3Origin
DomainName: !GetAtt S3Bucket.RegionalDomainName
S3OriginConfig:
OriginAccessIdentity: !Sub 'origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}'
- Id: ELBOrigin
DomainName: !GetAtt ElasticLoadBalancer.DNSName
CustomOriginConfig:
HTTPPort: 80
OriginProtocolPolicy: http-only
DefaultCacheBehavior:
TargetOriginId: ELBOrigin
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
- OPTIONS
- PUT
- POST
- PATCH
- DELETE
CachedMethods:
- GET
- HEAD
ForwardedValues:
QueryString: true
Cookies:
Forward: none
CacheBehaviors:
- PathPattern: '/static/*'
TargetOriginId: S3Origin
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
ForwardedValues:
QueryString: false
Cookies:
Forward: none
Enabled: true
Comment: !Sub 'CloudFront distribution for ${AWS::StackName} - Global CDN'
DefaultRootObject: index.html
PriceClass: PriceClass_100
ViewerCertificate:
CloudFrontDefaultCertificate: true
# Route 53 Hosted Zone
Route53HostedZone:
Type: AWS::Route53::HostedZone
Properties:
Name: !Ref DomainName
HostedZoneConfig:
Comment: !Sub 'Hosted zone for ${DomainName}'
# Route 53 Record for CloudFront
Route53Record:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref Route53HostedZone
Name: !Ref DomainName
Type: A
AliasTarget:
DNSName: !GetAtt CloudFrontDistribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2 # CloudFront hosted zone ID
# Customer Gateway
CustomerGateway:
Type: AWS::EC2::CustomerGateway
Properties:
Type: ipsec.1
BgpAsn: 65000
IpAddress: !Ref CustomerGatewayIP
Tags:
- Key: Name
Value: Corporate-Data-Center-Gateway
# VPN Gateway
VPNGateway:
Type: AWS::EC2::VpnGateway
Properties:
Type: ipsec.1
Tags:
- Key: Name
Value: VPN-Gateway
# VPN Gateway Attachment
VPNGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
VpnGatewayId: !Ref VPNGateway
# VPN Connection
VPNConnection:
Type: AWS::EC2::VpnConnection
Properties:
Type: ipsec.1
StaticRoutesOnly: true
CustomerGatewayId: !Ref CustomerGateway
VpnGatewayId: !Ref VPNGateway
Tags:
- Key: Name
Value: Corporate-VPN-Connection
# VPN Connection Route
VPNConnectionRoute:
Type: AWS::EC2::VpnConnectionRoute
Properties:
VpnConnectionId: !Ref VPNConnection
DestinationCidrBlock: 192.168.0.0/16 # Corporate network CIDR
# Private Route Table for VPN
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PrivateRouteTable
# Route to VPN Gateway
VPNRoute:
Type: AWS::EC2::Route
DependsOn: VPNGatewayAttachment
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 192.168.0.0/16
VpnGatewayId: !Ref VPNGateway
# Associate Private Subnets with Private Route Table
PrivateSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetA
RouteTableId: !Ref PrivateRouteTable
PrivateSubnetBRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetB
RouteTableId: !Ref PrivateRouteTable
Outputs:
VPCId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub '${AWS::StackName}-VPC-ID'
LoadBalancerDNS:
Description: Elastic Load Balancer DNS name
Value: !GetAtt ElasticLoadBalancer.DNSName
CloudFrontDomainName:
Description: CloudFront Distribution Domain Name
Value: !GetAtt CloudFrontDistribution.DomainName
Route53HostedZoneId:
Description: Route 53 Hosted Zone ID
Value: !Ref Route53HostedZone
S3BucketName:
Description: S3 Bucket Name
Value: !Ref S3Bucket
PrimaryDatabaseEndpoint:
Description: RDS Primary Database Endpoint
Value: !GetAtt RDSPrimaryDatabase.Endpoint.Address
SecondaryDatabaseEndpoint:
Description: RDS Secondary Database Endpoint
Value: !GetAtt RDSSecondaryDatabase.Endpoint.Address
VPNGatewayId:
Description: VPN Gateway ID
Value: !Ref VPNGateway
CustomerGatewayId:
Description: Customer Gateway ID
Value: !Ref CustomerGateway
先日のアップデートであるルールファイルをうまく使うことで、さらに意図通りのテンプレートが作れそうですね。すごいです。
さいごに
本日は Amazon Q Developer IDE のコンテキスト機能がイメージをサポートしたので AWS アーキテクチャ構成図から CloudFormation テンプレートを作成させてみました。
Amazon Q Developer 以外でたまにこういった画像から何か指示を行うことはありましたが、Amazon Q Developer で使いやすくなったのは嬉しいです。
ファイルタイプとしては JPEG、PNG、GIF、WebP がサポートされており、最大サイズは 3.75 MB まで、サイズは 8,000 x 8,000 ピクセル以下であること、ひとつのメッセージに最大 20 枚までという制限や上限が一応ありますのでそのあたりも気にしながら使ってみてください。詳細は以下に記載されていました。