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

[ゼロから始める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

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

関連コラム

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

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

このコラムに関連する
セミナーアーカイブ動画

AWS Ambassador Presents トレンド技術を語り尽くせ! 第1回 「Infrastructure as Code」

SHARE
シェアシェア ポストポスト
AWS Ambassador Presents トレンド技術を語り尽くせ! 第1回 「Infrastructure as Code」
SHARE
ポスト シェア