前提

・NATGatewayを作成しない。
・各VPCが2AZ(Private Subnet:2個、Public Subnet:2個)で構成される。
・CloudFormationのテンプレートをyaml形式とする。
・AWSの管理者ユーザで検証しています。
・AWS CloudShellよりCLI実行することでCloudFormationスタックを作成します。
・AWS CloudShellの使い方を割愛します。

NATGatewayの料金について

NATGatewayを作成しない理由としては、料金が高いからです。
Private SubnetでNATGatewayを使ってインターネットに接続する場合、NATGateway料金が発生します。逆にPublic Subnetでインターネットゲートウェイ(InternetGateway)を使ってインターネットに接続する場合、別途InternetGatewayの料金が発生しません。

検証などで、インターネットに出れる必要がある場合、Public SubnetでEC2などを作成します。インターネットに接続できない場合の検証はPrivate Subnetで作成します。

NAT ゲートウェイの料金(AWS公式より抜粋)
https://aws.amazon.com/jp/vpc/pricing/
VPC 内に NAT ゲートウェイを作成することを選択した場合は、ゲートウェイがプロビジョニングされ利用可能であった "NAT ゲートウェイ時間" に対して料金が請求されます。データ処理料金は、トラフィックの送信元か送信先にかかわらず、NAT ゲートウェイで処理されたギガバイト単位で適用されます。1 時間未満の NAT ゲートウェイ時間は、1 時間分として請求されます。また、NAT ゲートウェイを介して転送されるすべてのデータに対して標準的な AWS データ転送料金が発生します。NAT ゲートウェイへの課金を止めたい場合は、AWS マネジメントコンソール、コマンドラインインターフェイス、API を使用して NAT ゲートウェイを削除します。
リージョン:東京
NAT ゲートウェイあたりの料金 (USD/時) 処理データ 1 GB あたりの料金 (USD)
0.062USD 0.062USD

構成図

CloudFormationテンプレートとパラメーター

テンプレート

パラメーターを設定して再利用可能なテンプレートを作成します。
ファイル名:VPC_NoNatGateway.yaml

AWSTemplateFormatVersion: '2010-09-09'
Description: 'VPC'
Parameters:
# ----------------------------------------------------------------------------#
# Environment Parameters
# ----------------------------------------------------------------------------#
  Environment:
    Type: String
    Description: "Environment"

# ----------------------------------------------------------------------------#
# VPC Parameters
# ----------------------------------------------------------------------------#
  VpcCidrBlock:
    Type: String
    Description: "VpcCidrBlock"
  VpcName:
    Type: String
    Description: "VpcName"

# ----------------------------------------------------------------------------#
# DHCPOptions Parameters
# ----------------------------------------------------------------------------#
  DomainName:
    Type: String
    Description: "DomainName"
  DhcpOptionsName:
    Type: String
    Description: "DhcpOptionsName"

# ----------------------------------------------------------------------------#
# InternetGateway Parameters
# ----------------------------------------------------------------------------#
  InternetGatewayName:
    Type: String
    Description: "InternetGatewayName"

# ----------------------------------------------------------------------------#
# Subnet Parameters
# ----------------------------------------------------------------------------#
#PublicSubnet01 Parameters
  PublicSubnet01AvailabilityZone:
    Type: String
    Description: "PublicSubnet01AvailabilityZone"
  PublicSubnet01CidrBlock:
    Type: String
    Description: "PublicSubnet01CidrBlock"
  PublicSubnet01Name:
    Type: String
    Description: "PublicSubnet01Name"
#PublicSubnet02 Parameters
  PublicSubnet02AvailabilityZone:
    Type: String
    Description: "PublicSubnet02AvailabilityZone"
  PublicSubnet02CidrBlock:
    Type: String
    Description: "PublicSubnet02CidrBlock"
  PublicSubnet02Name:
    Type: String
    Description: "PublicSubnet02Name"
#PrivateSubnet01 Parameters
  PrivateSubnet01AvailabilityZone:
    Type: String
    Description: "PrivateSubnet01AvailabilityZone"
  PrivateSubnet01CidrBlock:
    Type: String
    Description: "PrivateSubnet01CidrBlock"
  PrivateSubnet01Name:
    Type: String
    Description: "PrivateSubnet01Name"
