0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VPCで理解するCloudFormation

Posted at

はじめに

新人であった昨年度、0からAWS基盤構築の経験をさせていただき、マネコン上からAWSのリソースを弄り回していると「あれ?これなんだっけ?いつのバージョンのやつだっけ?」みたいな現象が頻発してました。
やはりGUIは悪でCLIは正義ということを身を以って体感したのでCloudFormation(cfn)の学習を始めました。
今回はcfnの勉強がてらVPCの一般的な基盤構築を行ってみました。

構成図

vpc.png
ご覧の通り、マネコンの「VPCを作成 / VPCなど」で作成できる諸々のリソースを作成します。
RouteTableもマネコン上からはあまり意識しませんが、作成対象のため今回の構成図では明示的に記述しています。

テンプレート

以下先に全文。

template.vpc.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Create Fargate and ALB

Parameters:
  ProjectName:
    Type: String
    Description: Project Name for all
  VPCCiderBlock:
    Default: 10.0.0.0/16
    Type: String
    Description: VPC Cider Block for VPC
  PubSub1aCiderBlock:
    Default: 10.0.10.0/24
    Type: String
    Description: Public Subnet 1a Cider Block for PublicSubnet1a
  PriSub1aCiderBlock:
    Default: 10.0.20.0/24
    Type: String
    Description: Private Subnet 1a Cider Block for PrivateSubnet1a
  PubSub1cCiderBlock:
    Default: 10.0.30.0/24
    Type: String
    Description: Public Subnet 1c Cider Block for PublicSubnet1c
  PriSub1cCiderBlock:
    Default: 10.0.40.0/24
    Type: String
    Description: Private Subnet 1c Cider Block for PrivateSubnet1c

Resources:
  ############################################
  #### VPC                                ####
  ############################################
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCiderBlock
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-VPC

  ############################################
  #### Subnet                             ####
  ############################################
  PubSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      CidrBlock: !Ref PubSub1aCiderBlock
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-Public-Subnet-1a

  PriSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      CidrBlock: !Ref PriSub1aCiderBlock
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-Private-Subnet-1a

  PubSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      CidrBlock: !Ref PubSub1cCiderBlock
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-Public-Subnet-1c

  PriSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      CidrBlock: !Ref PriSub1cCiderBlock
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-Private-Subnet-1c

  ############################################
  #### Route Table                        ####
  ############################################
  PubRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-rtb-public
      VpcId: !Ref VPC

  PriRouteTable1a:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-rtb-private-1a
      VpcId: !Ref VPC

  PriRouteTable1c:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-rtb-private-1c
      VpcId: !Ref VPC

  ############################################
  #### Gateway                            ####
  ############################################
  S3Endpoint:
    Type: "AWS::EC2::VPCEndpoint"
    Properties:
      RouteTableIds:
        - !Ref PriRouteTable1a
        - !Ref PriRouteTable1c
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
      VpcEndpointType: Gateway
      VpcId: !Ref VPC

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

  IGWAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref IGW
      VpcId: !Ref VPC
      
      
  # ############################################
  # #### NAT Gateway                        ####
  # ############################################
  # >>>>>>>> NAT Gatewayが必要な場合 >>>>>>>>>>>>
  # NatGatewayEIP:
  #   Type: AWS::EC2::EIP
  #   Properties:
  #     Domain: vpc
  #   DependsOn: VPC
    
  # NatGateway:
  #   Type: AWS::EC2::NatGateway
  #   Properties:
  #     AllocationId: 
  #       Fn::GetAtt:
  #         - NatGatewayEIP
  #         - AllocationId
  #     SubnetId: !Ref PubSubnet1a
  #     Tags:
  #       - Key: Name
  #         Value: !Sub ${ProjectName}-natgateway
  # <<<<<<<<< NAT Gatewayが必要な場合 <<<<<<<<<<<<
  
  

  ############################################
  #### Route                              ####
  ############################################
  PubRoute:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref IGW
      RouteTableId: !Ref PubRouteTable
  
  # >>>>>>>>> NAT Gatewayが必要な場合 >>>>>>>>>
  # PriRoute1a:
  #   Type: AWS::EC2::Route
  #   Properties:
  #     RouteTableId: !Ref PriRouteTable1a
  #     DestinationCidrBlock: 0.0.0.0/0
  #     NatGatewayId: !Ref NatGateway

  # PriRoute1c:
  #   Type: AWS::EC2::Route
  #   Properties:
  #     RouteTableId: !Ref PriRouteTable1c
  #     DestinationCidrBlock: 0.0.0.0/0
  #     NatGatewayId: !Ref NatGateway
  # <<<<<<<<<< NAT Gatewayが必要な場合 <<<<<<<<

  ############################################
  #### Route Table Association            ####
  ############################################
  PubSub1aRouteTableAssociate:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PubRouteTable
      SubnetId: !Ref PubSubnet1a

  PubSub1cRouteTableAssociate:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PubRouteTable
      SubnetId: !Ref PubSubnet1c

  PriSub1aRouteTableAssociate:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PriRouteTable1a
      SubnetId: !Ref PriSubnet1a

  PriSub1cRouteTableAssociate:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PriRouteTable1c
      SubnetId: !Ref PriSubnet1c

