Cloudformationのテンプレートに使える関数をまとめてみました ( 1 )

2021.12.21

こんにちは、イムチェジョンです。
最近、Cloudformationの作成をしています。
作成するときに関数を使ったらもっと簡単に作成できたので、作成しながら役に立った関数についてまとめたいと思います。
関数が多いので、今回のブログは2つに分けて作成します。
今回にまとめる関数は下のアジェンダで確認できます。

Cloudformationのテンプレートに使える関数をまとめてみました (2)

アジェンダ

  1. Fn::Base64
  2. Fn::Cidr
  3. 条件関数
  4. Fn::FindInMap
  5. Fn::GetAtt
  6. Fn::GetAZs

1. Fn::Base64

関数の定義

  • Fn::Base64 組み込み関数は入力文字列のBase64表示を返却
  • 一般的に UserData 属性でエンコードされたデータをAmazon EC2インスタンスに伝達するのに使用

  • パラメータ

    • valueToEncode
      • Base64に変換する文字列の値
  • 戻り値
    • Base64で表示された元の文字列

使い方

Fn::Base64: valueToEncode
!Base64 valueToEncode

EC2インスタンスのuserdata属性でエンコードされたデータをAmazon EC2インスタンスに伝達するとき

#〜省略〜
DevAnsibleEC2:
	Type: AWS::EC2::Instance
	Properties:
		ImageId: !Ref AMIIDAnsible
		InstanceType: !Ref InstanceTypeAnsible
		DisableApiTermination: true
		IamInstanceProfile: !Ref ManagementEC2Profile
		BlockDeviceMappings:
			- DeviceName: "/dev/xvda"
				Ebs:
					VolumeType: gp2
					VolumeSize: 8
		KeyName: !Ref KeyName
		Monitoring: false
		UserData: !Base64 |
			#! /bin/bash
			yum update
			yum install git
			yum install ansible
#〜省略〜

2. Fn::Cidr

関数の定義

  • 組み込み関数Fn::CidrはCIDRアドレスブロックのArrayを返す
  • 返されたCIDRブロックの数はcountパラメータによって異なる。

  • パラメータ

    • ipBlock
      • 小さいCIDRブロックに分割されるユーザー指定CIDRアドレスブロック
    • count
      • 生成するCIDRの数
      • 有効な範囲は1~256
    • cidrBits
      • CIDRに対するサブネットビット数
      • 例えば、このパラメータに対する値として「8」を指定すると、「/24」マスクのCIDRが生成
  • 戻り値
    • CIDRアドレスブロックのArray

使い方

Fn::Cidr: 
  - ipBlock 
  - count
  - cidrBits

!Cidr [ ipBlock, count, cidrBits ]

OUTPUTとしてVPCのCIDR(192.168.0.0/16)を基準に10つサブネットマスクが「/24」の CIDRを出力

#〜省略〜
Resources:  
	VPC:  
		Type: AWS::EC2::VPC  
		Properties:  
			CidrBlock:  192.168.0.0/16
			nableDnsSupport:  true  
			EnableDnsHostnames:  true  

Outputs:  
	Subnets:  
		Description:  Output Fn::Cidr
		Value:  !Join  [  ":",  !Cidr  [  192.168.0.0/16,  10,  8  ]  ]

3. 条件関数

関数の定義

  • 条件関数を使用してスタックリソースを条件付きで生成
  • スタックの生成やアップデート時に宣言する入力パラメータを基準に、この条件を評価

Fn::And

  • Fn::AndはAND演算子の役割
  • 含められる最小条件数は2、最大値は10
  • パラメータ
    • condition
      • true または falseに評価される条件
Fn::And: [condition]
!And [condition]

Fn::Equals

  • 二つの値が同じかどうかを比較
  • 二つの値が同じであれば trueを返還、違うと falseを返還
  • パラメータ
    • value
      • 比較しようとするタイプの値
Fn::Equals: [value_1, value_2]
!Equals [value_1, value_2]

Fn::If

  • 指定された条件が true と評価された場合は特定の値を返還し、指定された条件が false と評価された場合は他の値を返還
  • パラメータ
    • condition_name
      • 条件セクションの条件について参照
      • 条件名を使用して条件を参照
    • value_if_true
      • 指定された条件が trueと評価される場合に返還される値
    • value_if_false
      • 指定された条件が falseと評価される場合に返還される値
Fn::If: [condition_name, value_if_true, value_if_false]
!If [condition_name, value_if_true, value_if_false]

Fn::Not

  • Fn::NotはNOT演算子の役割
  • falseと評価される条件について trueを返還、 trueと評価される条件について falseを返還
  • パラメータ
    • condition
      • Fn::Equals または trueに評価される条件
Fn::Not: [condition]
!Not [condition]

Fn::Or

  • Fn::OrはOR演算子の役割
  • 指定された全ての条件の中で一つでもtrueと評価されるとtrueが返還、条件すべてがfalseと評価される場合、falseが返還
  • 含められる最小条件数は2、最大値は10
  • パラメータ
    • condition
      • true または falseに評価される条件
Fn::Or: [condition, ...]
!Or [condition, ...]

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  Env:
    Type: String
    Default: prod
    AllowedValues:
      - dev
      - prod
    Description: environment name. (dev or prod)
  Scope:
    Type: String
    Default: public
    AllowedValues:
      - public
      - private
  EC2Role:
    Type: String
    Description: enter the ec2 role name.
  KeyPair:
    Type: AWS::EC2::KeyPair::KeyName
    Description: KeyPair Name
