[小ネタ]「!Cidr」というチョット便利なCloudFormationの組み込み関数

CloudFormationの中で勝手にネットワークアドレスを計算してくれる「!Cidr」というチョット便利なCloudFormationの組み込み関数を触ってみました!
2020.02.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。大阪オフィスの林です。

!Cidrというチョット便利なCloudFormationの組み込み関数を使ってみたので備忘でまとめておきたいと思います。

!Cidrとは

!CidrとはCIDRアドレスブロックの配列を返すCloudFormationの組み込み関数です。少々分かり辛いと思いますので早速やっていきます。なお!Cidrは短縮形の構文で、完全名関数の構文ではFn::Cidrで記述します。今回サンプルのコードでは短縮形構文の!Cidrを使っていきます。詳細はこちらをご確認ください。

やってみた

!Cidr実装前のコード

組み込み関数を使っていないコードを見てみましょう。Subnetを作成している部分で5つのサブネット(CidrBlock: 192.168.0.0/27 - CidrBlock: 192.168.0.128/27)をハードコートしています。このコードを別環境で使用する場合、ハードコートしている部分を書き換えてあげる必要があります。別環境で使用するときにサブネットマスクに応じたネットワークアドレスを調べるのも手間ですよね。

(省略)

# ------------------------------------------------------------#
#  Subnet
# ------------------------------------------------------------#
  Subnet01:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: 192.168.0.0/27
      Tags:
        - Key: Name
          Value: subnet01
  Subnet02:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1c
      CidrBlock: 192.168.0.32/27
      Tags:
        - Key: Name
          Value: subnet02
  Subnet03:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: 192.168.0.64/27
      Tags:
        - Key: Name
          Value: subnet03
  Subnet04:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1c
      CidrBlock: 192.168.0.96/27
      Tags:
        - Key: Name
          Value: subnet04
  Subnet05:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: 192.168.0.128/27
      Tags:
        - Key: Name
          Value: subnet05

!Cidr実装後のコード

今回!Cidrと併せてVPCで使用するCIDRをInputparameterとして渡すよう実装しています。

AWSTemplateFormatVersion: '2010-09-09'
Description: "BaseNetwork Create by Classmethod"
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      -
        Parameters:
          - CidrBlock
Parameters:
  CidrBlock:
    Description: Please type the CidrBlock.
    Type: String
    Default: 192.168.0.0/16
Resources:
# ------------------------------------------------------------#
#  VPC
# ------------------------------------------------------------#
  VPC:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: !Sub ${CidrBlock}
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      Tags:
        - Key: Name
          Value: test-vpc

!Cidrを使ったコードはここからです。
例えばCidrBlock: !Select [ 0, !Cidr [ !GetAtt VPC.CidrBlock, 1, 8 ]]というように記述することで、VPCが持っているネットワークアドレスを元にサブネット用に指定したネットワークアドレスを計算させてCidrBlockのパラメータに入れています。自身でサブネットマスクに応じたネットワークアドレスを調べなくていい点も便利な点と言えます。各種パラメータの説明は後述します。

# ------------------------------------------------------------#
#  Subnet
# ------------------------------------------------------------#
  Subnet01:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: !Select [ 0, !Cidr [ !GetAtt VPC.CidrBlock, 1, 7 ]]
      Tags:
        - Key: Name
          Value: subnet01
  Subnet02:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1c
      CidrBlock: !Select [ 1, !Cidr [ !GetAtt VPC.CidrBlock, 2, 7 ]]
      Tags:
        - Key: Name
          Value: subnet02
  Subnet03:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: !Select [ 2, !Cidr [ !GetAtt VPC.CidrBlock, 3, 7 ]]
      Tags:
        - Key: Name
          Value: subnet03
  Subnet04:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1c
      CidrBlock: !Select [ 3, !Cidr [ !GetAtt VPC.CidrBlock, 4, 7 ]]
      Tags:
        - Key: Name
          Value: subnet04
  Subnet05:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: !Select [ 4, !Cidr [ !GetAtt VPC.CidrBlock, 5, 7 ]]
      Tags:
        - Key: Name
          Value: subnet05

!Cidrを使わない場合と、使った場合とで結果的にデプロイされる環境は同じでも、サブネットマスクに応じたネットワークアドレスを調べたり、他の環境で使うときの汎用性の高さなどを考えると!Cidrを使った方がメリットが多いのではないかと思っています。

!Cidrのパラメータと配列データの関係

ここで簡単に!Cidrの各種パラメータの説明をしておきたと思います。 !select!Cidrを併用する場合は4つのパラメータを指定する必要があります。下図は!select!Cidrを併用した際に指定するパラメータの一例です。

① 取り出すデータの番地を指定

配列に格納された何番目のデータを取り出すか指定します。配列は「0」から始まるので1つ目のデータを取り出したい場合は「0」と指定し、3番目のデータを取り出したい場合は「2」と指定します。

② 元データを指定

配列に格納される元データを指定します。

③ 作成する配列データの数を指定

何個の配列データを作成するかを指定します。

④ サブネットビットを指定

CIDRのビット数を指定します。サブネットビットはサブネットマスクの逆です。例えば/24を指定したい場合は、8ビットの8を指定し、/27を指定したい場合は、5ビットの5を指定します。

まとめ

ミニマムな環境であればちょこちょこっと書き換えてあげればいいですがそれもそれで手間ですよね。特にサブネットマスクが変わるとネットワークアドレスの指定があってるか確認するのも面倒くさいですよね。そんな方に是非参考になればと思います。
使ってないけど便利なパラメータや関数がまだまだありそうなので調べながら触っていければと思います!

以上、大阪オフィスの林がお送りしました!