#PrivateSubnet02 Parameters
  PrivateSubnet02AvailabilityZone:
    Type: String
    Description: "PrivateSubnet02AvailabilityZone"
  PrivateSubnet02CidrBlock:
    Type: String
    Description: "PrivateSubnet02CidrBlock"
  PrivateSubnet02Name:
    Type: String
    Description: "PrivateSubnet02Name"

# ----------------------------------------------------------------------------#
# RouteTable Parameters
# ----------------------------------------------------------------------------#
#PublicSubnet01RouteTable Parameters
  PublicSubnet01RouteTableName:
    Type: String
    Description: "PublicSubnet01RouteTableName"
#PublicSubnet02RouteTable Parameters
  PublicSubnet02RouteTableName:
    Type: String
    Description: "PublicSubnet02RouteTableName"
#PrivateSubnet01RouteTable Parameters
  PrivateSubnet01RouteTableName:
    Type: String
    Description: "PrivateSubnet01RouteTableName"
#PrivateSubnet02RouteTable Parameters
  PrivateSubnet02RouteTableName:
    Type: String
    Description: "PrivateSubnet02RouteTableName"

# ----------------------------------------------------------------------------#
# IAMRole Parameters
# ----------------------------------------------------------------------------#
  VPCFlowLogsRoleDescription:
    Type: String
    Description: "VPCFlowLogsRoleDescription"
  RoleName:
    Type: String
    Description: "RoleName. The name created will be 'RoleName-Region'"   

# ----------------------------------------------------------------------------#
# IAM Managed Policy Parameters
# ----------------------------------------------------------------------------#
  PolicyDescription:
    Type: String
    Description: "PolicyDescription"
  ManagedPolicyName:
    Type: String
    Description: "PolicyName. The name created will be 'PolicyName-Region'"   

# ----------------------------------------------------------------------------#
# LogGroupName Parameters
# ----------------------------------------------------------------------------#
  LogGroupName:
    Type: String
    Description: "VPCFlowLogs LogGroupName"

# ----------------------------------------------------------------------------#
# FlowLog Parameters
# ----------------------------------------------------------------------------#
  FlowLogName:
    Type: String
    Description: "VPCFlowLogsName"

Resources:
# ----------------------------------------------------------------------------#
# VPC
# ----------------------------------------------------------------------------#
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidrBlock
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
      - Key: Name
        Value: !Ref VpcName
      - Key: Env
        Value: !Ref Environment

# ----------------------------------------------------------------------------#
# DHCPOptions
# ----------------------------------------------------------------------------#
  DHCPOptions:
    Type: AWS::EC2::DHCPOptions
    Properties:
      DomainName: !Ref DomainName
      DomainNameServers:
        - AmazonProvidedDNS
      Tags:
      - Key: Name
        Value: !Ref DhcpOptionsName
      - Key: Env
        Value: !Ref Environment

# ----------------------------------------------------------------------------#
# VPC DHCPOptions Association
# ----------------------------------------------------------------------------#
  InfraDev1TyoDHCPOptionsAssociation:
    Type: AWS::EC2::VPCDHCPOptionsAssociation
    Properties:
      VpcId: !Ref VPC
      DhcpOptionsId: !Ref DHCPOptions

# ----------------------------------------------------------------------------#
# InternetGateway
# ----------------------------------------------------------------------------#
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
      - Key: Name
        Value: !Ref InternetGatewayName
      - Key: Env
        Value: !Ref Environment

# ----------------------------------------------------------------------------#
# VPC Gateway Attachment
# ----------------------------------------------------------------------------#
  IGWAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

# ----------------------------------------------------------------------------#
# Subnet
# ----------------------------------------------------------------------------#
#PublicSubnet01
  PublicSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref PublicSubnet01AvailabilityZone
      CidrBlock: !Ref PublicSubnet01CidrBlock
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: !Ref PublicSubnet01Name
      - Key: Env
        Value: !Ref Environment
#PublicSubnet02
  PublicSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref PublicSubnet02AvailabilityZone
      CidrBlock: !Ref PublicSubnet02CidrBlock
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: !Ref PublicSubnet02Name
      - Key: Env
        Value: !Ref Environment
#PrivateSubnet01
  PrivateSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref PrivateSubnet01AvailabilityZone
      CidrBlock: !Ref PrivateSubnet01CidrBlock
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: !Ref PrivateSubnet01Name
      - Key: Env
        Value: !Ref Environment
