本連載では、以下のイメージの構成にあるAWSリソース基盤自動化環境の構築を実践していきます。

本連載で構築していく基盤自動化環境のイメージ

前回は、AWSが提供するオープンソースツール「taskcat」を使って、作成したテンプレートをテストする環境を構築し、結果を出力する方法を解説しました。今回からは、実際にテンプレートを実装していきます。

今回は、サンプルで作成していたVPCに加えて、パブリック、プライベートサブネット、ルートテーブル、インターネットゲートウェイを作成します。このスタック構成は基本AWS無料枠で構成されるサービスとなっており、スタック構築後も特に費用は発生しません。

なお、実際のソースコードはGitHub上にコミットしています。以降のソースコードでは本質的でない記述を一部省略しているので、実行コードを作成する場合は、必要に応じて適宜GitHub上のソースコードも参照してください。

VPC/Subnet/RouteTable/InternetGatewayスタック構築テンプレート

構築するVPC関連の設定内容は、連載「クラウドネイティブアプリケーションの基本」の第4回で構築したVPC構成と基本的にほぼ同様です。違いとしては、構築するIPアドレス体系や、構築すると費用が発生するNATGatewayを除外している点、コンソール上で作成された際には自動作成される暗黙のメインルートテーブルとサブネットへの関連付けがCloudFormationでは実行されないので、定義を明示的に行っている点です(メインルートテーブルの作成と関連付けは、次回NATGatewayの設定で行います)。

サンプルとして作成する「sample-vpc-cfn.yml」は、以下の通りです。

AWSTemplateFormatVersion: '2010-09-09'

// omit

Parameters:
  VPCName:                                                                   #(A)
    Description: Target VPC Stack Name
    Type: String
    MinLength: 1
    MaxLength: 255
    AllowedPattern: ^[a-zA-Z][-a-zA-Z0-9]*$
    Default: mynavi-sample-cloudformation-vpc
  VPCCiderBlock:                                                             #(B)
    Description: CiderBlock paramater for VPC
    Type: String
    MinLength: 9
    MaxLength: 18
    AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
    Default: 172.200.0.0/16
  PublicSubnet1CiderBlock:                                                   #(C)
    Description: CiderBlock paramater for VPC
    Type: String
    MinLength: 9
    MaxLength: 18
    AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
    Default: 172.200.1.0/24

 // omit

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

  PublicSubnet1:                                                             #(E)
     Type: AWS::EC2::Subnet
     Properties:
       CidrBlock: !Sub ${PublicSubnet1CiderBlock}
       VpcId: !Ref VPC
       AvailabilityZone: !Select [ 0, !GetAZs '' ]                           #(F)
       Tags:
         - Key: Name
           Value: !Sub ${VPCName}-PublicSubnet1

// omit

  IGW:                                                                       #(G)
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${VPCName}-IGW

  IGWAttach:                                                                 #(H)
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref IGW
      VpcId: !Ref VPC

  CustomRouteTable:                                                          #(I)
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${VPCName}-PublicRoute

  CustomRoute:                                                               #(J)
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref CustomRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref IGW

  PublicSubnet1Association:                                                  #(K)
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref CustomRouteTable

// omit

Outputs:
  VPC:                                                                       #(L)
    Description: VPC ID
    Value: !Ref VPC
    Export:
      Name: !Sub ${VPCName}-VPCID

  PublicSubnet1:                                                             #(M)
    Description: PublicSubnet1
    Value: !Ref PublicSubnet1
    Export:
      Name: !Sub ${VPCName}-PublicSubnet1

  PublicSubnet1Arn:                                                          #(N)
    Description: PublicSubnet1Arn
    Value: !Sub                                                              #(O)
      - arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/${PublicSubnet1}
      - PublicSubnet1: !Ref PublicSubnet1
    Export:
      Name: !Sub ${VPCName}-PublicSubnet1Arn

 // omit

テンプレートの記述の基本となるポイントは、下表の通りです。

