CloudFormationを使ってNAT Gatewayを構築する

#はじめに
本記事では、AWS CloudFormation管理コンソールを使って、NAT Gatewayを構築する手順を説明しています。（初学者向け）

本記事で掲載しているテンプレートの最新版は、下記に置いてます。
https://github.com/okubo-t/aws-cloudformation
#構成図
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283246/cb1eb25f-cc38-f735-0a71-db5fbdd555b3.png" width=70%>

#構築するコンポーネント
[NATゲートウェイ]
(https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-nat-gateway.html)
[EIP(Elastic IP アドレス)](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html)
[ルーティングテーブルの更新](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-nat-gateway.html#nat-gateway-create-route)

#前提条件
下記の記事の構築手順で、VPCを構築していること。
[CloudFormationを使ってVPCを構築する](https://qiita.com/okubot55/items/b18a5dd5166f1ec2696c)

PJPrefixの値は、同一にすること。
#構築手順
１ AWS CloudFormation管理コンソールから、スタックの作成をクリックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/e0c3e7c3-f478-18c7-2dc2-7e669d1b399d.png"　 width=50%>

２ 後述のテンプレートを選択します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/060a4709-622a-2394-de5f-ac2103045137.png"　 width=50%>

３ 各パラメータを入力します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/bbb0f795-dc2e-b72e-bb60-f858049d8c64.jpeg"　 width=50%>

|パラメータ名|用途|備考|
|:---|:---|:---|
|スタックの名前|テンプレートから作成するリソース一式の名前|例　prd-stack-nat-20180801|
|PJPrefix|構築するプロジェクトの環境を識別するために各コンポーネントの先頭に付与する識別子|例 qiita-prd|
|NATGatewayACreate|構成図のPublic SubnetAに作成する場合は、<font color="Red">true</font><br>構成図のPublic SubnetAに作成しない場合は、<font color="Red">false</font>|true（デフォルト）|
|NATGatewayCCreate|構成図のPublic SubnetCに作成する場合は、<font color="Red">true</font><br>構成図のPublic SubnetCに作成しない場合は、<font color="Red">false</font>|true（デフォルト）|

<font color="Red">注意事項：NATGatewayACreateとNATGatewayCCreateのどちらか一方は、trueにしない場合、エラーになります。</font>

4 後続は、デフォルトのまま次へ次へで、作成します。
状況が CREATE COMPLETEになれば、NAT Gatewayの構築が完了です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/f919b748-e62b-9f47-0eed-a3ab499405f0.png"　 width=50%>

#テンプレート
```natgateway.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"
```