#PrivateSubnet02
  PrivateSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref PrivateSubnet02AvailabilityZone
      CidrBlock: !Ref PrivateSubnet02CidrBlock
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: !Ref PrivateSubnet02Name
      - Key: Env
        Value: !Ref Environment

# ----------------------------------------------------------------------------#
# RouteTable
# ----------------------------------------------------------------------------#
#PublicSubnet01RouteTable
  PublicSubnet01RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: !Ref PublicSubnet01RouteTableName
      - Key: Env
        Value: !Ref Environment
#PublicSubnet02RouteTable
  PublicSubnet02RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: !Ref PublicSubnet02RouteTableName
      - Key: Env
        Value: !Ref Environment
#PrivateSubnet01RouteTable
  PrivateSubnet01RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: !Ref PrivateSubnet01RouteTableName
      - Key: Env
        Value: !Ref Environment
#PrivateSubnet02RouteTable
  PrivateSubnet02RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: !Ref PrivateSubnet02RouteTableName
      - Key: Env
        Value: !Ref Environment

# ----------------------------------------------------------------------------#
# Route
# ----------------------------------------------------------------------------#
#PublicSubnet01Route01
  PublicSubnet01Route01:
    Type: AWS::EC2::Route
    DependsOn: IGWAttachment
    Properties:
      RouteTableId: !Ref PublicSubnet01RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
#PublicSubnet02Route01
  PublicSubnet02Route01:
    Type: AWS::EC2::Route
    DependsOn: IGWAttachment
    Properties:
      RouteTableId: !Ref PublicSubnet02RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

# ----------------------------------------------------------------------------#
# Subnet RouteTable Association
# ----------------------------------------------------------------------------#
#PublicSubnet01RouteTableAssociation
  PublicSubnet01RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet01
      RouteTableId: !Ref PublicSubnet01RouteTable
#PublicSubnet02RouteTableAssociation
  PublicSubnet02RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet02
      RouteTableId: !Ref PublicSubnet02RouteTable
#PrivateSubnet01RouteTableAssociation
  PrivateSubnet01RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet01
      RouteTableId: !Ref PrivateSubnet01RouteTable
#PrivateSubnet02RouteTableAssociation
  PrivateSubnet02RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet02
      RouteTableId: !Ref PrivateSubnet02RouteTable

# ----------------------------------------------------------------------------#
# IAM Role
# ----------------------------------------------------------------------------#
  VPCFlowLogsRole:
    Type: AWS::IAM::Role
    Properties:
      Description: !Ref VPCFlowLogsRoleDescription
# RoleName must be set considering multiple regions.
# https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-rolename
      RoleName: 
        !Join 
          - '-'
          -
            - !Ref RoleName
            - !Ref  AWS::Region
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: Allow
          Principal:
            Service: "vpc-flow-logs.amazonaws.com"
          Action: "sts:AssumeRole"
      Path: /
      Tags:
        - Key: Name
          Value:
            !Join 
              - '-'
              -
                - !Ref RoleName
                - !Ref  AWS::Region
        - Key: Env
          Value: !Ref Environment                   

# ----------------------------------------------------------------------------#
# IAM Managed Policy
# ----------------------------------------------------------------------------#
  VPCFlowLogsManagedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      Description: !Ref PolicyDescription
# ManagedPolicyName must be set considering multiple regions.
# https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html#cfn-iam-managedpolicy-managedpolicyname
      ManagedPolicyName: 
        !Join 
          - '-'
          -
            - !Ref ManagedPolicyName
            - !Ref  AWS::Region
      Path: /
      Roles:
        - !Ref VPCFlowLogsRole
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: Allow
          Action:
            - "logs:CreateLogGroup"
            - "logs:CreateLogStream"
            - "logs:PutLogEvents"
            - "logs:DescribeLogGroups"
            - "logs:DescribeLogStreams"
          Resource: "*"

# ----------------------------------------------------------------------------#
# LogGroup
# ----------------------------------------------------------------------------#
  VPCFlowLogsLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Ref LogGroupName

# ----------------------------------------------------------------------------#
# FlowLog
# ----------------------------------------------------------------------------#
  FlowLog:
    Type: AWS::EC2::FlowLog
    Properties:
      ResourceType: VPC
      ResourceId: !Ref VPC
      TrafficType: ALL
      LogDestinationType: cloud-watch-logs
      LogGroupName: !Ref VPCFlowLogsLogGroup
      DeliverLogsPermissionArn: !GetAtt VPCFlowLogsRole.Arn
      MaxAggregationInterval: 600
      Tags:
      - Key: Name
        Value: !Ref FlowLogName
      - Key: Env
        Value: !Ref Environment      

