はじめに
最近、自身のAWS環境でネットワークのスタディーをするために、主要なネットワーク関連のサービス(S3ゲートウェイ・エンドポイント、PrivateLink、トランジット・ゲートウェイ、ゲートウェイ・ロードバランサー)の環境構築・実機検証をやっていました。その際、事前準備としてVPC環境作成(サブネットや、インターネットゲートウェイ、セキュリティー・グループ作成など)が必要となりますが、毎度毎度同じセットアップをすることになり手間もかかります。そこで、本来試したいネットワーク関連サービスの検証に時間を割けるようにすべく、事前準備部分のVPC環境作成をCloudFormationのコードを書いて自動作成できるようにしてみました。本記事では、筆者が作成したCloudFormationのサンプルコードをご紹介します。
なお、CloudFormationの詳細については、AWS CloudFormationドキュメントを参照ください。
作成するVPC環境
今回作成する構成は下記の通りです。
- AWSのリージョン:東京リージョン(ap-northeast-1)を使用
- 以下のCIDRアドレス範囲を持つVPCを作成
- VPC (10.0.0.0/16)
- AZ(ap-northeast-1a)に、以下のCIDRアドレス範囲をもつサブネットを作成
- パブリック・サブネット (10.0.1.0/24)
- プライベート・サブネット (10.0.2.0/24)
- AZ(ap-northeast-1c)に、以下のCIDRアドレス範囲をもつサブネットを作成
- パブリック・サブネット (10.0.3.0/24)
- プライベート・サブネット (10.0.4.0/24)
- インターネットゲートウェイ
- ルートテーブル
- パブリック・サブネットに対するルートテーブルには、下記の宛先とターゲットを別途追記指定
- 宛先:0.0.0.0/0、ターゲット:インターネットゲートウェイ
- パブリック・サブネットに対するルートテーブルには、下記の宛先とターゲットを別途追記指定
- セキュリティー・グループ
- パブリック・サブネットとプライベート・サブネットそれぞれに対してグループを用意
- パブリック・サブネット用
- 外部からのSSH、HTTP通信を許可
- プライベート・サブネット用
- パブリック・サブネットからのSSH通信とPINGを許可
- パブリック・サブネット用
- パブリック・サブネットとプライベート・サブネットそれぞれに対してグループを用意
CloudFormationサンプルコード
今回作成したサンプルコードは下記のようなYAMLファイルです。
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample Script for Creating NetWork Stack (VPC,Public Subnet,Private Subnet,Internet Gateway,Route Table,Security Group)
Parameters:
AzName01:
Description: Set 1st az-name
Type: String
Default: ap-northeast-1a
AllowedValues:
- ap-northeast-1a
- ap-northeast-1c
- ap-northeast-1d
AzName02:
Description: Set 2nd az-name
Type: String
Default: ap-northeast-1c
AllowedValues:
- ap-northeast-1a
- ap-northeast-1c
- ap-northeast-1d
VPCCidrBlock:
Description: VPC Cidr Block
Type: String
Default: 10.0.0.0/16
PublicSubnetCidrBlock01:
Description: Public Subnet Cidr Block for 1st az-name
Type: String
Default: 10.0.1.0/24
PrivateSubnetCidrBlock01:
Description: Private Subnet Cidr Block for 1st az-name
Type: String
Default: 10.0.2.0/24
PublicSubnetCidrBlock02:
Description: Public Subnet Cidr Block for 2nd az-name
Type: String
Default: 10.0.3.0/24
PrivateSubnetCidrBlock02:
Description: Private Subnet Cidr Block for 2nd az-name
Type: String
Default: 10.0.4.0/24
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCidrBlock
EnableDnsHostnames: 'true'
EnableDnsSupport: 'true'
Tags:
- Key: Name
Value: My-vpc
MyPublicSubnet01:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: !Ref PublicSubnetCidrBlock01
AvailabilityZone: !Ref AzName01
Tags:
- Key: Name
Value: My-Public-Subnet-01
DependsOn: MyVPC
MyPrivateSubnet01:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: !Ref PrivateSubnetCidrBlock01
AvailabilityZone: !Ref AzName01
Tags:
- Key: Name
Value: My-Private-Subnet-01
DependsOn: MyVPC
MyPublicSubnet02:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: !Ref PublicSubnetCidrBlock02
AvailabilityZone: !Ref AzName02
Tags:
- Key: Name
Value: My-Public-Subnet-02
DependsOn: MyVPC
MyPrivateSubnet02:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: !Ref PrivateSubnetCidrBlock02
AvailabilityZone: !Ref AzName02
Tags:
- Key: Name
Value: My-Private-Subnet-02
DependsOn: MyVPC
MyIGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: My-internet-gateway
DependsOn: MyVPC
MyIGWAttachToVPC:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MyVPC
InternetGatewayId: !Ref MyIGW
MyPublicRtbl01:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: My-Public-Rtbl-01
DependsOn: MyIGW
MyPublicRoute01:
Type: AWS::EC2::Route
Properties:
RouteTableId:
Ref: MyPublicRtbl01
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref MyIGW
MyPublicSubnetRouteTblAssociation01:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref MyPublicRtbl01
SubnetId: !Ref MyPublicSubnet01
MyPrivateRtbl01:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: My-Private-Rtbl-01
MyPrivateSubnetRouteTblAssociation01:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref MyPrivateRtbl01
SubnetId: !Ref MyPrivateSubnet01
MyPublicRtbl02:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: My-Public-Rtbl-02
DependsOn: MyIGW
MyPublicRoute02:
Type: AWS::EC2::Route
Properties:
RouteTableId:
Ref: MyPublicRtbl02
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref MyIGW
MyPublicSubnetRouteTblAssociation02:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref MyPublicRtbl02
SubnetId: !Ref MyPublicSubnet02
MyPrivateRtbl02:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: My-Private-Rtbl-02
MyPrivateSubnetRouteTblAssociation02:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref MyPrivateRtbl02
SubnetId: !Ref MyPrivateSubnet02
MyPublicSecGrp01:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow http to client host
VpcId: !Ref MyVPC
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 22
ToPort: 22
- CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 80
ToPort: 80
Tags:
- Key: Name
Value: My-Public-Security-Group-01
MyPrivateSecGrp01:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow Ingress trafic from Public Subnet
VpcId: !Ref MyVPC
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref MyPublicSecGrp01
IpProtocol: tcp
FromPort: 22
ToPort: 22
- SourceSecurityGroupId: !Ref MyPublicSecGrp01
IpProtocol: icmp
FromPort: 8
ToPort: -1
Tags:
- Key: Name
Value: My-Private-Security-Group-01
MyPublicSecGrp02:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow http to client host
VpcId: !Ref MyVPC
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 22
ToPort: 22
- CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 80
ToPort: 80
Tags:
- Key: Name
Value: My-Public-Security-Group-02
MyPrivateSecGrp02:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow Ingress trafic from Public Subnet
VpcId: !Ref MyVPC
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref MyPublicSecGrp02
IpProtocol: tcp
FromPort: 22
ToPort: 22
- SourceSecurityGroupId: !Ref MyPublicSecGrp02
IpProtocol: icmp
FromPort: 8
ToPort: -1
Tags:
- Key: Name
Value: My-Private-Security-Group-02
Outputs:
MyStackPublicSubnetID01:
Description: The ID of My Public Subnet for AzName01
Value: !Ref MyPublicSubnet01
Export:
Name: !Sub "${AWS::StackName}--PublicSubnetId01"
MyStackPrivateSubnetID01:
Description: The ID of My Private Subnet for AzName01
Value: !Ref MyPrivateSubnet01
Export:
Name: !Sub "${AWS::StackName}--PrivateSubnetId01"
MyStackPublicSubnetSecurityGroupID01:
Description: The ID of My Public Subnet Security Group for AzName01
Value: !Ref MyPublicSecGrp01
Export:
Name: !Sub "${AWS::StackName}--PublicSubnetSecGrpId01"
MyStackPrivateSubnetSecurityGroupID01:
Description: The ID of My Private Subnet Security Group for AzName01
Value: !Ref MyPrivateSecGrp01
Export:
Name: !Sub "${AWS::StackName}--PrivateSubnetSecGrpId01"
MyStackPublicSubnetID02:
Description: The ID of My Public Subnet for AzName02
Value: !Ref MyPublicSubnet02
Export:
Name: !Sub "${AWS::StackName}--PublicSubnetId02"
MyStackPrivateSubnetID02:
Description: The ID of My Private Subnet for AzName02
Value: !Ref MyPrivateSubnet02
Export:
Name: !Sub "${AWS::StackName}--PrivateSubnetId02"
MyStackPublicSubnetSecurityGroupID02:
Description: The ID of My Public Subnet Security Group for AzName02
Value: !Ref MyPublicSecGrp02
Export:
Name: !Sub "${AWS::StackName}--PublicSubnetSecGrpId02"
MyStackPrivateSubnetSecurityGroupID02:
Description: The ID of My Private Subnet Security Group for AzName02
Value: !Ref MyPrivateSecGrp02
Export:
Name: !Sub "${AWS::StackName}--PrivateSubnetSecGrpId02"
今回のサンプルコードの主なポイントは下記の部分になります。
- Parametersセクション
- 作成する環境に応じて、AZやCIDRアドレス範囲を指定可能にしました。ただし、東京リージョンにあるもののみが利用可能です。
- Resourcesセクション
- 作成するリソース(VPC、サブネット、インターネットゲートウェイ等)の構成を定義します。
- CloudFormationはリソースを並行して作成されるため、例えばサブネットやインターネットゲートウェイは必ずVPCの作成完了後に作成を開始する等の考慮が必要になります。その為、そのようなリソースの作成においては、DependsOn属性を指定する必要があります。
- Outputsセクション
- 各サブネットのIDとセキュリティー・グループのID情報を出力します。これらの情報は、別に作成しているEC2プロビジョニング用のCloudFormationのコード実行時に必要になります。(ネストスタックのスタディーがやりたく、敢えて本記事で紹介しているサンプルコードでは、EC2インスタンスのプロビジョニング部分はスコープ外としています。)
作成したサンプルコードの実行
AWSのマネジメントコンソールにログオンし、CloudFormationの「スタックの作成」の画面において、最初に今回のサンプルコードをアップロードします。その後、「スタックの詳細を指定」の画面において、スタック名等を入力していきます。(以下はサンプルです。)
-
パラメータ確認
下記のようにAZの名前や、パブリック・サブネット、プライベート・サブネット等のCIDRアドレス範囲等が表示されますので、確認します。アドレス範囲等はここで指定が可能です。
確認が終了したら画面右下の「次へ」ボタンを押下げします。その後に遷移した先の画面では特に何もせずに「次へ」ボタンを押下げします。 -
レビュー画面の確認
下記のようなパラメータ一覧が表示されますので、問題なければ右下の「送信」ボタンを押下げして、CloudFormationのコードを実行します。
-
コードの実行
下記画面のようにスタックの作成が開始されます。スタックのステータスが最終的に「CREATE_COMPLETE」になればOKです。
スタックの作成完了後のイメージは下記の通りです。
-
「出力」タブの確認
サンプルコードのOutputsセクションに指定した、サブネットIDやセキュリティー・グループID等の一覧が表示されます。
おわりに
今回は、CloudFormationを使用して、VPC環境を自動作成するサンプルコードを紹介しました。このVPC環境上にEC2をプロビジョニングするサンプルコードについては、また別の記事で紹介予定です。