AWS CloudFormation 是 Amazon Web Services 提供的基礎架構即程式碼(Infrastructure as Code, IaC)服務。透過 CloudFormation,您可以使用範本檔案來定義和部署 AWS 資源,實現基礎架構的自動化管理。
- 一致性:確保每次部署的環境都相同
- 版本控制:範本可以納入 Git 進行版本管理
- 自動化:減少人工操作錯誤
- 可重複性:輕鬆複製相同的基礎架構到不同環境
- 依賴管理:自動處理資源之間的相依關係
範本結構(YAML/JSON)
CloudFormation 範本支援 YAML 和 JSON 兩種格式。以下是基本的範本結構:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| AWSTemplateFormatVersion: '2010-09-09'
Description: 範本描述說明
Parameters:
# 輸入參數定義
Mappings:
# 靜態變數對應
Conditions:
# 條件判斷
Resources:
# AWS 資源定義(必填)
Outputs:
# 輸出值定義
|
YAML vs JSON
YAML 格式較為簡潔易讀,是目前推薦的格式:
1
2
3
4
5
6
| # YAML 範例
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: my-example-bucket
|
1
2
3
4
5
6
7
8
9
10
| {
"Resources": {
"MyBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "my-example-bucket"
}
}
}
}
|
Parameters 參數設定
Parameters 允許您在建立 Stack 時傳入動態值,增加範本的靈活性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| Parameters:
EnvironmentType:
Description: 環境類型
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
ConstraintDescription: 必須是 dev、staging 或 prod
InstanceType:
Description: EC2 執行個體類型
Type: String
Default: t3.micro
AllowedValues:
- t3.micro
- t3.small
- t3.medium
KeyPairName:
Description: SSH 金鑰對名稱
Type: AWS::EC2::KeyPair::KeyName
|
常用參數類型
| 類型 | 說明 |
|---|
| String | 字串值 |
| Number | 數值 |
| List | 數值列表 |
| CommaDelimitedList | 逗號分隔的字串列表 |
| AWS::EC2::KeyPair::KeyName | EC2 金鑰對 |
| AWS::EC2::VPC::Id | VPC ID |
| AWS::EC2::Subnet::Id | 子網路 ID |
Resources 資源定義
Resources 是範本中唯一必填的區段,用於定義要建立的 AWS 資源:
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| Resources:
# VPC 定義
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentType}-vpc
# 公有子網路
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentType}-public-subnet
# EC2 執行個體
WebServer:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0abcdef1234567890
InstanceType: !Ref InstanceType
KeyName: !Ref KeyPairName
SubnetId: !Ref PublicSubnet
SecurityGroupIds:
- !Ref WebServerSecurityGroup
Tags:
- Key: Name
Value: !Sub ${EnvironmentType}-web-server
# 安全群組
WebServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Web Server Security Group
VpcId: !Ref MyVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
|
Outputs 輸出值
Outputs 用於匯出 Stack 建立後的重要資訊:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| Outputs:
VPCId:
Description: VPC ID
Value: !Ref MyVPC
Export:
Name: !Sub ${EnvironmentType}-VPCId
WebServerPublicIP:
Description: Web Server 公開 IP 位址
Value: !GetAtt WebServer.PublicIp
WebServerDNS:
Description: Web Server DNS 名稱
Value: !GetAtt WebServer.PublicDnsName
Export:
Name: !Sub ${EnvironmentType}-WebServerDNS
|
建立 Stack
您可以透過 AWS CLI 或 AWS Console 建立 Stack:
使用 AWS CLI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 建立 Stack
aws cloudformation create-stack \
--stack-name my-web-stack \
--template-body file://template.yaml \
--parameters \
ParameterKey=EnvironmentType,ParameterValue=dev \
ParameterKey=InstanceType,ParameterValue=t3.micro \
ParameterKey=KeyPairName,ParameterValue=my-key-pair
# 等待 Stack 建立完成
aws cloudformation wait stack-create-complete \
--stack-name my-web-stack
# 查看 Stack 狀態
aws cloudformation describe-stacks \
--stack-name my-web-stack
|
更新與刪除 Stack
更新 Stack
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 更新 Stack
aws cloudformation update-stack \
--stack-name my-web-stack \
--template-body file://template.yaml \
--parameters \
ParameterKey=EnvironmentType,ParameterValue=staging \
ParameterKey=InstanceType,ParameterValue=t3.small
# 使用變更集預覽變更
aws cloudformation create-change-set \
--stack-name my-web-stack \
--change-set-name my-changes \
--template-body file://template.yaml
# 執行變更集
aws cloudformation execute-change-set \
--stack-name my-web-stack \
--change-set-name my-changes
|
刪除 Stack
1
2
3
4
5
6
7
| # 刪除 Stack
aws cloudformation delete-stack \
--stack-name my-web-stack
# 等待刪除完成
aws cloudformation wait stack-delete-complete \
--stack-name my-web-stack
|
內建函數
CloudFormation 提供多種內建函數來處理動態值:
Ref 函數
引用參數或資源:
1
2
3
4
5
| # 引用參數
InstanceType: !Ref InstanceType
# 引用資源(返回資源 ID)
SubnetId: !Ref PublicSubnet
|
GetAtt 函數
取得資源的屬性值:
1
2
3
4
5
6
7
8
| # 取得 EC2 公開 IP
PublicIP: !GetAtt WebServer.PublicIp
# 取得 S3 Bucket ARN
BucketArn: !GetAtt MyBucket.Arn
# 取得 RDS 端點
DBEndpoint: !GetAtt MyDatabase.Endpoint.Address
|
Join 函數
連接字串:
1
2
3
4
5
6
7
8
| # 使用逗號連接
SecurityGroups: !Join
- ','
- - !Ref SG1
- !Ref SG2
- !Ref SG3
# 結果:sg-111,sg-222,sg-333
|
其他常用函數
1
2
3
4
5
6
7
8
9
10
11
| # Sub - 字串替換
Name: !Sub '${EnvironmentType}-${AWS::StackName}-bucket'
# Select - 從列表中選取
AZ: !Select [0, !GetAZs '']
# If - 條件判斷
InstanceType: !If [IsProd, t3.large, t3.micro]
# ImportValue - 匯入其他 Stack 的輸出值
VPCId: !ImportValue prod-VPCId
|
最佳實踐
1. 範本組織
- 將大型範本拆分成巢狀 Stack
- 使用有意義的資源邏輯名稱
- 加入適當的註解說明
2. 安全性
1
2
3
4
5
6
| # 避免硬編碼敏感資訊,使用 SSM Parameter Store
Parameters:
DBPassword:
Type: AWS::SSM::Parameter::Value<String>
Default: /myapp/db/password
NoEcho: true
|
3. 錯誤處理
1
2
3
4
5
| # 設定 DeletionPolicy 保護重要資源
MyDatabase:
Type: AWS::RDS::DBInstance
DeletionPolicy: Retain
UpdateReplacePolicy: Snapshot
|
4. 標籤管理
1
2
3
4
5
6
7
8
| # 統一標籤格式
Tags:
- Key: Environment
Value: !Ref EnvironmentType
- Key: Project
Value: MyProject
- Key: Owner
Value: DevOps Team
|
5. 使用變更集
在更新 Stack 前,務必先建立變更集預覽變更內容,避免意外刪除或替換資源。
參考資料