너도 할 수 있어! CloudFormation 템플릿 세션 자세히 알아보기 (2)

2022.04.06

안녕하세요, 임채정입니다.
제가 처음에 CloudFormation 템플릿을 작성할 때 도대체 이 코드는 어떤 코드인지 몰라서 한참 헤맸던 것 같습니다.
그래서 이번 블로그에서는 CloudFormation 템플릿을 처음 작성하시는 분이 쉽게 이해하실 수 있도록 CloudFormation 템플릿의 세션에 대해 정리해보려고 합니다!

해당 블로그는 총 2개로 나눠져있습니다.
해당 블로그에서 소개하지 않은 CloudFormation 템플릿 세션에 대해 알고싶은 분들은 이전 블로그를 참고해주세요.

아젠다

  1. Rules
  2. Mappings
  3. Conditions
  4. Transform
  5. 마무리

1. Rules

스택을 생성하거나 업데이트할 때 템플릿에 전달된 파라미터 또는 파라미터의 조합을 검증합니다.
규칙 섹션은 리소스를 생성하거나 업데이트하기 전에 파라미터 값을 검증합니다.

규칙세션에서는 해당 함수를 사용합니다.

  • Fn::And
  • Fn::Contains
  • Fn::EachMemberEquals
  • Fn::EachMemberIn
  • Fn::Equals
  • Fn::If
  • Fn::Not
  • Fn::Or
  • Fn::RefAll
  • Fn::ValueOf
  • Fn::ValueOfAll

rules-test.yaml

AWSTemplateFormatVersion: '2010-09-09'

Rules:
  devInstanceType:
    RuleCondition: !Equals 
      - !Ref Environment
      - dev
    Assertions:
      - Assert:
          'Fn::Contains':
            - - t2.medium
            - !Ref InstanceType
        AssertDescription: 'instance type must be t2.medium'
  prdInstanceType:
    RuleCondition: !Equals 
      - !Ref Environment
      - prd
    Assertions:
      - Assert:
          'Fn::Contains':
            - - t2.large
            - !Ref InstanceType
        AssertDescription: 'instance type must be t2.large'

...

해당 예시는 2개의 인스턴스의 인스턴스 타입으로 정의된 파라미터 값을 검증합니다.
즉, dev 인스턴스는 t2.medium 이고, prd 인스턴스는 t2.large 인것을 확인합니다.

2. Mappings

매핑 세션에서는 키와 명명된 값을 세트로 정의합니다.
예를 들어 리전 이름을 키로 하여 구체적인 지역별로 필요한 값을 지정하는 것으로 사용합니다.
또한, 매핑 세션에서 정의한 값을 취득하려면 Fn::FindInMap 삽입 함수를 사용해야 합니다.

mappings-test.yaml

AWSTemplateFormatVersion: "2010-09-09"

# ------------
# Mappings
# ------------
Mappings: 
  RegionMap: 
    us-east-1:
      HVM64: ami-0fxxxxxxxxxxxxx54
    us-east-2:
      HVM64: ami-0bxxxxxxxxxxxxx34
    ap-northeast-1:
      HVM64: ami-06xxxxxxxxxxxxx32
    ap-northeast-2:
      HVM64: ami-08xxxxxxxxxxxxx51

# ------------
# Resources
# ------------
Resources: 
  EC2Instance: 
    Type: "AWS::EC2::Instance"
    Properties: 
      ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", HVM64]
      ...

메핑 세션에서 각 리전의 이름을 키로, AMI를 값으로 정의했습니다.
그리고 리소스에서 불러올때는 예제의 24번 줄과 같이 작성합니다.

해당 코드의 의미는 다음과 같습니다.
1) Mappings 세션 중에 RegionMap 그룹에서
2) 현재 Cfn을 실행하는 리전의 키에 맞는
3) HVM64에 정의된 값을 가지고 옵니다.

3. Conditions

조건 (Conditions) 세션에서는 조건 함수를 통해 리소스의 생성 또는 구성된 환경을 정의하는 문이 포함됩니다.
예를 들어 조건을 생성해서 조건이 true인 경우 AWS CloudFormation에서 리소스 또는 출력을 생성하도록 할 수 있습니다.
또는 조건을 속성에 연결하여 조건이 true인 경우 AWS CloudFormation에서 속성을 특정 값으로 설정, false인 경우 AWS CloudFormation에서 다른 값으로 설정가능합니다.

