Cloud9を動かせるVPCを作る

# はじめに

新しく作ったVPC上にCloud9を作ろうとしたらうまく動かなかったので、Cloud9が動くVPC環境を作る方法を簡単にまとめました。


# 概要

前提として、接続方法はAWS Systems Manager (SSM)になります。

- パブリックサブネットで動かす
    - サブネットのIPアドレス自動割り当てをONにする必要あり
- プライベートサブネットで動かす
    - パブリックサブネットも必要
    - NATゲートウェイが必要

# 参考

https://qiita.com/azureus/items/92f287c164990daefb5b

https://zenn.dev/part_of_mitsuo/articles/20220710-cloudformation03

# パブリックサブネットで動かす

## コンソールから作成
VPC作成の画面から、以下のように設定し作成します。たくさんリソースを作るとわかりずらくなるので、サブネットは1つにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/189576c8-1039-d111-41bb-72eb45d7a0b2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/acf716a0-eb3e-7794-d0fc-74e342f8231d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/e0babb05-a06b-4c10-d7e8-90228fccc098.png)

Resource mapは以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/be92df8c-5de7-0623-8255-7dd282dbdf10.png)

作成後、サブネットのIPアドレス自動割り当てをONにする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/46d7c890-75aa-aa6c-7e01-316cd102e33d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/5f61b611-5ec8-9529-3281-0e68b9da7737.png)

### 削除する
コンソールからVPCを削除するだけで、関連するリソースは全部削除されます。

## CloudFormationから作成
以下のコードになります。ほぼChatGPTが生成してくれました、便利。
<details><summary>クリックで表示</summary><div>

```yaml:create_vpc.yaml
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  VpcName:
    Type: String
    Default: forcloud9
    Description: Name of the VPC
  VpcCIDR:
    Type: String
    Default: 10.50.0.0/16
    Description: CIDR block for the VPC

Resources:
  VPC:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Ref VpcName

  InternetGateway:
    Type: 'AWS::EC2::InternetGateway'
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-igw

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

  PublicSubnet:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [ 0, !Cidr [ !Ref VpcCIDR, 24, 8 ] ]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-subnet-public1

  PublicRouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-rtb-public
  PublicRoute:
    Type: 'AWS::EC2::Route'
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref InternetGateway

  SubnetRouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable
```
</div></details>

### 削除する
スタックを削除すると、すべて削除されます。

# プライベートサブネットで動かす

公式に以下の記述ありますので、NATゲートウェイを作る必要があります。

https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/vpc-settings.html#vpc-settings-requirements

> プライベートサブネットを使用している場合は、パブリックサブネットで NAT ゲートウェイをホストして、サブネットのインスタンスによるインターネットとの通信を許可します。


## コンソールから作成
コンソールで、以下のように設定します。わかりやすくパブリック・プライベートサブネットは１つずつにします。
作成後は、サブネットのIPアドレス自動割り当てをONにする必要はないです。（パブリックサブネットで起動する場合は、自動割り当てをONにしてください。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/dea036c1-86e7-f350-0989-babf823cdbbf.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/374ea373-4010-b152-0ea0-5ce9f38c116b.png)

Resource mapは以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/e84a3ac0-99fc-f3e0-1ea6-969b45950308.png)

### 削除する
削除するときは、NATゲートウェイを先に削除する必要があります。
またVPCを削除しても、NATゲートウェイに割り付けられたEIPは削除されませんので、別途削除する必要があります。


## ClooudFormationから作成
以下のコードになります。パブリックサブネットのIPアドレス自動割り当てはOFFにしています。

<details><summary>クリックで表示</summary><div>

```yaml:create_vpc.yaml
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  VpcName:
    Type: String
    Default: for-private-bycfn
    Description: Name of the VPC
  VpcCIDR:
    Type: String
    Default: 10.50.0.0/16
    Description: CIDR block for the VPC

Resources:
  VPC:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Ref VpcName

  InternetGateway:
    Type: 'AWS::EC2::InternetGateway'
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-igw

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

  PublicSubnet:
    Type: 'AWS::EC2::Subnet'
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [ 0, !Cidr [ !Ref VpcCIDR, 24, 8 ] ]
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-subnet-public1

  PublicRouteTable:
    Type: 'AWS::EC2::RouteTable'
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-rtb-public
  PublicRoute:
    Type: 'AWS::EC2::Route'
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref InternetGateway

  SubnetRouteTableAssociation:
    Type: 'AWS::EC2::SubnetRouteTableAssociation'
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  ##################################################
  # Private Subnet
  ##################################################
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Select [ 1, !Cidr [ !Ref VpcCIDR, 24, 8 ] ]
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-subnet-private1

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-rtb-private

  PrivateRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway

  NatGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatGatewayEIP.AllocationId
      SubnetId: !Ref PublicSubnet
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-nat-public1
          
  NatGatewayEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub ${VpcName}-nat-eip

  PrivateSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref PrivateSubnet
```
</div></details>

### 削除する
スタックを削除すると、すべて削除されます。コンソールの場合とは異なり、NATゲートウェイやEIPも一緒に削除してくれます。

# おわりに
便利なCloud9なので、専用の環境ごとに作っておきたい時のテンプレートが欲しいと考え記事にしました。
自分用の備忘録ですが、どなたかのお役に立てれば幸いです。