Study Notes - CloudFormation Template Anatomy


整理 CloudFormation 整理官方文件學習筆記,主要是 Template Anatomy (結構) 的整理。

CloudFormation 簡介

CloudFormation 主要用來將資源模組化 (model),然後可以快速配置新環境,節省時間,因為是透過文字描述檔 (Template),所以可以進 Source Control,達到版控的目的。文件提到有以下三個效益:

  • Simplify Infrastructure Management:簡化基礎建設資源的管理
  • Quickly Replicate Your Infrastructure:快速重建基礎建設資源
  • Easily Control and Track Changes to Your Infrastructure:更加容易管理和追蹤資源異動

名詞

以下是文件中常見的名詞,或者縮寫。

  • CFN: CloudFormation 的縮寫
  • Templates: 用 json or yaml 描述資源的文件,也是 CFN 最重要的部分
  • Stacks: 透過 Templates 的描述檔,產生的實體 (physical) 資源 (resources) 集合稱為 Stacks,這些資源可以是 EC2 Instances, RDS, EIP, VPC, Security Groups …. 等,幾乎支援 AWS 所有的資源。
  • ChangeSets: 針對已經建立的 Stacks 做異動,你可以讓 CFN 先產生一個 ChangeSets,他會把整個異動的結果顯示給你參考,告訴你可能產生的影響以及變動。
  • Resource Type: 定義 AWS 資源的類型,用 AWS::aws-product-name::data-type-name 表示資源,像是 EC2 Instance 是 AWS::EC2::Instance
  • Resource Properties: 描述每個 Resource Type 的屬性。

Working with Templates

CloudFormation Template 是用來描述資源的文件,支援 jsonyaml 兩種資料格式。我個人比較推薦 yaml,因為可讀性比 json 好很多,另外很重要的是:yaml 可以註解,json 不行。

我覺得 Template 可以算 Infra as Code 的 DSL (Domain-specific language),雖然他不是完整的 Programming Language,但已經具備 variables, functions / libraries, lambdas (Conditions) 等概念,甚至是 data type (custom resources)。

Templates 的設計有很多方式,以下是三種主要的方法:

  • 透過 AWS Console 上的視覺化工具:CloudFormation Designer 設計。
  • 使用官方提供的範例:Template SnippetsSample Templates
  • 利用 AWS CloudFormer,產生目前的 Infra 的 Template。他也是用 CFN 動態生出一台 EC2,上面跑了 RoR 的應用程式,過程當中需要給這個 Stack 一定的權限,他會讀取所有資源的資訊,一系列的問答之後,最後產生一個 Template 檔案。

Template Anatomy

一份 Template 結構 會有以下 Sections,其中只有 Resources 是必要的,其他都是 Optional:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
---
# Specifies the AWS CloudFormation template version that the template conforms to.
AWSTemplateFormatVersion: "version date"
Description:
# Provide additional information about the template.
Metadata:
# 指定 Template 的參數,把 Template 想像成程式的 Function,這個就是 Input。對應的有 Outputs
Parameters:
# 通常透過 Fn::FindInMap 找對應資料使用,像是不同 Region 的 AMI、或者資源等。
Mappings:
# 定義控制條件,建立資源時,可以參考控制條件,決定是否建立。例如環境是 Prod,則建立某一個資源。
Conditions:
# Serverless Application Model (AWS SAM) 新增的 Sections
Transform:
# 最主要的資源描述都在這個 Sections, 也是 Template 裡唯一必要的。
Resources:
# 輸出,將執行結果輸出。可以單純當作顯示,也可以給其他 Stack 使用。
Outputs:

Templates 的結構有很多東西,整理三個最重要的:Parameters、Resources、Outputs

Parameters Section

Parameters 是定義 Template 可以輸入哪一些參數,有點像程式的 Function 參數的宣告。

基本的 Syntax 如下:

1
2
3
4
Parameters:
ParameterLogicalID:
Type: DataType
ParameterProperty: value

ParameterLogicalID 表示參數名稱,有點像是變數名稱。

要注意的是,文件並沒有提到可以用哪一些字元,但實際上只能使用 [A-Z],不能有 - (dash) or _ (underline)。

Type 可以指定資料型態,基本的有 String, Number, List<Number>, CommaDelimitedListCommaDelimitedList 通常會用來指定環境,像是 "test,dev,prod" 這樣的內容。