############################################
#### OutPuts                            ####
############################################
Outputs:
  VpcId:
    Value: !Ref VPC
    Description: VPC ID
    Export:
      Name: !Sub ${ProjectName}-VpcId
  PubSub1aId:
    Value: !Ref PubSubnet1a
    Description: Public Subnet ID in ap-northeast-1a
    Export:
      Name: !Sub ${ProjectName}-PubSub1aId
  PubSub1cId:
    Value: !Ref PubSubnet1c
    Description: Public Subnet ID in ap-northeast-1c
    Export:
      Name: !Sub ${ProjectName}-PubSub1cId
  PriSub1aId:
    Value: !Ref PriSubnet1a
    Description: Private Subnet ID in ap-northeast-1a
    Export:
      Name: !Sub ${ProjectName}-PriSub1aId
  PriSub1cId:
    Value: !Ref PriSubnet1c
    Description: Private Subnet ID in ap-northeast-1c
    Export:
      Name: !Sub ${ProjectName}-PriSub1cId

ここで個人的に学びになった点をピックアップしてみます。

RouteTable

基本的にはマネコンで作成するときと同じ認識でリソースを作っていきますが、マネコンと大きく違う点がRouteTable関係です。
RouteTableは、AWS::EC2::RouteTableでRouteTable自体を作成し、AWS::EC2::Routeでそれぞれのルートを作成、AWS::EC2::SubnetRouteTableAssociationでRouteTableとSubnetを結び付けることで機能します。

なお、NAT Gatewayを使わない限り Private の Route は必要ありません。
理由としては、S3 Endpoint(ゲートウェイ型)はRouteTableに直接アタッチするためです。(マネコンでは Route として Private Subnet -> S3 Endpoint として作成される)

IGW

InternetGateWay(IGW)などのGateway関係は基本的に、その「Gateway本体」と「Gatewayのアタッチ処理」を別のキーとて記述する必要があります。
今回の例で言うと、 IGWで本体を作成して、IGWAttachmentでそれを作成済みのVPCにアタッチしています。

OutPuts

このキーはオプショナルですが、かなり使用頻度が高くなりそうなのでピックアップします。
OutPutsに記述することで、このテンプレートで定義したリソースを他のテンプレートでも呼び出せるようにすることができるようになります。
Valueで呼び出すリソースを、Export.Nameで呼び出す際の変数を定義します。
これで、VPCなどの多く共通して使いそうなリソースを個別のテンプレートとして用意しておいて、あとは使途に応じて随時作成するテンプレートから呼び出すことができるようになります。

パラメータと実行ファイル

テンプレートのParametersで、テンプレート内で使用する変数を定義することができます。
この際に変数に代入するものをテンプレート実行時に動的に与えても良いのですが、以下のようなjsonファイルとして外部に切り出して呼び出すこともできます。

parameter.vpc.json
[
  {
    "ParameterKey": "ProjectName",
    "ParameterValue": "test"
  }
]

また、以下のshスクリプトを実行することで、jsonファイルを使ったテンプレートからスタックを作成することができます。

deploy.vpc.sh
#!/bin/bash

aws cloudformation create-stack \
  --stack-name testStackVPC \
  --template-body file://template.vpc.yaml \
  --parameters file://parameter.vpc.json \
  --capabilities CAPABILITY_NAMED_IAM

まとめ

上記でVPCを対象にCfnの簡単な動きをまとめました。
やはりGUIでぽちぽちやっていると、現在のリソースの状況を把握しにくくなるのでコードで管理できるのは非常にいいですね。
今後もCfn使っていこうと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?