Outputs:
# ----------------------------------------------------------------------------#
# VPC Outputs
# ----------------------------------------------------------------------------#
  VPC:
    Value: !Ref VPC
    Export:
      Name: !Ref VpcName

# ----------------------------------------------------------------------------#
# Subnet Outputs
# ----------------------------------------------------------------------------#
#PublicSubnet01
  PublicSubnet01:
    Value: !Ref PublicSubnet01
    Export:
      Name: !Ref PublicSubnet01Name
#PublicSubnet02
  PublicSubnet02:
    Value: !Ref PublicSubnet02
    Export:
      Name: !Ref PublicSubnet02Name
#PrivateSubnet01
  PrivateSubnet01:
    Value: !Ref PrivateSubnet01
    Export:
      Name: !Ref PrivateSubnet01Name
#PrivateSubnet02
  PrivateSubnet02:
    Value: !Ref PrivateSubnet02
    Export:
      Name: !Ref PrivateSubnet02Name

# ----------------------------------------------------------------------------#
# RouteTable Outputs
# ----------------------------------------------------------------------------#
#PublicSubnet01RouteTable
  PublicSubnet01RouteTable:
    Value: !Ref PublicSubnet01RouteTable
    Export:
      Name: !Ref PublicSubnet01RouteTableName
#PublicSubnet02RouteTable
  PublicSubnet02RouteTable:
    Value: !Ref PublicSubnet02RouteTable
    Export:
      Name: !Ref PublicSubnet02RouteTableName
#PrivateSubnet01RouteTable
  PrivateSubnet01RouteTable:
    Value: !Ref PrivateSubnet01RouteTable
    Export:
      Name: !Ref PrivateSubnet01RouteTableName
#PrivateSubnet02RouteTable
  PrivateSubnet02RouteTable:
    Value: !Ref PrivateSubnet02RouteTable
    Export:
      Name: !Ref PrivateSubnet02RouteTableName

パラメーター(Inputファイル)

ファイル名:KbyDev3-Tyo-VPC_NoNatGateway.yaml

StackName: 'KbyDev3-Tyo-VPC'
Parameters:
- ParameterKey: 'Environment'
  ParameterValue: 'KbyDev3'
- ParameterKey: 'VpcCidrBlock'
  ParameterValue: '10.30.0.0/16'
- ParameterKey: 'VpcName'
  ParameterValue: 'KbyDev3-Tyo-Vpc'
- ParameterKey: 'DomainName'
  ParameterValue: 'ap-northeast-1.compute.internal'
- ParameterKey: 'DhcpOptionsName'
  ParameterValue: 'KbyDev3-Tyo-DhcpOptions'
- ParameterKey: 'InternetGatewayName'
  ParameterValue: 'KbyDev3-Tyo-Igw01'

- ParameterKey: 'PublicSubnet01AvailabilityZone'
  ParameterValue: 'ap-northeast-1c'
- ParameterKey: 'PublicSubnet01CidrBlock'
  ParameterValue: '10.30.0.0/23'
- ParameterKey: 'PublicSubnet01Name'
  ParameterValue: 'KbyDev3-Tyo-Subnet-Front01'

- ParameterKey: 'PublicSubnet02AvailabilityZone'
  ParameterValue: 'ap-northeast-1a'
- ParameterKey: 'PublicSubnet02CidrBlock'
  ParameterValue: '10.30.100.0/23'
- ParameterKey: 'PublicSubnet02Name'
  ParameterValue: 'KbyDev3-Tyo-Subnet-Front02'

- ParameterKey: 'PrivateSubnet01AvailabilityZone'
  ParameterValue: 'ap-northeast-1c'
- ParameterKey: 'PrivateSubnet01CidrBlock'
  ParameterValue: '10.30.2.0/23'
- ParameterKey: 'PrivateSubnet01Name'
  ParameterValue: 'KbyDev3-Tyo-Subnet-Back01'

- ParameterKey: 'PrivateSubnet02AvailabilityZone'
  ParameterValue: 'ap-northeast-1a'
