上一篇比較了 SQS、SNS 與 EventBridge,決定哪些工作需要排隊、通知或依事件內容分流。
當架構裡開始出現 VPC、ECS、資料庫、Queue 與 IAM Role 等等的服務,接下來可能會遇到另一個問題:開發環境設定好了,測試與正式環境要再手動建立一次嗎?
只靠 Console 操作,第一套環境基本上不難建立,麻煩的是後續不同環境的設定逐漸不一致、修改原因沒有留下紀錄,需要重建時才發現操作文件漏了步驟等等。
這篇會先介紹 Infrastructure as Code(IaC,基礎設施即程式碼),再用同一份 CloudFormation 範本建立兩個 Stack,模擬開發與測試環境,觀察如何管理設定差異,以及如何在更新前確認影響範圍。
使用 IaC 時,我們會將資源與設定寫進檔案,再交給工具建立或更新,例如描述「需要一個 SQS Queue,Visibility Timeout 設成 60 秒」,工具就會依設定處理資源。
將檔案放進 Git 後,團隊可以比較版本、審查修改,並留下變更原因,同一份定義也能重複部署,減少每次手動建立時的遺漏,不過使用同一份範本,不代表所有環境的設定都必須相同。
正式環境可能需要更多運算資源、更長的資料保留時間,這類設定差異可以透過參數管理,讓不同環境共用資源定義;若環境的架構差異較大,則需要進一步規劃範本的拆分與重用方式。
先釐清兩個容易混淆的服務 CloudFormation 與 CDK。
CloudFormation 讓我們直接使用 YAML/JSON 描述 AWS 資源,再由 CloudFormation 服務負責部署。
AWS CDK 則使用 TypeScript、Python 等程式語言定義資源,一般部署流程會先產生 CloudFormation 範本,再交給 CloudFormation 執行。
例如建立 SQS Queue,直接撰寫 CloudFormation 時,資源定義會是:
OrderEmailQueue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: 60
CDK 的 TypeScript 程式碼片段則可以寫成:
new sqs.Queue(this, 'OrderEmailQueue', {
visibilityTimeout: Duration.seconds(60),
});
這是放在 CDK Stack 裡的程式碼片段,完整程式還需要匯入對應套件。
sqs.Queue用來定義佇列,this指向目前的 Stack,Duration.seconds(60)則代表 60 秒。
兩者可以建立相同資源,差別在於如何撰寫與組合設定,當每個 Queue 都需要搭配死信佇列、告警與固定標籤時,CDK 可以將整組設定封裝成共用元件,讓團隊重複使用。
再加入 Terraform,可以從以下幾個方向比較:
| 工具 | 撰寫與部署方式 | 部署狀態管理 | 適合優先評估的情況 |
|---|---|---|---|
| CloudFormation | YAML/JSON 直接交由 AWS 部署 | AWS 管理 Stack 狀態 | 主要使用 AWS,希望直接檢視資源設定 |
| AWS CDK | 程式碼產生 CloudFormation 範本後部署 | 一般部署由 CloudFormation 管理 | 團隊熟悉程式開發,需要組合與重用資源元件 |
| Terraform | 使用 HCL,透過 Provider 操作資源 | 團隊需安排 State 的儲存、權限與鎖定,也可採用託管方案 | 已有 Terraform 工具鏈,或需要整合不同平台 |
Terraform 的 State(狀態) 會記錄設定與實際資源的對應關係;Provider 則負責與 AWS 等平台的 API 互動。
CloudFormation 的 Stack 狀態由 AWS 管理,但團隊仍需負責部署權限與變更審查。
選工具時,也要看團隊的維護經驗,若已有成熟 Terraform Module 與部署流程,就不需要只因為新專案在 AWS 上而換工具。
這次選 CloudFormation,是因為只需要一個簡單資源,能直接從 Console 上傳範本,集中觀察參數與變更管理 ,CDK 的元件封裝與 Terraform 的工具鏈設定,這次都先不展開。
這次在同一個 AWS 帳號、東京 Region(ap-northeast-1)中,建立兩個獨立的 Stack,分別模擬開發與測試環境:
| 項目 | 開發環境 | 測試環境 |
|---|---|---|
| Stack 名稱 | day24-dev |
day24-test |
| 範本 | 同一份 day24-sqs.yaml |
同一份 day24-sqs.yaml |
| 初始 Visibility Timeout | 60 秒 | 90 秒 |
| 更新後 | 120 秒 | 維持 90 秒 |
Stack(堆疊) 是 CloudFormation 管理的一組資源,本次每個 Stack 都只建立自己的 SQS Queue,用來示範設定管理,並非完整的應用程式環境。
上述秒數只用來辨識設定差異,不是不同環境的建議值。
全程使用本機文字編輯器與 AWS Console,不需要 EC2 或 CloudShell,登入身分須具備 CloudFormation Stack、Change Set 與 SQS 資源的操作權限,Console 上傳範本也需要相應的 S3 權限。
在電腦上建立 day24-sqs.yaml,貼入以下內容並儲存:
AWSTemplateFormatVersion: '2010-09-09'
Description: SQS queue for the Day 24 multi-environment demo
Parameters:
VisibilityTimeoutSeconds:
Type: Number
Default: 60
MinValue: 0
MaxValue: 43200
Description: Queue visibility timeout in seconds
Resources:
OrderEmailQueue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: !Ref VisibilityTimeoutSeconds
SqsManagedSseEnabled: true
Outputs:
QueueUrl:
Description: URL of the queue created by this stack
Value: !Ref OrderEmailQueue
這份範本分成三個部分:
| 區塊 | 用途 |
|---|---|
Parameters |
部署時可以輸入的設定,本次是 Visibility Timeout |
Resources |
要建立的資源,本次是一個 SQS Queue |
Outputs |
部署後顯示的資訊,本次是 Queue URL |
!Ref VisibilityTimeoutSeconds 會取得輸入的參數值,!Ref OrderEmailQueue 則會取得這個 Queue 的 URL。
OrderEmailQueue 是範本內的 Logical ID(邏輯識別碼),這裡沒有指定 QueueName,CloudFormation 會自動產生實際名稱,因此兩個 Stack 可以使用相同範本,各自建立不同的 Queue。
SqsManagedSseEnabled: true 則明確指定使用 SQS 管理的伺服器端加密。
進入 CloudFormation → Stacks → Create stack → With new resources (standard),確認 Region 為東京。
day24-sqs.yaml,點選 Next。day24-dev。VisibilityTimeoutSeconds 輸入 60。若公司要求使用指定的 CloudFormation service role,請依既有規範選取;未指定時,CloudFormation 會使用依目前登入身分權限取得的暫時憑證操作資源。