Conditions:
  IsProduction: !Equals [!Ref Env, "prod"]
  IsEC2Role: !Not [!Equals [!Ref EC2Role, ""]]
  IsPublic: !Equals [!Ref Scope, "public"]
  ProdAndPub: !And [!Equals [!Ref Env, "prod"], !Equals [!Ref Scope, "public"]]
  ProdOrPub: !Or [!Equals [!Ref Env, "prod"], !Equals [!Ref Scope, "public"]]

Resources:
  EC2instance:
    Type: AWS::EC2::Instance
    Condition: IsPublic
    Properties:
      ImageId: ami-00000000
      InstanceType: !If [IsProduction, "t2.micro", "t2.nano"]
      IamInstanceProfile: !If [IsEC2Role, !Ref EC2Role, !Ref "AWS::NoValue"]
      BlockDeviceMappings:
        - DeviceName: '/dev/xvda'
          Ebs:
            VolumeType: 'gp2'
            VolumeSize: 10
      KeyName: !Ref KeyPair
      Tags:
      -
        Key: Name
        Value: !Sub "${AWS::StackName}-${Env}-${Scope}"
        
Outputs:
  ProdAndPub:
    Value: !If [ProdAndPub, true, false]
  ProdOrPub:
    Value: !If [ProdOrPub, true, false]

4. Fn::FindInMap

関数の定義

  • Fn::FindInMap 組み込み関数は Mappings セクションで宣言された2 レベルマップのキーに該当する値を返還

  • パラメータ

    • MapName
      • キーおよび値が含まれたマッピングセクションで宣言されたマッピングの論理名
    • TopLevelKey
      • 最上位キー名
      • この値はキと値のペアのリスト
    • SecondLevelKey
      • TopLevelKeyに割りあてられたリストのキーのうちの一つに設定された2番目のレベルキーの名前です。
  • 戻り値
    • SecondLevelKeyに割りあてられた値

使い方

Fn::FindInMap: [ MapName, TopLevelKey, SecondLevelKey ]
!FindInMap [ MapName, TopLevelKey, SecondLevelKey ]

Mappingsに設定されているCIDRの値をFn::FindInMapを利用してリソースに指定

#〜省略〜
Mappings:
	SubnetConfig: 
		VPC: 
			CIDR: '10.0.0.0/16' 
		PublicOne: 
			CIDR: '10.0.0.0/24' 
		PublicTwo: 
			CIDR: '10.0.1.0/24' 
		PrivateOne: 
			CIDR: '10.0.100.0/24' 
		PrivateTwo: 
			CIDR: '10.0.101.0/24'

Resources: 
	VPC: 
		Type: AWS::EC2::VPC 
		Properties: 
			EnableDnsSupport: true 
			EnableDnsHostnames: true 
			CidrBlock: !FindInMap [SubnetConfig, VPC, CIDR]

	PublicSubnetOne: 
		Type: AWS::EC2::Subnet 
		Properties: 
		#〜省略〜
		CidrBlock: !FindInMap [SubnetConfig, PublicOne, CIDR] 
		
#〜省略〜

5. Fn::GetAtt

関数の定義

  • Fn::GetAtt 組み込み関数はテンプレートのリソースから属性値を返す

  • パラメータ

    • logicalNameOfResource
      • 希望する属性を含むリソースの論理名 (論理的IDともいう)
    • attributeName
      • 必要としている値のある、リソース固有の属性の名前
  • 戻り値
    • 属性値

使い方

Fn::GetAtt: [ logicalNameOfResource, attributeName ]
!GetAtt logicalNameOfResource.attributeName

rdsのIAM RoleのArnの値をRDSインスタンスに設定

#〜省略〜
# ------------
# RDS IAM Role
# ------------
RDSRole:
	Type: "AWS::IAM::Role"
	Properties:
		AssumeRolePolicyDocument:
			Version: "2012-10-17"
			Statement:
				- Effect: "Allow"
					Principal:
						Service:
							- "monitoring.rds.amazonaws.com"
					Action:
						- "sts:AssumeRole"
		ManagedPolicyArns:
			- "arn:aws:iam::aws:policy/service-role/AmazonRDSMonitoringRole"
		Path: "/"
		RoleName: rds-monitoring-role

#〜省略〜

# ------------
# PostgreSQL Instance
# ------------
PostgreSQLDBInstance1:
	Type: "AWS::RDS::DBInstance"
	Properties:
		AutoMinorVersionUpgrade: false
		AvailabilityZone: "ap-northeast-1a"
		#〜省略〜
		MonitoringInterval: 60
		MonitoringRoleArn: !GetAtt RDSRole.Arn
		Engine: aurora-postgresql
		EngineVersion: "11.11"
		EnablePerformanceInsights: True
#〜省略〜

6. Fn::GetAZs

関数の定義Fn::GetAZs

  • Fn::GetAZs 関数は、指定されたリージョンのAZをアルファベット順に並べるArrayを返す
  • お客様が他のAZにアクセスできるため、テンプレート作成者はFn::GetAZs関数を使用して呼び出すユーザーのアクセス権限によって調整されるテンプレートを作成

  • パラメータ

    • AZを読み込むリージョンの名前の空文字列を指定すると、「AWS::Region」と指定するようになる
  • 戻り値
    • リージョンのAZの一覧

使い方

Fn::GetAZs: region
!GetAZs region

Public SubnetにAZを指定するとき

#〜省略〜
# -----
# Public Subnet
# -----
publicSubnet:
	Type: AWS::EC2::Subnet
	Properties:
		AvailabilityZone: !Select [ 0, !GetAZs  '' ]
		CidrBlock: !Select [0, !Cidr [!GetAtt  vpc.CidrBlock, 2, 8]]
		VpcId: 10.0.0.0/16
		Tags:
			- Key: Name
			  Value: public-subnet
#〜省略〜