ChatGPTと一緒にサーバーを立ててみる

最近なにかと話題のChatGPTですが、どうやらコードも生成できるみたいです。 今回はChatGPTと一緒にEC2インスタンスを立ち上げて見ようと思います。どのくらい正確な対応をしてくれるのか気になったので試してみました。
2022.12.13

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ChatGPTとは

ChatGPTは対話に最適化されてた深層学習のモデルの一つです。 OpenAIによってChatGPTとWebページ上でやり取りを行うことができます。

ChatGPTの詳細については以下の記事が参考になると思います。

対話の内容は汎用的で、一般的な会話からコードの生成までできたりします。 今回はChatGPTと一緒にEC2の構築を行おうと思いますが、一応以下のような普通の会話もできます。

今回構築したいもの

ChatGPTは一度にあまり長いコードは生成できないみたいなので、シンプルなアーキテクチャを構築します。

VPC内にEC2が1台あってそこにNginxがインストールされているというものです。 構成図でいうと以下のような感じです。

一緒に構築すると言ってもChatGPTがAWS環境を直接触れるわけではないので、今回はCloudFormationのコードを生成してもらいます。 自分は生成されたコードをレビューしながらデプロイしていきます。

ChatGPTにお願いしてみる。

VPC作成

まずはジャブがてらVPCを作成するテンプレートを生成してもらいましょう。

指定したCIDRはなどのパラメータはしっかりと反映されています。 ですが、インターネットへの経路が設定されていません。 再度お願いしてみます。

いい感じです。 ルートテーブルも明示的に設定してもらいます。

悪くないんじゃないでしょうか? Exportしてる部分が気になりますが、しっかりと変数名にスタック名でプレフィックスを入れてくれているので問題なさそうです。 リソース名などもいいと思います。

一度、この状態でデプロイしてみます。

問題なくデプロイできました。

EC2を追加してもらう

EC2を追加してNginxもインストールしてもらいます。

いい感じです。 コードが長くなったので生成してもらったものは付録に書いておきます。 追加された部分は以下のコードです。

EC2の部分

 EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-09d95fab7fff3776c
      InstanceType: t2.micro
      KeyName: sample-key
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      SubnetId: !Ref PublicSubnet
      UserData:
        "Fn::Base64": !Sub |
          #!/bin/bash
          yum update -y
          yum install -y nginx
          systemctl start nginx
          systemctl enable nginx

  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for EC2 instance
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0

セキュリティグループまでしっかり作成してくれています。 流石ですね。

AMIの正体

まず気になるのはAMIです。 せっかくなので、ChatGPTにAMIの詳細をCLIから取得する方法を聞いてみます。

それっぽいコマンドを出力してくれました。 CLIのリファレンスを確認してみると適切なコマンドです。

こちらのAMIですが、us-east-1のリージョンに存在しました。 Amazon Linux 2 AMI 2.0.20200520.1 x86_64 HVM gp2と割と妥当なイメージだったようです。 ただ、学習したデータセットの影響か作成日が2020/5/27と古めだったので、そのまま使うのはやはり注意が必要です。

実行してみましたが、該当のイメージはないとのことです。

AMIの詳細

$ aws ec2 describe-images --image-ids ami-09d95fab7fff3776c

An error occurred (InvalidAMIID.NotFound) when calling the DescribeImages operation: The image id '[ami-09d95fab7fff3776c]' does not exist

AMIの部分は適当なAL2の最新のAMIにこちらで変更します。

ユーザーデータの中身

AmazonLinux2だとNginxはamazon-linux-extrasを使用してインストールすることが多いかなと思います。 このままのコードだとamazon-linux-extrasを使用するように警告が出てNginxのインストールが失敗します。

ChatGPTにamazon-linux-extrasを使用してインストールするように変更してもらいます。

コード全体の変更は出力されてませんでしたが、ユーザーデータは出力されました。 これなら問題なさそうです。

デプロイしてみる

実際にこのテンプレートをデプロイしてみます。 詳細なコードについては付録に書いておきます。

シンタックスエラー等の問題もなく一発でデプロイできました。

HTTPで疎通確認してみる

ブラウザから該当のEC2にアクセスしてみます。

問題なくNginxのページが表示されました。

感想

ChatGPTすごいですね。一応汎用的な対話モデルとして作られているのにここまでコードの出力が自然にできるとは思っていませんでした。 特に前の会話を覚えていて、それを踏まえて修正してくれるところがすごいですね。

ただ、ChatGPTが生成したコードを何も考えずにそのまま使うのは危ないと思います。ChatGPTが必ずしも設計上のベストプラクティス、セキュリティやライセンスを考慮してくれるわけではないので) AWSの知識を持った上で生成されたコードをレビューしながら作業していく必要があると感じました。

ただ、対話的にコードを生成してくれるので誰かにお願いしながら一緒に作業をしている感覚はありました。 カスタマイズ性が高くインタラクティブなコードスニペットみたいな感じで向き合っていくと良いと思いました。

付録

ChatGPTが生成したテンプレート

ChatGPT.yaml

AWSTemplateFormatVersion: '2010-09-09'

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true

  InternetGateway:
    Type: AWS::EC2::InternetGateway

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

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      MapPublicIpOnLaunch: true

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

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref RouteTable
      SubnetId: !Ref PublicSubnet

  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-09d95fab7fff3776c
      InstanceType: t2.micro
      KeyName: sample-key
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      SubnetId: !Ref PublicSubnet
      UserData:
        "Fn::Base64": !Sub |
          #!/bin/bash
          yum update -y
          yum install -y nginx
          systemctl start nginx
          systemctl enable nginx

  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for EC2 instance
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0

Outputs:
  VPCID:
    Description: VPC ID
    Value: !Ref VPC
    Export:
      Name: !Sub '${AWS::StackName}-VPCID'
  PublicSubnetID:
    Description: Public Subnet ID
    Value: !Ref PublicSubnet
    Export:
      Name: !Sub '${AWS::StackName}-PublicSubnetID'
  EC2InstanceID:
    Description: EC2 instance ID
    Value: !Ref EC2Instance
    Export:
      Name: !Sub '${AWS::StackName}-EC2InstanceID'

修正したもの

修正後

AWSTemplateFormatVersion: '2010-09-09'

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true

  InternetGateway:
    Type: AWS::EC2::InternetGateway

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

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      MapPublicIpOnLaunch: true

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

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref RouteTable
      SubnetId: !Ref PublicSubnet

  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-072bfb8ae2c884cc4
      InstanceType: t2.micro
      KeyName: sample
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      SubnetId: !Ref PublicSubnet
      UserData:
        "Fn::Base64": !Sub |
          #!/bin/bash
          yum update -y
          amazon-linux-extras install -y nginx1
          systemctl start nginx
          systemctl enable nginx

  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for EC2 instance
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0

Outputs:
  VPCID:
    Description: VPC ID
    Value: !Ref VPC
    Export:
      Name: !Sub '${AWS::StackName}-VPCID'
  PublicSubnetID:
    Description: Public Subnet ID
    Value: !Ref PublicSubnet
    Export:
      Name: !Sub '${AWS::StackName}-PublicSubnetID'
  EC2InstanceID:
    Description: EC2 instance ID
    Value: !Ref EC2Instance
    Export:
      Name: !Sub '${AWS::StackName}-EC2InstanceID'