AWS-CloudFormation

今話題の「ChatGPT」さんにCloudFormationテンプレートを作ってもらう

ご挨拶

お疲れ様です、寺井です。

「ChatGPT」盛り上がってますね~~
SNSなどで話題になっているので、私も存在は知っていたのですが、触ったことは無い状態でした。

今回はChatGPT先生がどれほどの方なのか、CloudFormationのテンプレートを作ってもらうことで試してみたいと思います。

ChatGPTってなに?

Wikiでは以下のように記載されています。

ChatGPT(チャットジーピーティー、Generative Pre-trained Transformer)[1]は、OpenAIが2022年11月に公開した人工知能チャットボット。OpenAIのGPT-3ファミリーの言語モデルを基に構築されており、教師あり学習と強化学習の両方の手法で転移学習されている。
参考:ウィキペディア(ChatGPT)

なるほど、分からん。
とにかくすごそうなので「百聞は一見にしかず」ということで、使ってみましょう。

必要なもの

ChatGPTアカウント

「ChatGPT」を使用するにはアカウント登録が必要です。
アカウントがまだ無いという方は以下のページよりアカウント登録を行ってください。
ChatGPT登録ページ

AWSアカウント

今回はCloudFormationテンプレートを流してリソースを作ろうと思いますので、CloudFormationが使用できる環境を用意します。

CloudFormationでスタックを作成するので、CloudFormationが使用できるIAMロールも作成しておきます。

やってみる

ChatGPT生成

チャット欄に

EC2を使用して、パブリックに公開されたWEBサーバーを作成するCloudFormationテンプレートを作ってほしい

と入力しました。

こんな雑な聞き方で大丈夫なんでしょうか。やってみます。

おおおおお~~~!どんどん書かれていってます!!
生成には少し時間がかかりますので、ちょっと待ちます。

完成したようです!
ChatGPTさんは文字数制限からなのか固まってしまってますが、テンプレートは出来てるっぽいので良しとしましょう。

生成されたテンプレートの内容はこちら

---
AWSTemplateFormatVersion: "2010-09-09"
Description: Create a public web server using EC2
Parameters:
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues: [t2.micro, t2.small, t2.medium]
    Description: EC2 instance type
  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instances
  AMI:
    Type: AWS::EC2::Image::Id
    Description: AMI ID for the Amazon Linux 2 image
    Default: ami-0a887e401f7654935 # Amazon Linux 2 AMI
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref InstanceType
      ImageId: !Ref AMI
      KeyName: !Ref KeyName
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          yum update -y
          yum install httpd -y
          systemctl start httpd
          systemctl enable httpd
          echo "<html><body><h1>Hello from your new web server!</h1></body></html>" > /var/www/html/index.html
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP and HTTPS access
      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
Outputs:
  WebsiteURL:
    Description: URL for the website
    Value: !Sub "http://${EC2Instance.PublicDnsName}/"

コードの内容をコピーして.yamlファイルとして保存しておきます。

テンプレートの内容

  • OSはAmazon Linux 2
  • 「Parameters」セクションで[インスタンスタイプ]・[AMI]・[キーペア]を受け取る
  • 「ユーザーデータ」でApacheをインストールして[/var/www/html/index.html]にページ作成
  • [80]と[443]のポートでインバウンド許可する「セキュリティグループ」を設定
  • 「Outputs」で対象のWEBサーバーにアクセスするURLを出力

という内容のようです。

ではこのCloudFormationテンプレートを実際に流してみたいと思います。

スタックの作成

CloudFormation>スタック>スタックの作成

  • テンプレートの準備 :テンプレートの準備完了
  • テンプレートソース :テンプレートファイルのアップロード
  • テンプレートファイルのアップロード :「ファイルを選択」から先程保存したテンプレートファイルを選択

スタックの名前をつけて、お好きなインスタンスタイプ・キーペアを選択

  • タグ     :任意
  • アクセス許可 :前準備で作成したCFn用のIAMロールを選択
  • スタックの失敗オプション:すべてのスタックリソースをロールバックする

「詳細オプション」は必要であれば設定してください。

最終画面で問題なければ「送信」から作成を実行します。

スタックの作成エラー

スタックがロールバックしたので内容を確認したところ、指定したAMIが存在しなかったようです。

Parameter validation failed: parameter value ami-0a887e401f7654935 for parameter name AMI does not exist. Rollback requested by user.

リージョンを変更してスタックの作成

調べてみるとChatGPTさんが使用したAMIは「米国東部 (バージニア北部)us-east-1」のものでした。

「us-east-1」でスタックを作成すると、無事作成完了しました!

「出力」タブにWEBサーバーにアクセスするURLが表示されているのでアクセスしてみます。

ブラウザでもWEBサーバーが起動されていることを確認できました。

え、すごくないですか??

ChatGPT生成(2回目)

次はちょっと難しめに、いくつか要件をあげてみます。

以下の要件を踏まえてCloudFormationのテンプレートを作成してほしい
・東京リージョンで起動
・LAMP環境
・EC2に「phpMyAdmin」を使用してRDSのデータベースを表示できるページを用意

さっきの反省も活かしてリージョンも東京で指定します。

生成が止まってしまいました。
文字数制限がある(?)とのことなので、分割してでもいいからどんどん続けてもらいます。

最終的に完成したテンプレートはこちらです。
(※かなり長いのでご注意)

クリックで開く

