クラウド エンジニアブログ

[ゼロから始めるInfrastructure as Code] 第2回 パラメータ参照方法

2023年2月8日掲載

始めに

クラウドインテグレーション課 クラウドエンジニアの濱田です。 「ゼロから始めるInfrastructure as Code」、第2回目です。

前回はVPCを1つだけ作成するシンプルなテンプレートを記述しました。 今回は、その中にサブネットを作っていきたいと思います。

まずは考えてみる

前回の「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テンプレートの書き方

  1. 必須セクションを書く
  2. 作成したいリソースの、Typeの書き方を調べる
  3. 必要なプロパティを調べる
    • まずは必須のものを書く
    • 必要に応じて設定値を追加する
  4. リソースがどんな戻り値を用意しているか把握する
    • 他のリソースを作るとき、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は、リソース作成の順番を自分で判断してくれるのですが、ものによっては順番を判断できず、前のリソースが作成されていないのに、次のリソースを作ろうとします。

※ 参考: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html#gatewayattachment

今回の場合、「ルートが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

以上で第二回は終了です。 次回もお楽しみに! クラウドエンジニアの濱田でした!

関連コラム

このコラムに関連する製品

このコラムに関連する
導入事例

このコラムに関連する
セミナー・イベント

[ゼロから始めるInfrastructure as Code] 第2回 パラメータ参照方法

SHARE
シェアシェア ポストポスト
[ゼロから始めるInfrastructure as Code] 第2回 パラメータ参照方法
SHARE
ポスト シェア