AWS CloudFormation 基礎架構即程式碼

AWS CloudFormation Infrastructure as Code

CloudFormation 概述

AWS CloudFormation 是 Amazon Web Services 提供的基礎架構即程式碼(Infrastructure as Code, IaC)服務。透過 CloudFormation,您可以使用範本檔案來定義和部署 AWS 資源,實現基礎架構的自動化管理。

為什麼選擇 CloudFormation?

  • 一致性:確保每次部署的環境都相同
  • 版本控制:範本可以納入 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::KeyNameEC2 金鑰對
AWS::EC2::VPC::IdVPC 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 前,務必先建立變更集預覽變更內容,避免意外刪除或替換資源。

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy