NATインスタンスをテンプレート化した

### テンプレート化した理由
AWSのテストをしたいときに、NATゲートウェイだとそこそこコストがかかるので、Natインスタンスを利用することがあります。NATインスタンスは使用するときだけ起動すればよいので、NATゲートウェイよりもコストを抑えられますが、まったく使用しない場合では、若干のEBSのコストが発生します。
そこで、NATインスタンスをCFnテンプレート化し、使用したいときだけ作成して課金できるようにしてみました。

### 参考にしたブログ
クラスメソッドさんの以下のブログを参考にさせていただきました。

https://dev.classmethod.jp/articles/how-to-create-amazon-linux-2023-nat-instance

https://dev.classmethod.jp/articles/create_nat_gateway/

### テンプレートの前提
EC2キーペア、NATインスタンス用のサブネット(パブリックとプライベート)、ルートテーブル（パブリックとプライベート）、インターネットゲートウェイ、セキュリティグループ、インスタンスプロファイルは作成済みとします。

### テンプレート
```yaml:sample.yaml
Parameters:
  EnableNatInstance:
    Description: Enable NAT Instance.
    Type: String
    Default: false
    AllowedValues: [true, false]

Conditions:
  EnableNatInstance:
    !Equals [true, !Ref EnableNatInstance]

Resources:
  NATInstance:
    Type: AWS::EC2::Instance
    Condition: EnableNatInstance
    Properties:
      KeyName: "EC2 キーペア名"
      ImageId: ami-0dfa284c9d7b2adad
      InstanceType: t3.nano
      IamInstanceProfile: "インスタンスプロファイル名"
      NetworkInterfaces: 
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          SubnetId: subnet-xxxxxxxxxxxxxx NATインスタンスを配置するパブリックサブネットのID
          GroupSet:
            - sg-xxxxxxxxxxxxxxxx NATインタンス用のセキュリティグループ
      SourceDestCheck: false
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: gp3
            VolumeSize: 8
            DeleteOnTermination: true
      Tags:
        - Key: Name
          Value: "NatInstance"
      UserData:
        Fn::Base64: |
          #!/bin/bash
          sudo sysctl -w net.ipv4.ip_forward=1 | sudo tee -a /etc/sysctl.conf
          sudo yum -y upgrade
          sudo yum install -y nftables
          # NAT追加設定
          sudo nft add table nat
          sudo nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
          sudo nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
          sudo nft add rule nat postrouting oifname "$(ip -o link show device-number-0 | awk -F': ' '{print $2}')" masquerade
          # NAT設定保存
          sudo nft list table nat | sudo tee /etc/nftables/al2023-nat.nft
          echo 'include "/etc/nftables/al2023-nat.nft"' | sudo tee -a /etc/sysconfig/nftables.conf
          # サービス起動＋自動起動設定
          sudo systemctl start nftables
          sudo systemctl enable nftables

  PrivateSubnetRoute:
    Type: AWS::EC2::Route
    Condition: EnableNatInstance
    Properties:
      RouteTableId: rtb-xxxxxxxxxxxxxxxxx プライベートサブネットのルートテーブルID
      DestinationCidrBlock: 0.0.0.0/0
      InstanceId: !Ref NATInstance
```

### 起動後
NATインスタンスにSSM Session Managerで接続して、nftablesが起動しているかを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636209/c06ed146-7d9f-b5da-1657-2357b8bafb97.png)

プライベートサブネットのルートテーブルも更新されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636209/d4d73169-3972-b367-9775-72f1a6f046be.png)


プライベートサブネットに作成したEC2からインターネットにアクセスできるかを確認します。

### NATインスタンスを削除するとき
CloudFormationのスタックアクション→既存スタックの変更セットを作成から、テンプレートの設定時に、パラメータをfalseにします。（次回作成する時はtrueにします）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636209/75e5a707-b260-bee5-472b-38bb601b40dd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636209/2758afc5-3861-e0c4-63c8-a7315141776b.png)

### 次回予定
EC2起動時に必要なパッケージをインストールして、初期設定できることがわかったため、次回はVPN用のソフトを組み込んだEC2インスタンスの起動テンプレートを作成してみようと思います。