概要
今回はCloudFormationを使って
- VPC
- パブリックサブネットとプライベートサブネット
- IGW
- ルートテーブルおよびルーティングの設定
を構築したいと思います
前提
- 東京リージョンを使用
- AWSを使用
- ネットワークに関する基本的な知識をある程度持っている
ディレクトリ構成
構成は以下の通りです
tree
.
└── templates
└── network
└── vpc.yml
vpc.yml
AWSTemplateFormatVersion: 2010-09-09
Description: 'VPC Stack'
# -------------------------------------
# Metadata
# -------------------------------------
Metadata:
# 入力パラメータのグループ化と順序を指定
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "Common Configuration"
Parameters:
- ProjectName
- Environment
- Label:
default: "VPC Configuration"
Parameters:
- VPCCIDR
- ELBPublicSubnet1CIDR
- ELBPublicSubnet2CIDR
- ECSPublicSubnet1CIDR
- ECSPublicSubnet2CIDR
- RDSPrivateSubnet1CIDR
- RDSPrivateSubnet2CIDR
# -------------------------------------
# Parameters
# -------------------------------------
Parameters:
ProjectName:
Description: "Please type the ProjectName. (ex: my-project)"
Type: String
Default: my-project
ConstraintDescription: "ProjectName is required."
MinLength: 1
Environment:
Description: "Please select Environment."
Type: String
Default: dev
AllowedValues:
- dev
- stg
- prd
ConstraintDescription: "Environment must be select."
VPCCIDR:
Description: "Please type the VPC CIDR."
Type: String
Default: 10.0.0.0/16
ELBPublicSubnet1CIDR:
Description: "Please type the ELB Public Subnet 1 CIDR."
Type: String
Default: 10.0.1.0/24
ELBPublicSubnet2CIDR:
Description: "Please type the ELB Public Subnet 2 CIDR."
Type: String
Default: 10.0.2.0/24
ECSPublicSubnet1CIDR:
Description: "Please type the ECS Public Subnet 1 CIDR."
Type: String
Default: 10.0.3.0/24
ECSPublicSubnet2CIDR:
Description: "Please type the ECS Public Subnet 2 CIDR."
Type: String
Default: 10.0.4.0/24
RDSPrivateSubnet1CIDR:
Description: "Please type the RDS Private Subnet 1 CIDR."
Type: String
Default: 10.0.5.0/24
RDSPrivateSubnet2CIDR:
Description: "Please type the RDS Private Subnet 2 CIDR."
Type: String
Default: 10.0.6.0/24
# -------------------------------------
# Resources
# -------------------------------------
Resources:
# -------------------------------------
# VPC
# -------------------------------------
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${Environment}-vpc
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
# VPC内にインターネットゲートウェイがないとパブリックサブネットからインターネットへアクセスできないので作成
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
# Parametersで入力した値を対応する変数に置き換える
# https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html
Value: !Sub ${ProjectName}-${Environment}-igw
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
# インターネットゲートウェイをVPCにアタッチする
AttachInternetGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId : !Ref InternetGateway
# -------------------------------------
# Public Subnet
# -------------------------------------
ELBPublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
VpcId: !Ref VPC
CidrBlock: !Ref ELBPublicSubnet1CIDR
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value:
!Join [
"-",
[
!Sub "${ProjectName}-${Environment}-pub-alb",
!Select [2, !Split ["-", !Select [0, !GetAZs ""]]],
],
]
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
ELBPublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [1, !GetAZs ""]
VpcId: !Ref VPC
CidrBlock: !Ref ELBPublicSubnet2CIDR
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value:
!Join [
"-",
[
!Sub "${ProjectName}-${Environment}-pub-alb",
!Select [2, !Split ["-", !Select [1, !GetAZs ""]]],
],
]
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
ECSPublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref ECSPublicSubnet1CIDR
# パブリックIPv4アドレスの自動割り当て
# パブリックなのでtrueにする
MapPublicIpOnLaunch: true
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs ""]
Tags:
- Key: Name
Value:
!Join [
"-",
[
!Sub "${ProjectName}-${Environment}-pub-ecs",
!Select [2, !Split ["-", !Select [0, !GetAZs ""]]],
],
]
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
ECSPublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref ECSPublicSubnet2CIDR
MapPublicIpOnLaunch: true
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs ""]
Tags:
- Key: Name
Value:
!Join [
"-",
[
!Sub "${ProjectName}-${Environment}-pub-ecs",
!Select [2, !Split ["-", !Select [1, !GetAZs ""]]],
],
]
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
RDSPrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
# パブリックIPv4アドレスの自動割り当て
# プライベートなのでfalseにする
CidrBlock: !Ref RDSPrivateSubnet1CIDR
MapPublicIpOnLaunch: false
# VPCのLogicalIDを!Refで参照してあげることでVPCのIDを自動的に当てはめる
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs ""]
Tags:
- Key: Name
Value:
!Join [
"-",
[
!Sub "${ProjectName}-${Environment}-priv-rds",
!Select [2, !Split ["-", !Select [0, !GetAZs ""]]],
],
]
RDSPrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [1, !GetAZs ""]
VpcId: !Ref VPC
CidrBlock: !Ref RDSPrivateSubnet2CIDR
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value:
!Join [
"-",
[
!Sub "${ProjectName}-${Environment}-priv-rds",
!Select [2, !Split ["-", !Select [1, !GetAZs ""]]],
],
]
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
# -------------------------------------
# Public Route Table
# -------------------------------------
ELBPublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
# どのVPCと紐づけるか定義する
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${Environment}-pub-alb-rtb
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
# ELBのルーティング
ELBPublicRoute:
Type: AWS::EC2::Route
# インターネットゲートウェイと紐付ける
DependsOn: AttachInternetGateway
Properties:
RouteTableId: !Ref ELBPublicRouteTable
# インターネット(0.0.0.0/0)へのアクセスを許可
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
# ルートテーブルとサブネットを紐づける
ELBPublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref ELBPublicSubnet1
RouteTableId: !Ref ELBPublicRouteTable
ELBPublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref ELBPublicSubnet2
RouteTableId: !Ref ELBPublicRouteTable
ECSPublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${Environment}-pub-ecs-rtb
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
ECSPublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachInternetGateway
Properties:
RouteTableId: !Ref ECSPublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
ECSPublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref ECSPublicSubnet1
RouteTableId: !Ref ECSPublicRouteTable
ECSPublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref ECSPublicSubnet2
RouteTableId: !Ref ECSPublicRouteTable
# -------------------------------------
# Private Route Table
# -------------------------------------
RDSPrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${Environment}-priv-rds-rtb
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
RDSPrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref RDSPrivateSubnet1
RouteTableId: !Ref RDSPrivateRouteTable
RDSPrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref RDSPrivateSubnet2
RouteTableId: !Ref RDSPrivateRouteTable
# -------------------------------------
# Outputs
# -------------------------------------
# https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html
Outputs:
VPC:
Description: "A reference to the created VPC."
Value: !Ref VPC
PublicSubnets:
Description: "A list of the public subnets."
Value:
!Join [
",",
[
!Ref ECSPublicSubnet1,
!Ref ECSPublicSubnet2,
!Ref ELBPublicSubnet1,
!Ref ELBPublicSubnet2,
],
]
PrivateSubnets:
Description: "A list of the private subnets."
Value: !Join [",", [!Ref RDSPrivateSubnet1, !Ref RDSPrivateSubnet2]]
ELBPublicSubnet1:
Description: "A reference to the public subnet in the 1st Availability Zone."
Value: !Ref ELBPublicSubnet1
ELBPublicSubnet2:
Description: "A reference to the public subnet in the 2nd Availability Zone."
Value: !Ref ELBPublicSubnet2
ECSPublicSubnet1:
Description: "A reference to the public subnet in the 1st Availability Zone."
Value: !Ref ECSPublicSubnet1
ECSPublicSubnet2:
Description: "A reference to the public subnet in the 2nd Availability Zone."
Value: !Ref ECSPublicSubnet2
RDSPrivateSubnet1:
Description: "A reference to the private subnet in the 1st Availability Zone."
Value: !Ref RDSPrivateSubnet1
RDSPrivateSubnet2:
Description: "A reference to the private subnet in the 2nd Availability Zone."
Value: !Ref RDSPrivateSubnet2
1つずつ解説していきます
Metadata
Metadataを使用する際に
AWS::CloudFormation::Interface:
と記載することで後述するParametersをグループ分けして見やすくすることができます
今回は
- Common Configuration(汎用的な設定)
- プロジェクト名や環境(dev,stg,prd)などタグ付けに必要な変数
- VPC Configuration(VPCの設定)
- VPC,ALB,ECS,RDSのCIDRの設定
2種類に分類します
# -------------------------------------
# Metadata
# -------------------------------------
Metadata:
# 入力パラメータのグループ化と順序を指定
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "Common Configuration"
Parameters:
- ProjectName
- Environment
- Label:
default: "VPC Configuration"
Parameters:
- VPCCIDR
- ELBPublicSubnet1CIDR
- ELBPublicSubnet2CIDR
- ECSPublicSubnet1CIDR
- ECSPublicSubnet2CIDR
- RDSPrivateSubnet1CIDR
- RDSPrivateSubnet2CIDR
Parameters
Metadataで説明したパラメータのデフォルト値の設定などを行います
# -------------------------------------
# Parameters
# -------------------------------------
Parameters:
ProjectName:
Description: "Please type the ProjectName. (ex: my-project)"
Type: String
Default: my-project
ConstraintDescription: "ProjectName is required."
MinLength: 1
Environment:
Description: "Please select Environment."
Type: String
Default: dev
# AllowedValuesを設定することでパラメータ指定時にドロップダウン形式で選択できる
AllowedValues:
- dev
- stg
- prd
ConstraintDescription: "Environment must be select."
VPCCIDR:
Description: "Please type the VPC CIDR."
Type: String
Default: 10.0.0.0/16
ELBPublicSubnet1CIDR:
Description: "Please type the ELB Public Subnet 1 CIDR."
Type: String
Default: 10.0.1.0/24
ELBPublicSubnet2CIDR:
Description: "Please type the ELB Public Subnet 2 CIDR."
Type: String
Default: 10.0.2.0/24
ECSPublicSubnet1CIDR:
Description: "Please type the ECS Public Subnet 1 CIDR."
Type: String
Default: 10.0.3.0/24
ECSPublicSubnet2CIDR:
Description: "Please type the ECS Public Subnet 2 CIDR."
Type: String
Default: 10.0.4.0/24
RDSPrivateSubnet1CIDR:
Description: "Please type the RDS Private Subnet 1 CIDR."
Type: String
Default: 10.0.5.0/24
RDSPrivateSubnet2CIDR:
Description: "Please type the RDS Private Subnet 2 CIDR."
Type: String
Default: 10.0.6.0/24
VPC
VPCを作成します
Resources:
# -------------------------------------
# VPC
# -------------------------------------
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${Environment}-vpc
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
Internet Gateway
パブリックサブネットからインターネットへアクセスできるようにするためにVPC内にインターネットゲートウェイを作成します
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
# Parametersで入力した値を対応する変数に置き換える
# https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html
Value: !Sub ${ProjectName}-${Environment}-igw
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
# インターネットゲートウェイをVPCにアタッチする
AttachInternetGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId : !Ref InternetGateway
パブリックサブネット
ELBPublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
VpcId: !Ref VPC
CidrBlock: !Ref ELBPublicSubnet1CIDR
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value:
!Join [
"-",
[
!Sub "${ProjectName}-${Environment}-pub-alb",
!Select [2, !Split ["-", !Select [0, !GetAZs ""]]],
],
]
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
ELBのパブリックサブネットを例に説明します
AvailabilityZoneをハードコーディングするのは推奨されていないので
!Select [0, !GetAZs ""]
を使用するとリージョン内のAZの配列のうち指定した配列のindex番号を取得します
(東京リージョンだと仮定してap-northeast-1aが指定されます)
詳細はAWSの公式ドキュメントを参照してください
タグについても説明します
!Select [0, !GetAZs ""]
でAZ(ap-norteast-1aと仮定します)を取得し、
!Split関数を使って"-"でAZを配列にして分離します
["ap","northeast","1a"]
その後、
!Select [2, !Split ["-", !Select [0, !GetAZs ""]]],
をすることで
["ap","northeast","1a"]
の2番目のindexの値(1a)を取得します
最後に!Join関数を使って
"${ProjectName}-${Environment}-pub-alb"と"1a"を"-"で合体させます
- ProjectNameがmy-project
- Environmentがdev
と仮定すると、Nameタグの値が
my-project-dev-pub-albー1a
になり、AZに応じたより汎用的なタグ名になります
Tags:
- Key: Name
Value:
!Join [
"-",
[
!Sub "${ProjectName}-${Environment}-pub-alb",
!Select [2, !Split ["-", !Select [0, !GetAZs ""]]],
],
]
他のパブリックサブネットもプライベートサブネットも同様に作成します
パブリックルートテーブル
ELBを例に説明します
ルートテーブルをどの
- サブネット
- VPC
- インタネットゲートウェイ
と紐づけるかと
ルーティング(パブリックなのですべてのIPアドレスを許可)
を設定する必要があります
# -------------------------------------
# Public Route Table
# -------------------------------------
ELBPublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
# どのVPCと紐づけるか定義する
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${Environment}-pub-alb-rtb
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
# ELBのルーティング
ELBPublicRoute:
Type: AWS::EC2::Route
# インターネットゲートウェイと紐付ける
DependsOn: AttachInternetGateway
Properties:
RouteTableId: !Ref ELBPublicRouteTable
# インターネット(0.0.0.0/0)へのアクセスを許可
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
ECSも同様の設定を行います
プライベートルートテーブル
プライベートルートテーブルからインターネットへアクセスすることはないのでInternetGatewayの設定は不要です
# -------------------------------------
# Private Route Table
# -------------------------------------
RDSPrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${Environment}-priv-rds-rtb
- Key: ProjectName
Value: !Ref ProjectName
- Key: Environment
Value: !Ref Environment
RDSPrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref RDSPrivateSubnet1
RouteTableId: !Ref RDSPrivateRouteTable
RDSPrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref RDSPrivateSubnet2
RouteTableId: !Ref RDSPrivateRouteTable
Outputs
Stack作成後に出力する情報を記載し、他のスタックでも利用できるようにします
# -------------------------------------
# Outputs
# -------------------------------------
# https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html
Outputs:
VPC:
Description: "A reference to the created VPC."
Value: !Ref VPC
PublicSubnets:
Description: "A list of the public subnets."
Value:
!Join [
",",
[
!Ref ECSPublicSubnet1,
!Ref ECSPublicSubnet2,
!Ref ELBPublicSubnet1,
!Ref ELBPublicSubnet2,
],
]
PrivateSubnets:
Description: "A list of the private subnets."
Value: !Join [",", [!Ref RDSPrivateSubnet1, !Ref RDSPrivateSubnet2]]
ELBPublicSubnet1:
Description: "A reference to the public subnet in the 1st Availability Zone."
Value: !Ref ELBPublicSubnet1
ELBPublicSubnet2:
Description: "A reference to the public subnet in the 2nd Availability Zone."
Value: !Ref ELBPublicSubnet2
ECSPublicSubnet1:
Description: "A reference to the public subnet in the 1st Availability Zone."
Value: !Ref ECSPublicSubnet1
ECSPublicSubnet2:
Description: "A reference to the public subnet in the 2nd Availability Zone."
Value: !Ref ECSPublicSubnet2
RDSPrivateSubnet1:
Description: "A reference to the private subnet in the 1st Availability Zone."
Value: !Ref RDSPrivateSubnet1
RDSPrivateSubnet2:
Description: "A reference to the private subnet in the 2nd Availability Zone."
Value: !Ref RDSPrivateSubnet2
実際に作成してみよう!
Parametersで作成したパラメータとデフォルト値が表示されていることを確認できます
また、Metadataを定義したことでパラメータが
- Common Configuration
- VPC Configuration
の2つに分類されていることが確認できました
リソースを確認しよう!
以下のようにリソースが作成されたら成功です
VPC
サブネット
インターネットゲートウェイ
不要なリソースを削除しよう!
参考