조건생성을 위해 해당 함수를 사용합니다.

  • Fn::And
  • Fn::Equals
  • Fn::If
  • Fn::Not
  • Fn::Or

conditions-test.yaml

AWSTemplateFormatVersion: '2010-09-09'

# ------------
# Conditions
# ------------
Conditions:
    isAccount: !Equals [!Ref "AWS::AccountId", 67xxxxxxxxxx]
 
# ------------
# Resources
# ------------
Resources:
    vpc:
        Type: AWS::ec2::VPC
        Properties:
            CidrBlock: 10.0.0.0/16
            EnableDnsHostnames: true
            EnableDnsSupport: true
            Tags:
                - Key: Name
                  Value: !Sub Conditions-vpc
        Condtion: isAccount

해당 예시는 해당 계정ID가 Cfn을 실행하는 계정ID와 일치할 때 리소스를 생성합니다.

4. Transform

변환(Transform) 세션은 AWS CloudFormation이 템플릿 처리를 위해 사용하는 매크로를 1개 이상 지정합니다.
AWS CloudFormation에서는 지정된 순서에 따라 매크로를 실행합니다.

transform-test.yaml

AWSTemplateFormatVersion: '2010-09-09'
  
# Transform for Description
Fn::Transform:
	Name: AWS::Include
	Parameters:
		Location: description.yaml
  
# ------------
# Resources
# ------------
Resources:
	# Transform for Resources
	Fn::Transform:
		Name: AWS::Include
		Parameters:
			Location: bucket1.yaml
  
	Bucket2:
		Type: AWS::S3::Bucket
		Properties:
			BucketName: !Sub  Backet2-${AWS::AccountId}
			# Transform for tags
			Fn::Transform:
				Name: AWS::Include
				Parameters:
					Location: tags.yaml

다음 transform-test.yaml 파일의 TransformLocation 의 파일에 해당 부분을 적어줍니다.

description.yaml

Description: 'Test Transform'

bucket1.yaml

Backet1:
	Type: AWS::S3::Bucket
	Properties:
		BucketName: !Sub  Backet1-${AWS::AccountId}
		AccessControl: Private
		PublicAccessBlockConfiguration:
		BlockPublicAcls: True
		BlockPublicPolicy: True
		IgnorePublicAcls: True
		RestrictPublicBuckets: True
	Tags:
		- Key: Name
		  Value: Bucket1

tags.yaml

Tags:
	- Key: Name
	  Value: Bucket2

그러면 템플릿을 패키지화 했을 때 다음과 같이 변경됩니다.

package.yaml

AWSTemplateFormatVersion: '2010-09-09'
Fn::Transform:
	Name: AWS::Include
	Parameters:
		Location: s3://<S3name>/5011e6xxxxxxxxxxxxxxxxxxxxxxxxx
Resources:
	Fn::Transform:
		Name: AWS::Include
		Parameters:
			Location: s3://<S3name>/4fbdc0xxxxxxxxxxxxxxxxxxxxxxxxx
	Bucket2:
		Type: AWS::S3::Bucket
		Properties:
			BucketName: !Sub  Backet2-${AWS::AccountId}
			Fn::Transform:
				Name: AWS::Include
				Parameters:
					Location: s3://<S3name>/b7b7a3xxxxxxxxxxxxxxxxxxxxxxxxx

CloudFormation 의 패키지 방법 및 실행방법은 다음의 블로그를 참고해주세요.

5. 마무리

이번 블로그에서는 CloudFormation 템플릿의 세션에 대해 정리를 해봤습니다.
특히 저번 블로그에서 정리했던 것보다 더 복잡하고 어려운 세션에 대해 정리했으니 CloudFormation 를 작성하시는 분들에게 도움이 되셨으면 좋겠습니다.

본 블로그 게시글을 보시고 문의 사항이 있으신 분들은 클래스메소드코리아 (info@classmethod.kr)로 연락 주시면 빠른 시일 내 담당자가 회신 드릴 수 있도록 하겠습니다 !