- ParameterKey: 'PrivateSubnet02CidrBlock'
  ParameterValue: '10.30.102.0/23'
- ParameterKey: 'PrivateSubnet02Name'
  ParameterValue: 'KbyDev3-Tyo-Subnet-Back02'

- ParameterKey: 'PublicSubnet01RouteTableName'
  ParameterValue: 'KbyDev3-Tyo-Rt-Front01'
- ParameterKey: 'PublicSubnet02RouteTableName'
  ParameterValue: 'KbyDev3-Tyo-Rt-Front02'
- ParameterKey: 'PrivateSubnet01RouteTableName'
  ParameterValue: 'KbyDev3-Tyo-Rt-Back01'
- ParameterKey: 'PrivateSubnet02RouteTableName'
  ParameterValue: 'KbyDev3-Tyo-Rt-Back02'

- ParameterKey: 'VPCFlowLogsRoleDescription'
  ParameterValue: 'IAMRole associated with the KbyDev3-Tyo-Vpc flow log'
- ParameterKey: 'RoleName'
  ParameterValue: 'KbyDev3-Tyo-IamRole-VPCFlowLogs'

- ParameterKey: 'PolicyDescription'
  ParameterValue: 'KbyDev3-Tyo-Vpc VPCFlowLogs IAM Managed Policy'
- ParameterKey: 'ManagedPolicyName'
  ParameterValue: 'KbyDev3-Tyo-ManagedPolicy-VPCFlowLogs'

- ParameterKey: 'LogGroupName'
  ParameterValue: 'KbyDev3-Tyo-Clwlog-VPCFlowLogs'
- ParameterKey: 'FlowLogName'
  ParameterValue: 'KbyDev3-Tyo-VPCFlowLogs'

Tags:
- Key: 'Name'
  Value: 'VPC'
- Key: 'Env'
  Value: 'KbyDev3-Tyo'

CLIでスタックの作成手順

1.予め必要なファイルをAWS CloudShellにアップします。

2.テンプレートファイルとパラメーターファイルが存在していることを確認

[cloudshell-user@ip-10-0-81-133 ~]$ ls -l
total 20
-rw-rw-r-- 1 cloudshell-user cloudshell-user  2506 Jul 16 06:43 KbyDev3-Tyo-VPC_NoNatGateway.yaml
-rw-rw-r-- 1 cloudshell-user cloudshell-user 16034 Jul 16 06:44 VPC_NoNatGateway.yaml

2.スタックの作成

コマンド:

aws cloudformation create-stack --template-body file://テンプレートファイル.yaml --cli-input-yaml file://パラメーターファイル.yaml --capabilities CAPABILITY_NAMED_IAM

コマンド例:

[cloudshell-user@ip-10-0-81-133 ~]$ aws cloudformation create-stack --template-body file://VPC_NoNatGateway.yaml --cli-input-yaml file://KbyDev3-Tyo-VPC_NoNatGateway.yaml --capabilities CAPABILITY_NAMED_IAM
{
    "StackId": "arn:aws:cloudformation:ap-northeast-1:887233683286:stack/KbyDev3-Tyo-VPC/a41e8eb0-04d3-11ed-b4e3-0e60318394c1"
}
[cloudshell-user@ip-10-0-81-133 ~]$ 

作成後の確認

1.スタックの確認

1-1.イベント画面の確認

1-2.リソース画面の確認

1-3.出力画面の確認

VPCのテンプレートで下記の画像のように後続で利用したいリソースをエクスポートしています。
後続のSGやEC2作成する時に「参照例」のように参照できます。

参照例:

VpcId: !ImportValue KbyDev3-Tyo-Vpc

2.VPCコンソールの確認

2-1.NATGatewayがないことを確認

2-2.InternetGatewayがあることを確認

2-3.Private Subnetのルートが1つであることを確認

2-4.Public Subnetのルートが2つであることを確認

まとめ

テンプレートを利用する時、名前の命名ルールを自分の環境に読み替えでください。
VPCのテンプレートで後続で利用したいリソースをエクスポートしています。
後続のSGやEC2作成する時に参照できます。次回の記事は、VPCのエクスポート名を参照してSGを作成したいと思います。

少しでもお役に立てれば幸いです。

参考

CloudFormation でよく使うAWS CLIコマンド

AWS CloudFormationでEC2AutoScalingを作成してみました(CLI)

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html

Last modified: 2022-07-16

Author