AWS CloudFormationでNAT Gatewayを構築する

今回はCloudformationを利用したNAT Gatewayの作成のコード化について解説します。

#前提条件
- Windows10を使用。
- PCはDELLを使用。
- ファイルの拡張子は.ymlを使用。
- 東京リージョンを使用。
- アベイラビリティゾーンは1aと1cを使用。

#料金
テンプレート自体には料金は発生しないが、作成後のAWSリソースに関しては料金が発生しますのでご注意下さい。
NAT Gatewayは比較的高額なのでハンズオンのみの使用であれば即時に削除を推奨します。

#事前準備
 
- AWSアカウントを所持していること。
- Amazon VPCへのアクセス権限（書き込み・読み取り）を許可していること。
- AWS Cloudformationへのアクセス権限（書き込み・読み取り）を許可していること。
- VPCとプライベートサブネットが作成済みであること。

#構築内容
- 複数AZにNAT Gatewayを作成する。
- 任意のEIPを作成し、バブリックサブネット上に配置。
- プライベートサブネット用のルートテーブルにEIPを割り当てる。
- プライベートサブネット用のルートテーブルにNAT Gatewayをアタッチする。

#テンプレート

NAT Gatewayの作成のスタックは以下の通りです。

```yml:natgateway_create.yml
AWSTemplateFormatVersion: "2010-09-09"
Description:
  NAT Gateway Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix

      - Label: 
          default: "NATGateway Configuration"
        Parameters: 
          - NATGatewayACreate
          - NATGatewayCCreate

    ParameterLabels: 
      NATGatewayACreate: 
        default: "NATGatewayACreate"
      NATGatewayCCreate: 
        default: "NATGatewayCCreate"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  NATGatewayACreate: 
    Default: true
    Type: String
    AllowedValues: 
      - true
      - false

  NATGatewayCCreate:
    Default: true
    Type: String
    AllowedValues:
      - true
      - false

# ------------------------------------------------------------#
# Conditions
# ------------------------------------------------------------# 
Conditions: 
  IsCreateNATGatewayA: !Equals [ !Ref NATGatewayACreate, true ]
  IsCreateNATGatewayAfalse: !Equals [ !Ref NATGatewayACreate, false ]

  IsCreateNATGatewayC: !Equals [ !Ref NATGatewayCCreate, true ]
  IsCreateNATGatewayCfalse: !Equals [ !Ref NATGatewayCCreate, false ]

# ------------------------------------------------------------#
#  NAT Gateway AZ:A
# ------------------------------------------------------------#
Resources:
# NATGatewayA Create
  NATGatewayA: 
    Type: "AWS::EC2::NatGateway"
    Condition: IsCreateNATGatewayA
    Properties: 
      AllocationId: !GetAtt NATGatewayAEIP.AllocationId 
      SubnetId: { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-natgw-a"

# NATGateway For EIP Create
  NATGatewayAEIP: 
    Type: "AWS::EC2::EIP"
    Condition: IsCreateNATGatewayA
    Properties: 
      Domain: vpc

# PrivateRouteA Update
  PrivateRouteA: 
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayA
    Properties: 
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-a" }
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayA

# PrivateRouteC Update (NATGatewayC NO Create)
  PrivateRouteC2: 
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayCfalse
    Properties: 
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-c" }
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayA

# ------------------------------------------------------------#
#  NAT Gateway AZ:C
# ------------------------------------------------------------#
# NATGatewayC Create
  NATGatewayC:
    Type: "AWS::EC2::NatGateway"
    Condition: IsCreateNATGatewayC
    Properties:
      AllocationId: !GetAtt NATGatewayCEIP.AllocationId 
      SubnetId: { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-natgw-c"

# NATGateway For EIP Create
  NATGatewayCEIP:
    Type: "AWS::EC2::EIP"
    Condition: IsCreateNATGatewayC
    Properties:
      Domain: vpc

# PrivateRouteC Update
  PrivateRouteC:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayC
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-c" }
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayC

# PrivateRouteA Update (NATGatewayA NO Create)
  PrivateRouteA2: 
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayAfalse
    Properties: 
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-a" }
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayC

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#                
Outputs:
# NATGateway EIP
  NATGatewayAEIP:
    Condition: IsCreateNATGatewayA
    Value: !Ref NATGatewayAEIP
    Export:
      Name: !Sub "${PJPrefix}-natgw-a-eip"

  NATGatewayCEIP:
    Condition: IsCreateNATGatewayC
    Value: !Ref NATGatewayCEIP
    Export:
      Name: !Sub "${PJPrefix}-natgw-c-eip"

```

#スタック作成後の確認手順
１、任意のEIPが生成されていることを確認する。
![eip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/ad3b5057-83bd-a66b-2377-aa1cb7548b1c.png)

２、NAT Gatewayが作成されておりEIPが割り当てられていて、且つパブリックサブネットに設置されていることを確認する。
![natgateway.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/f5d427fc-0e12-994e-8cde-96797f690c05.png)

３、プライベートサブネットのルートテーブルにNAT Gatewayがアタッチされていることを確認する。
![ルートテーブル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/2aa14ea7-a6b1-7a53-cf90-90df05954f3e.png)

#終わりに
今回はCloudFormaitonを使ってNAT Gatewayをコード化して構築してみました。
前回のVPCのコード化でテンプレートの書き方について少し慣れてきたので、成長していると実感しております。
他のAWSリソースでコード化が実現出来たら随時Qiitaに投稿します♪