記述 説明
A ステージング環境/プロダクション環境など別のVPCを作る場合の再利用に備えて、VPC名をパラメータ化します
B 異なるVPCでIPアドレス帯を変更できるようにパラメータ化しておきます
C Bと同様、VPC内に構築するサブネットアドレス帯を変更できるようにパラメータ化します。なおここでは、1つのパブリックサブネットしか記載していませんが、パブリック/サブネット各2つずつ定義します
D 構築するVPCリソースを定義します。設定可能なパラメータや必須項目については、AWS公式ページ「AWS::EC2::VPC」を参照してください
E VPC内に構築するパブリック/プライベートサブネットリソースを定義します。設定可能なパラメータや必須項目については、AWS公式ページ「AWS::EC2::Subnet」を参照してください。なおここでは、1つのパブリックサブネットしか記載していませんが、パブリック/サブネット各2つずつ定義します
F サブネットのAvailabilityZoneプロパティでは、組み込みファンクション「!GetAZs」や「!Select」を組み合わせて、リージョンで使用可能なアベイラビリティゾーンを取得します
G VPCに設定するインターネットゲートウェイリソースを定義します。設定可能なパラメータや必須項目については、AWS公式ページ「AWS::EC2::InternetGateway」を参照してください
H Gで作成したインターネットゲートウェイリソースをアタッチするVPCを定義するゲートウェイアタッチメントリソースを定義します。設定可能なパラメータや必須項目については、AWS公式ページ「AWS::EC2::VPCGatewayAttachment」を参照してください
I インターネットゲートウェイへ到達するルートテーブルを作成します。設定可能なパラメータや必須項目については、AWS公式ページ「AWS::EC2::RouteTable」を参照してください
J インターネットゲートウェイへ到達するルートを作成します。設定可能なパラメータや必須項目については、AWS公式ページ「AWS::EC2::Route」を参照してください
K Jで作成したルートとパブリックサブネットを関連付けます。設定可能なパラメータや必須項目については、AWS公式ページ「AWS::EC2::SubnetRouteTableAssociation」を参照してください
L VPCの物理IDをOutputsとして出力します。この値は次回以降、別のテンプレートで使用します(クロススタックリファレンス)
M VPC内に構築したパブリックサブネットの物理IDをOutputsとして出力します。なおここでは、1つのパブリックサブネットしか記載していませんが、パブリック/サブネット各2つずつ定義します
N VPC内に構築したパブリックサブネットのARN(AmazonResourceName)をOutputsとして出力します。なおここでは、1つのパブリックサブネットしか記載していませんが、パブリック/サブネット各2つずつ定義します。この値は次回以降、別のテンプレートで使用します(クロススタックリファレンス)
O 組み込み関数「!Sub」やAWSデフォルトの擬似パラメータを用いて、サブネットのARNを組み立てます。!Subを配列で構成し、配列の第1要素で変換文字列、第2要素で変換パラメータを指定してARNを出力しています。この記法の詳細については、AWS公式ページ「Fn::Sub」を参照してください

作成したテンプレートに対して、以下のように、スタック名とテンプレートパスを変更してヘルパースクリプトを実行します。パラメータはデフォルト値を利用するので省略します。

#!/usr/bin/env bash

stack_name="mynavi-sample-vpc"
template_path="sample-vpc-cfn.yml"
#parameters="VPCCiderBlock=172.200.0.0/16"

if [ "$parameters" == "" ]; then
    aws cloudformation deploy --stack-name ${stack_name} --template-file ${template_path} --capabilities CAPABILITY_IAM
else
    aws cloudformation deploy --stack-name ${stack_name} --template-file ${template_path} --parameter-overrides ${parameters} --capabilities CAPABILITY_IAM
fi

実行が正常に終了すると、VPCやサブネット、インターネットゲートウェイが作成されます。

PCやサブネット、インターネットゲートウェイが作成される

次回は、セキュリティグループとNATゲートウェイ、アプリケーションロードバランサーを構築するスタックテンプレートについて解説します。

著者紹介


川畑 光平(KAWABATA Kohei) - NTTデータ 課長代理

金融機関システム業務アプリケーション開発・システム基盤担当を経て、現在はソフトウェア開発自動化関連の研究開発・推進に従事。

Red Hat Certified Engineer、Pivotal Certified Spring Professional、AWS Certified Solutions Architect Professional等の資格を持ち、アプリケーション基盤・クラウドなどさまざまな開発プロジェクト支援にも携わる。2019 APN AWS Top Engineers & Ambassadors選出。

本連載の内容に対するご意見・ご質問は Facebook まで。