まずは考えてみる
前回の「CloudFormationテンプレートの書き方」通りに考えましょう。
-
- 必須セクションを書く
- 作成したいリソースの、Typeの書き方を調べる
- 必要なプロパティを調べる
- 必須セクションを書く CloudFormationは、以下の2行を書くところから始まります。
AWSTemplateFormatVersion: "2010-09-09" Resources:
- 作成したいリソースの、Typeの書き方を調べる 公式リファレンスの、サブネットのページを見てみましょう。
Type: AWS::EC2::Subnet、と書けばいいようです。AWSTemplateFormatVersion: "2010-09-09" Resources: Subnet: Type: AWS::EC2::Subnet
- 必要なプロパティを調べる まずは必須のプロパティを確認しましょう。 意外にも、VpcIdのみという事が分かります。 つまり、最低限以下を書けば動くという事ですね。
AWSTemplateFormatVersion: "2010-09-09" Resources: Subnet: Type: AWS::EC2::Subnet Properties: VpcId: vpc-xxxxxx
次に、必要に応じて設定値を追加します。 サブネットなので、CidrBlockと、AvailabilityZoneくらいは設定したいですね。 こんな感じでしょうか。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
Subnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
CidrBlock: 192.168.0.0/24
VpcId: vpc-xxxxxx
これでバッチリです! 上記をファイルに保存して、CFnで実行すれば、事前に作ったVPC内にサブネットを作成できます。
・・・ところで、VPCとサブネットを別々に作る機会ってそんなにありますか? 前述の書き方だと、事前にVpcIdが分かっていないとサブネットを作れません。 1枚のテンプレート内でVPCを作って、VPC IDを参照しつつ、サブネットを作れたら便利ですよね。
もちろん、出来ます!
組み込み関数を使って、パラメータを参照する
組み込み関数を使うと、対象が持っているパラメータを参照できます。
※ 組み込み関数一覧: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
例えば、VPCに対して「Ref」を使ったとき、VPCはVpcIdを返すように作られています。
各リソースがRefで何を返すのかは、公式リファレンスの「戻り値」に記載されています。 VPCのリファレンスを見てみましょう。
以上から、次のように直してあげれば、1枚のテンプレートでVPCとサブネットを作ることが出来ます。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 192.168.0.0/16
Subnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
CidrBlock: 192.168.0.0/24
VpcId: !Ref Vpc # <-- !Ref 論理名 で参照できる
ところで、VPCは他にもCidrBlockなどのパラメータを持っています。 それらは「Fn::GetAtt」を使うことで参照出来ます。
!GetAtt Vpc.CidrBlock
テンプレートを書く時、各リソースが何を返して、どうやったら欲しいパラメータを参照できるのかを考える事が大切です。 というわけで、CloudFormationの書き方に、今日の項目を追加します。
CloudFormationテンプレートの書き方
- 必須セクションを書く
- 作成したいリソースの、Typeの書き方を調べる
- 必要なプロパティを調べる
- まずは必須のものを書く
- 必要に応じて設定値を追加する
- リソースがどんな戻り値を用意しているか把握する
- 他のリソースを作るとき、RefとGetAttのどちらで参照すべきか考える
課題
では、本日の課題です。
- 以下の要件を満たすテンプレートを記述して下さい
- 192.168.0.0/16のCidrを持つVPCを作成する
- 作成したVPC内に、以下セグメントのサブネットを作成する
- 192.168.0.0/24
- Internet Gatewayを作成し、VPCにアタッチする
- ルートテーブルを作成し、Subnetに関連付ける
- ルートテーブルに0.0.0.0/0 -> IGWのルートを書く
解説
こちらです
今回から一気に作成リソースが増えました。 とはいえ、「CloudFormationテンプレートの書き方」通りに一個ずつ調べていけば大丈夫だと思います。
ちょっと詰まりそうなのは、以下の2つでしょうか。
- Internet Gatewayを作成し、VPCにアタッチする
- ルートテーブルに0.0.0.0/0 -> IGWのルートを書く
「Internet Gatewayを作成し、VPCにアタッチする」について、問題はVPCへのアタッチですね。 IGW作成と同時のアタッチは出来ないので、別途「IGWをVPCにアタッチする」というリソースを定義する必要があります。 調べてみると、「Type: AWS::EC2::VPCGatewayAttachment」が該当します。
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: String
VpcId: String
「ルートテーブルに0.0.0.0/0 -> IGWのルートを書く」について、なんとCFnでは、ルートを1つ1つリソースとして定義しなければいけません。 行数が増えると、かなり大変ですね。
Type: AWS::EC2::Route
Properties:
RouteTableId: String
DestinationCidrBlock: String
GatewayId: String
実は、もう一つ落とし穴があります。 基本的にCloudFormationは、リソース作成の順番を自分で判断してくれるのですが、ものによっては順番を判断できず、前のリソースが作成されていないのに、次のリソースを作ろうとします。
今回の場合、「ルートがIGWを含む」に該当するので、 「IGWの作成が終わってからルートを作成する」 と書いてあげなければなりません。 方法は簡単です。 「Type: AWS::EC2::Route」のセクションに、「DependsOn: AttachGateway」と書きましょう。 これでAttachGatewayが終わってから、ルートの作成を始めます。
まとめると、以下が解答例です。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 192.168.0.0/16
InternetGW:
Type: AWS::EC2::InternetGateway
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref Vpc
InternetGatewayId: !Ref InternetGW
Subnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-1a
VpcId: !Ref VPC
CidrBlock: 192.168.0.0/24
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Route:
DependsOn: AttachGateway
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGW
AssociateRouteTable:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref Subnet
RouteTableId: !Ref RouteTable
以上で第二回は終了です。 次回もお楽しみに! クラウドエンジニアの濱田でした!