上傳後,CloudFormation 會將範本存放到帳號內的 S3 Bucket,並顯示 S3 URL,建議先記下這個 URL,方便實作結束後找到並清理範本檔案,因為刪除 Stack 不會一併刪除這個檔案。

等待 Stack 狀態變成 CREATE_COMPLETE,如果失敗的話請查看 Events → Status reason,確認原因。
接著重複相同步驟,上傳同一份檔案,但改成:
day24-test
VisibilityTimeoutSeconds:90
兩個 Stack 完成後,各自開啟 Resources 頁籤,找到 OrderEmailQueue 對應的 Physical ID(實體識別碼),再前往同一 Region 的 SQS Console 查看資源。
預期會看到兩個不同的 Queue:
| 所屬 Stack | SQS Visibility Timeout |
|---|---|
day24-dev |
60 秒,或顯示為 1 分鐘 |
day24-test |
90 秒,或顯示為 1 分 30 秒 |
也可以在各 Stack 的 Outputs 頁籤取得 Queue URL,確認兩者對應不同資源。


到這裡可以發現共同的資源定義只有一份,環境差異由建立 Stack 時輸入的參數決定。
假設開發環境的消費者需要更長時間處理訊息,為了減少工作尚未完成、訊息就重新變成可見狀態的情況,這次將 Visibility Timeout 調整成 120 秒。
Visibility Timeout 不會限制程式執行時間,也不能完全避免 Standard Queue 的重複傳遞;消費者仍需具備冪等性。
回到 CloudFormation → day24-dev:
increase-visibility-timeout。VisibilityTimeoutSeconds 改成 120;若勾選了 Use existing value,先取消。Change Set(變更集) 用來預覽這次部署預計新增、修改或刪除哪些資源,建立完成後先不要執行,查看 Changes。
本次預期結果如下,請以實際產生的 Change Set 核對:
| 檢查項目 | 預期結果 |
|---|---|
| 資源 | OrderEmailQueue |
| Action | Modify |
| Replacement | False,不需要替換 Queue |
| 修改的屬性 | VisibilityTimeout,由參數值 60 調整為 120 |
更新前要一起確認受影響的資源、修改的屬性與 Replacement 判定,若出現預期以外的新增、刪除或替換,先釐清原因,再執行 Change Set。

VisibilityTimeout 支援原地更新,因此這次預期不需要重建 Queue。
此時實際 Queue 應維持 60 秒,Change Set 建立完成,只代表預覽完成,尚未套用修改。
確認內容正確後,選擇 Execute change set,依畫面確認執行。
等待 day24-dev 的狀態變成 UPDATE_COMPLETE,再回到 SQS 重新整理。若仍看到舊設定,稍候再確認。
預期結果如下:
| 檢查項目 | day24-dev |
day24-test |
|---|---|---|
| Visibility Timeout | 120 秒 | 維持 90 秒 |
| Queue URL | 與更新前相同 | 與更新前相同 |
| 是否被本次更新影響 | 是 | 否 |


這次只更新 day24-dev,所以即使兩個 Stack 使用同一份範本,CloudFormation 也不會自動把修改同步到另一個 Stack,如果同一項修改需要套用到多個環境,仍要安排各環境的部署順序與審核流程。
另外這次透過 Console 修改參數,本機 YAML 並沒有改變,Git 也不會自動記錄這次參數調整。
CloudFormation 中可以查看 Stack 目前的參數與部署事件,但這和程式碼版本管理是兩件事,正式使用時,應將各環境的非機密參數與範本一併納入版本管理,並讓部署流程讀取這些設定,才能審查與追蹤完整的環境差異。
測試完成後,到 CloudFormation 分別刪除 day24-dev 與 day24-test,並確認兩個 Queue 都已移除,本次沒有設定保留規則,因此刪除 Stack 時會刪除 Queue,裡面的訊息也會一併刪除。
最後可依先前記下的 S3 URL,刪除本次上傳的範本檔案。
部署前仍要確認 AWS 帳號、Region 與 Stack,避免將正確的設定套用到錯誤的環境。
如果有人直接到 Console 修改資源,實際設定就可能與範本產生 Drift(漂移),CloudFormation 能偵測支援範圍內的差異,團隊仍需判斷要將修改納入程式碼,或恢復原本設定。
另外,範本能重新建立資料庫或 Queue,不等於能還原原本的資料,要恢復完整服務,還需要準備外部相依設定、機密取得方式,以及資料備份與還原流程。
基礎設施可以透過程式碼部署之後,接下來要處理的是應用程式的新版本。
下一篇會比較滾動部署、藍綠部署與漸進式發布,看看如何控制上線影響,以及出問題時該怎麼退回。