Type 也可以指定 AWS 的資源型別 (AWS-specific parameter types),像是 特定的 EC2 instance id、Security Group Id … 也可以用 List 方式,讓使用者選擇。整理如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
AWS::EC2::AvailabilityZone::Name
AWS::EC2::Image::Id
AWS::EC2::Instance::Id
AWS::EC2::KeyPair::KeyName
AWS::EC2::SecurityGroup::GroupName
AWS::EC2::SecurityGroup::Id
AWS::EC2::Subnet::Id
AWS::EC2::Volume::Id
AWS::EC2::VPC::Id
AWS::Route53::HostedZone::Id
List<AWS::EC2::AvailabilityZone::Name>
List<AWS::EC2::Image::Id>
List<AWS::EC2::Instance::Id>
List<AWS::EC2::SecurityGroup::GroupName>
List<AWS::EC2::SecurityGroup::Id>
List<AWS::EC2::Subnet::Id>
List<AWS::EC2::Volume::Id>
List<AWS::EC2::VPC::Id>
List<AWS::Route53::HostedZone::Id>

ParameterProperty 有很多個選項,都是作為輸入條件篩選、限制、預設、說明、安全性隱藏 (像是密碼) … 等,條例如下:

  • AllowedPattern
  • AllowedValues
  • ConstraintDescription
  • Default
  • Description
  • MaxLength
  • MaxValue
  • MinLength
  • MinValue
  • NoEcho

Group and Sort Parameters in the AWS CloudFormation Console

Parameters 的清單預設使用 alphabetically 排序,如果想在 Console 做排序或者 Group,則可以透過 AWS::CloudFormation::Interface 調整。

AWS::CloudFormation::Interface

AWS CLI and API Support

參數可以透過 --parameters 傳遞,如下:

1
2
3
4
aws cloudformation create-stack \
--stack-name ${STACK_NAME} \
--template-body file://${TEMPLATE}
--parameters Param1=Value1,Param2=Value2,...

Resources Section

Resources 是 CFN 最主要的 Section,每個 Resource 由幾個 Fields 組成:

  • Logical ID: 使用者自訂名稱,只能使用 A-Za-z0-9,Template 使用此 ID 做為參考
  • Resource type: 主要參考 AWS Resource Types
  • Resource properties: 主要用來描述每個資源額外的屬性。每個 Resource Type 會有不同的 properties
1
2
3
4
5
Resources:
Logical ID:
Type: Resource type
Properties:
Set of properties

Outputs Section

Outputs 定義了哪一些產出的資源 (Resources):

  • 可以在 AWS CloudFormation Console 顯示
  • 可以給其他的 Stack 使用

Outputs 主要由以下 Fields 組成:

  • Logical ID: 顯示的 ID, 必須是 a-z, A-Z, 0-9
  • Description (optional)
  • Value (required): 通常是回傳 Physical ID,像是 EC2 Instance ID 可以用 {LogicalId}.InstanceID 取得
  • Export (optional): 給 cross stack 使用的 ID

格式如下:

1
2
3
4
5
6
Outputs:
Logical ID:
Description: Information about the value
Value: Value to return
Export:
Name: Value to export

其他工具 (Alternatives)

CloudFormation 是 AWS Infra as Code 的實踐,跟其他像是 Chef、Ansible、Puppet、Salt 是類似的東西。

但我覺得還是有差異的,其他的比較是針對 OS 上面的 Application 做自動化,CloudFormation 則是可以從 Network、Instance (VM) 提供 (Provisioning)、配置 (Configure Management),涵蓋層面廣泛很多,缺點就是:他是 AWS 自己的,無法跨其他 Cloud。

除了 CFN,還有其他很多類似的工具,以下整理知名的:

  • Terraform 是另一個類似 CloudFormation 的產品,可以跨不同的 Cloud,像是 AWS、Azure 等。
  • Ansible 也有 Cloud Module,可以做類似的事情,但不是那麼完整,他還是比較適合 Application Level 的 Deployment。
  • Chef / Puppet: 都比較適合應用程式的部署 (Deployment), 也可以做作業系統內部的程式 Provisioning.

我把 DevOps 分成幾個 Stages: Provisioning, Deployment, Configuration, Observation, Security.

CloudFormation 則是屬於 Provisioning、Configuration、Security,完成後再讓應用程式透過其他工具部署上去。

用 Container 的術語來說,我描述的 DevOps Stages 叫做 Orchestration,現在流行的有 K8S, Docker Swam, AWS ECS

Reference for CloudFormation

延伸閱讀

參考資料


留言