【AWS】CloudFormationで、定番のネットワーク構成を作成してみた
CloudFormationとは
簡単に言うと、AWSインフラをコードで実装できる仕組みのことです。
AWSマネジメントコンソールを使ってポチポチやっている操作を、コード化できるものです。
コードと聞くと尻込みしてしまいますが、慣れてくるとこっちのほうがAWSインフラを早く作成できるようになると思います(まだそこまで使いこなせていませんが、多分..)。
今回作成する範囲
以下の構成図に従って作成していきます。
構成図の作成には、VS CodeのプラグインであるDraw.io Integrationを使用しました。
よくありがちなネットワーク構成と、EC2インスタンスを1つ作るところまでを実装してみました。
雛形
VS CodeのCloudFormationプラグインを使って作成しました。
AWSTemplateFormatVersion: 2010-09-09
Resources:
雛形としては、いろんな要素が生成されますが、
今回は、Resources:セクションの配下に記載していきます。
他の要素は削除しておきます。
今回はYAML形式で記述しており、インデントを付けています。
まずはVPCの作成から
testVPC
という名前で、10.0.0.0/16
の大きいネットワークを作成します。
testVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
Tags:
- Key: Name
Value: testVPC
サブネットの作成
次に、4つのサブネットをType: AWS::EC2::Subnet
で作成します。
内訳は、2つのパブリックサブネットと2つのプライベートサブネットです。
パブリックサブネット:10.0.0.0/24
と10.0.2.0/24
プライベートサブネット:10.0.0.0/24
と10.0.2.0/24
それぞれのサブネットは、先ほど作成したtestVPC
に所属させたいので、VpcId:
で参照させます。参照には!Ref
という文字列を指定します。
publicsubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
VpcId: !Ref testVPC
CidrBlock: 10.0.0.0/24
Tags:
- Key: Name
Value: publicsubnet01
publicsubnet02:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1c
VpcId: !Ref testVPC
CidrBlock: 10.0.2.0/24
Tags:
- Key: Name
Value: publicsubnet02
privatesubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
VpcId: !Ref testVPC
CidrBlock: 10.0.1.0/24
Tags:
- Key: Name
Value: privatesubnet01
privatesubnet02:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1c
VpcId: !Ref testVPC
CidrBlock: 10.0.3.0/24
Tags:
- Key: Name
Value: privatesubnet02
インターネットゲートウェイの作成
インターネットゲートウェイを作成するには、Type: AWS::EC2::InternetGateway
を指定します。
igwCF:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: CFigw
インターネットゲートウェイをVPCへアタッチ
インターネットゲートウェイはVPCにアタッチ(関連付け)しないと使えませんので、Type: AWS::EC2::VPCGatewayAttachment
でアタッチします。
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref testVPC
InternetGatewayId: !Ref igwCF
ルートテーブルの作成
パブリックサブネット用のルートテーブルをType: AWS::EC2::RouteTable
で作成します。
routepublicsubnet:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref testVPC
Tags:
- Key: Name
Value: rt-publicsubnet
インターネットへ抜けられるようにするためのルートをType: AWS::EC2::Route
で作成します。ルートテーブルへのアタッチはRouteTableId:
で指定します。
routePublic:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref routepublicsubnet
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref igwCF
ルートテーブルへサブネットを関連付ける
Type: AWS::EC2::SubnetRouteTableAssociation
で、インターネットへ抜けられるサブネットを指定します。
今回は、2つのパブリックサブネットのみインターネットへ抜けられるようにしたいので、サブネットをSubnetId:
で、ルートテーブルをRouteTableId:
で指定します。
routeTableAssocPublic01:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref publicsubnet01
RouteTableId: !Ref routepublicsubnet
routeTableAssocPublic02:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref publicsubnet02
RouteTableId: !Ref routepublicsubnet
EC2用セキュリティグループの作成
ここまでで、ネットワークがひととおり作成できました。
次は、そのうちの1つのパブリックサブネットにEC2インスタンスを作成します。
まず、EC2用のセキュリティグループを作成します。セキュリティグループとはEC2インスタンス用のファイアウォールのようなものです。
セキュリティグループは、AWS::EC2::SecurityGroup
で作成します。
Webサーバを想定して、httpと管理用のSSHのみを許可するセキュリティグループを作成しまう。
SecGroupPublic:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: GroupName-SG
GroupDescription: SecGroupPublic
VpcId: !Ref testVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: SecGroupPublic
EC2の作成
最後にEC2インスタンスの作成です。
インスタンスタイプはInstanceType:
でt3.micro、イメージはImageId:
でAmazon Linuxを指定しました。
publicEC2Instance:
Type: AWS::EC2::Instance
Properties:
KeyName: KeyPair-210816
DisableApiTermination: false
ImageId: ami-09ebacdc178ae23b7
InstanceType: t3.micro
Monitoring: false
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId: !Ref publicsubnet01
GroupSet:
- !Ref SecGroupPublic
Tags:
- Key: Name
Value: publicEC2Instance
ここで悩んだのが、パブリックIPアドレスの割り当て方法でした。
公式ドキュメントを見ましたが、どうも分かりにくい..結局ググりまくって、以下の部分を発見しました。
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
動作確認
最終的に出来上がったCloudFormationテンプレートです。
AWSTemplateFormatVersion: 2010-09-09
Resources:
testVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
Tags:
- Key: Name
Value: testVPC
publicsubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
VpcId: !Ref testVPC
CidrBlock: 10.0.0.0/24
Tags:
- Key: Name
Value: publicsubnet01
publicsubnet02:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1c
VpcId: !Ref testVPC
CidrBlock: 10.0.2.0/24
Tags:
- Key: Name
Value: publicsubnet02
privatesubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
VpcId: !Ref testVPC
CidrBlock: 10.0.1.0/24
Tags:
- Key: Name
Value: privatesubnet01
privatesubnet02:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1c
VpcId: !Ref testVPC
CidrBlock: 10.0.3.0/24
Tags:
- Key: Name
Value: privatesubnet02
igwCF:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: CFigw
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref testVPC
InternetGatewayId: !Ref igwCF
routepublicsubnet:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref testVPC
Tags:
- Key: Name
Value: rt-publicsubnet
routePublic:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref routepublicsubnet
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref igwCF
routeTableAssocPublic01:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref publicsubnet01
RouteTableId: !Ref routepublicsubnet
routeTableAssocPublic02:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref publicsubnet02
RouteTableId: !Ref routepublicsubnet
SecGroupPublic:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: GroupName-SG
GroupDescription: SecGroupPublic
VpcId: !Ref testVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
#EC2
publicEC2Instance:
Type: AWS::EC2::Instance
Properties:
KeyName: KeyPair-210816
DisableApiTermination: false
ImageId: ami-09ebacdc178ae23b7
InstanceType: t3.micro
Monitoring: false
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId: !Ref publicsubnet01
GroupSet:
- !Ref SecGroupPublic
Tags:
- Key: Name
Value: publicEC2Instance
これをAWSマネジメントコンソールのCloudFormationから以下の手順で読み込ませて、動作確認します。
- AWSマネジメントコンソールからCloudFormationの画面を開く。
-
スタックの作成
ボタンをクリック - テンプレートの準備は、
テンプレートの準備完了
を選択 - テンプレートの指定は、
テンプレートファイルのアップロード
を選択 -
ファイルを選択
から先ほど作成したYAMLファイルを指定 - 次へを選択
- スタックの名前を入力し、
次へ
- スタックオプションの設定と詳細オプションはデフォルトのままで
次へ
-
スタックの作成
をクリック - イベントタブで、作成したスタックのステータスが
CREATE_COMPLETE
になったことを確認する。
- AWSマネジメントコンソールでVPCの画面に移動して、VPC、サブネット、インターネットゲートウェイ、ルートテーブルが作成されていることを確認する。
- AWSマネジメントコンソールでEC2の画面に移動して、EC2インスタンスが作成されていることを確認する。
- 最後に、Tera Termで、作成したEC2インスタンスにSSHでログインできることを確認する。
確認が終わったら、課金を防ぐためAWSマネジメントコンソールのCloudFormation画面から、先ほど作成したスタックを削除しておきます。
AWSマネジメントコンソールで作成すると、それぞれの画面でリソースを削除する必要があります(しかも消す順番にも決まりあり)が、CloudFormationだとスタックを削除すれば、順番も考慮して全てやってくれるので楽ですね!
次はEC2のAuto Scalingを試してみようと思います。
以上
Discussion