はじめに
最近AWSを始めたので、勉強がてらCloudFormationを用いてEC2の構築を行いました。
CloudFormationについて
CloudFormationはAWS内のインフラリソースを自動でプロビジョニングできるサービスです。
プロビジョニングしたいAWSリソースをコード(テンプレート)として記述し、目的のインフラ(スタック)を構築するというのがCloudFormationの流れになります。
(プロビジョニング : ネットワークやコンピューターリソースを準備すること)
参考:https://aws.amazon.com/jp/cloudformation/features/
インフラ構成図
インフラ構成は非常に単純で下図にようになります。
VPCは東京リージョンに作成し、パブリックサブネットはap-northeast-1aに作成しています。
EC2へのアクセスは指定した固定IPからのSSH, HTTPアクセスのみ許可しています。
EC2から外部へのアクセスは全て許可しています。
テンプレート記述の基本構文
テンプレートはJSONまたはYAML形式で記述することができ、今回はYAML形式で記述しています。
テンプレートの基本構文は以下のようになります。
# テンプレート形式のバージョン
AWSTemplateFormatVersion:
# テンプレートに関する記述
Description:
# 入力パラメータ
Parameters:
# 構築するリソースの記述
Resources:
# 出力パラメータ
Outputs:
AWSTemplateFormatVersion
CloudFormationのテンプレート形式のバージョンで、2010-09-09が現時点での最新バージョンです。
2010-09-09が最新
Description
テンプレートの内容に関する記述です。
Parameters
記述したリソースに対し、パラメータを入力値として与えたい場合に記述します。
ここに記述したパラメータはテンプレートからスタックを作成する際に入力値として与えることになります。
Resources
構築したいAWSのリソースを記述します。
Outputs
ここに記述したパラメータはスタックの作成が終わったときに出力値として得られます。
リソース記述の基本構文
# リソースの論理名
(ResourceName):
# リソースタイプ
Type:
# リソースのプロパティ
Properties:
リソースの論理名
テンプレート内でのリソース名を記述します。
Type
リソースのタイプを指定します。
リソースタイプの参考:
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html
Properties
リソースのプロパティを指定します。
テンプレート解説
AWSTemplateFormatVersion: "2010-09-09"
Description: Provision EC2
テンプレートファイルの始めに形式のバージョンとテンプレート内容を記述しています。
Parameters:
KeyName:
Description: The EC2 Key Pair to allow SSH access to the instance
Type: "AWS::EC2::KeyPair::KeyName"
MyIP:
Description: IP address allowed to access EC2
Type: String
次に、EC2へのアクセスのキーペア名とアクセス可能なIPアドレスを入力パラメータとして設定しています。このように記述することで、テンプレートファイル内にキーペア名、IPアドレスを直接書く必要がなくなります。
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: vpc-cf
IGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: igw-cf
# IGWをVPCにアタッチ
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref IGW
ここからResourcesの記述になります。
まず記述内容は順にVPCの作成、インターネットゲートウェイ(IGW)の作成、IGWをVPCにアタッチとなります。
リソースのTags属性でNameタグを作成しています。
またAttachGatewayのプロパティVpcId, InternetGatewayIdにはそれぞれVPC, IGWのIDを指定する必要があるのですが、テンプレートの組み込み関数Refを用いることでリソースの論理名からIDを取得しています。
!Refは組み込み関数Refの短縮表記です。
組み込み関数Refについて:
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html
PubSub:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
Tags:
- Key: Name
Value: pub-sub-a-cf
PubSubRT:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: pub-sub-a-rt-cf
# PubSub-インターネット間のルーティング
PubSubToInternet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PubSubRT
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IGW
# ルートテーブルをサブネットに関連付け
AssoPubSubRT:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PubSub
RouteTableId: !Ref PubSubRT
次はパブリックサブネットの作成です。
1番目のリソースで先ほど作成したVPC内にサブネットを作成しています。
2番目以降のリソースではそれぞれ、ルーティングテーブルの作成、パブリックサブネット-インターネット間のルートの作成、ルートテーブルのパブリックサブネットへの関連付けを行っています。
EC2:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-00d101850e971728d
KeyName: !Ref KeyName
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId: !Ref PubSub
GroupSet:
- !Ref EC2SG
UserData: !Base64 |
#!/bin/bash
sudo yum install -y git
Tags:
- Key: Name
Value: ec2-a-cf
次にEC2インスタンスの作成です。
EC2のAMIにはAmazon linux2を選択しています。今回は東京リージョンを選択していますが、リージョンが変わるとAMIのIDも変わるので、適宜変更する必要があります。テンプレート構文のMappingを使うことでリージョンについて条件判定を行った上で適切なAMIのIDを記述できるようです。
Mappingの利用:
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/gettingstarted.templatebasics.html
(ページ中程)
EC2にはパブリックIPを自動で割り振ります。
その場合ネットワークインターフェースはデバイスインデックスが0である必要があるのでNetworkInterfaces下の設定を行っています。
EC2のパブリックIP自動割り振りについて:
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html
UserDataに記述した内容はインスタンスの作成時に実行されるので、プログラムのインストールなど初期設定を行うことができます。
何もしないのは寂しいのでgitをインストールしています。
UserData属性にはBase64エンコードされたテキストを渡す必要があるので、組み込み関数!Base64を使用しています。
(!Base64は入力文字列のBase64表現を返します。)
EC2SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: ec2-sg-cf
GroupDescription: Allow SSH and HTTP access only MyIP
VpcId: !Ref VPC
SecurityGroupIngress:
# http
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref MyIP
# ssh
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref MyIP
次にEC2インスタンスのセキュリティーブループを記述しています。
自分のIPアドレスからのみHTTP, SSH接続を許可しています。
Outputs:
EC2PublicIP:
Value: !GetAtt EC2.PublicIp
Description: Public IP of EC2 instance
最後に出力パラメータを記述しています。
スタックの作成
AWSにログインし、サービスメニューからCloudFormationのページに移ります。
次にCloudFormationページ内の"スタックの作成"ボタンをクリックすると次のような画面に移ります。
テンプレートの選択項目のテンプレートをAmazon S3にアップロードを選択し、テンプレートファイルを選択して次へをクリックします。
詳細指定の画面に移ります。テンプレートファイルのParametersに記述したパラメータをここで指定することができます。
次のページはタグやアクセス権限のページです。必要ならば入力して次の確認ページに進み、問題がなければ作成ボタンをクリックします。
終わりに
- テンプレートファイルのParametersやOutputsで入力パラメータや出力パラメータを設定できるのは非常に便利でした。いろいろと有効活用ができそう。
- サブネットのルーティングの設定の部分はややコードが煩雑になってしまったので、もっと良い記述方法を探していきたいと思います。
- 構築したスタック内のリソースを一括で削除できるのはすごく楽です。
参考
AWS CloudFormation公式ドキュメント
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/Welcome.html