---
Parameters:
KeyName:
Description: EC2インスタンスのキーペア
Type: AWS::EC2::KeyPair::KeyName
InstanceType:
Description: EC2インスタンスのインスタンスタイプ
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t2.small
- t2.medium
DBName:
Description: データベース名
Type: String
DBUser:
Description: データベースのユーザ名
Type: String
DBPassword:
Description: データベースのパスワード
Type: String
NoEcho: true

Resources:
# VPC作成
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-VPC

# サブネット作成
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.1.0/24
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-PublicSubnet1

# インターネットゲートウェイ作成
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-InternetGateway

# VPCとインターネットゲートウェイを紐付け
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC

# ルートテーブル作成
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-PublicRouteTable

# サブネットとルートテーブルを紐付け
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable

# インターネットに接続するためのルートを作成
PublicRoute:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteTableId: !Ref PublicRouteTable

# セキュリティグループ作成
WebSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP and SSH traffic
SecurityGroupIngress:
# HTTPのインバウンドアクセスを許可
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
# SSHのインバウンドアクセスを許可
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
VpcId: !Ref VPC
GroupName: !Sub ${AWS::StackName}-WebSecurityGroup
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-WebSecurityGroup

# EC2インスタンス作成
WebInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0c55b159cbfafe1f0 # Amazon Linux 2 LTS
InstanceType: !Ref InstanceType
KeyName: !Ref KeyName
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- !Ref WebSecurityGroup
SubnetId: !Ref PublicSubnet1
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd24 php72 php72-mysqlnd
chkconfig httpd on
service httpd start
cd /var/www/html
echo "" > index.php
# phpMyAdminのインストール
cd /tmp
wget https://files.phpmyadmin.net/phpMyAdmin/5.1.0/phpMyAdmin-5.1.0-all-languages.tar.gz
tar xzf phpMyAdmin-5.1.0-all-languages.tar.gz
mv phpMyAdmin-5.1.0-all-languages /var/www/html/phpmyadmin
rm phpMyAdmin-5.1.0-all-languages.tar.gz
# config.inc.phpの作成
cd /var/www/html/phpmyadmin
cp config.sample.inc.php config.inc.php
sed -i "s/\$cfg\['Servers'\]\[\$i\]\['host'\] = 'localhost';/\$cfg['Servers'][\$i]['host'] = '${DBEndpoint}';/" config.inc.php
sed -i "s/\$cfg\['Servers'\]\[\$i\]\['user'\] = 'root';/\$cfg['Servers'][\$i]['user'] = '${DBUser}';/" config.inc.php
sed -i "s/\$cfg\['Servers'\]\[\$i\]\['password'\] = '';/\$cfg['Servers'][\$i]['password'] = '${DBPassword}';/" config.inc.php
sed -i "s/\$cfg\['Servers'\]\[\$i\]\['AllowNoPassword'\] = false;/\$cfg['Servers'][\$i]['AllowNoPassword'] = true;/" config.inc.php
# RDS作成
RDS:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceClass: !Ref DBInstanceClass
Engine: mysql
MasterUsername: !Ref DBUser
MasterUserPassword: !Ref DBPassword
AllocatedStorage: !Ref DBAllocatedStorage
DBInstanceIdentifier: !Sub ${AWS::StackName}-rds
MultiAZ: false
StorageType: gp2
VPCSecurityGroups:
- !Ref DBSecurityGroup
DBSubnetGroupName: !Ref DBSubnetGroup
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-RDS

# RDSセキュリティグループ作成
DBSecurityGroup:
Type: AWS::RDS::DBSecurityGroup
Properties:
GroupDescription: Allow MySQL traffic
DBSecurityGroupIngress:
- EC2SecurityGroupName: !Ref WebSecurityGroup
EC2SecurityGroupOwnerId: !Ref AWS::AccountId
# WebサーバーからMySQLへのアクセスを許可
# Webサーバーのセキュリティグループを参照する
# ※EC2SecurityGroupOwnerIdには自身のアカウントIDを指定
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-DBSecurityGroup

# RDSサブネットグループ作成
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for RDS
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-DBSubnetGroup

とりあえずCloudFormationで流してみます。

スタックの作成

先ほどと同じ手順でスタックの作成を行います。

スタックの作成エラー

以下のようなエラーが。

Template format error: Unresolved resource dependencies [DBAllocatedStorage, DBInstanceClass] in the Resources block of the template

テンプレート内でリソースの依存関係が上手くいっていないようです。

結果

ChatGPT先生に色々問い詰めてみましたが、こちらの聞き方が悪いのか、ベストな解決策を教えてくれることはありませんでした

完璧ではなかったものの、テンプレートの大部分を作成してくれたので、これだけでも作業時間がグッと減らせるのでは?と思います。

ChatGPT「Too many requests」エラー

また、試行錯誤してリクエストしまくってたら、以下のようなエラーが出てしばらく使えなくなりました。
「Too many requests in 1 hour. Try again later.」

あまりにも短期間にリクエストし過ぎるとこのようになるので、ご利用は計画的に。

感想

「ChatGPT」に全く同じ質問を投げかけても、返ってくる回答はその都度異なることが多いです。
AIが返しやすいような聞き方をするとか、これからAIと上手く付き合っていくために、使い手のスキルアップが必要だと感じました。

上手く使うことができれば、単純な作業はほぼこれで解決できるようになるんでしょうか…。
もっと鍛錬を積んで、AIと仲良くなれるように精進します。

ここまでお付き合いいただきありがとうございました。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA