延伸昨天的 Terraform 基礎,今天我們來談談 Terraform 的專案架構與組態管理。
Terraform 在初始化階段(terraform init
)會以目錄為單位匯入各種設定檔,並讀取該目錄下的 backend(儲存位置) 設定。因此,可以說 Terraform 管理資源的基本邏輯是——「一個目錄,就是一個 state(狀態) 的範圍」。
在管理多環境的 Terraform 專案時,清晰的目錄結構能有效劃分邏輯邊界,避免不同環境間的設定混淆或資源衝突。一般做法是為每個環境建立獨立的目錄,每個目錄內包含完整的 Terraform 配置檔。這樣的設計不僅讓專案結構直覺易懂,也方便 CI/CD 流程針對不同環境進行自動化部署。
範例結構:
infra/
├── prod/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ └── backend.tf
└── staging/
├── main.tf
├── variables.tf
├── outputs.tf
└── backend.tf
特點:
infra/prod
與 infra/staging
各自代表一個獨立的 Terraform 專案。
- State:Terraform 的 state 記錄資源的實際狀態,確保每次執行時 Terraform 能正確掌握目前的資源情況。
- Backend:定義 state 的儲存位置,可為本地檔案或遠端儲存(如 GCS、S3)。
.tf
的讀取邏輯目錄除了是劃分資源與狀態的基礎,也是terraform 機制的基礎,在同一個目錄底下,Terraform 不在乎檔案名稱,只要副檔名是 .tf
,都會被一併讀入並整合成同一份設定:
staging/
├── main.tf
├── network.tf
├── compute.tf
├── variables.tf
└── outputs.tf
Terraform 會將這些檔案內容「拼接」成完整設定,因此以下兩種結構結果相同:
# 單一檔案寫法
main.tf
# 拆檔寫法
main.tf
network.tf
compute.tf
拆分 .tf
檔案的目的只是為了維護可讀性與模組化結構,而非影響執行結果。
.tfvars
的搭配若設定中使用了變數(variable
),Terraform 會從以下來源讀取值:
-var-file
檔案,例如 terraform apply -var-file=staging.tfvars
terraform.tfvars
或 *.auto.tfvars
-var
參數這樣可以透過 tfvars
區分環境設定,而不必複製整份 .tf
檔案。
範例:建立一個 GCP bucket
infra/
├── main.tf
├── variables.tf
└── staging.tfvars
variables.tf
variable "project_id" {
description = "GCP 專案 ID"
type = string
}
variable "bucket_name" {
description = "要建立的儲存桶名稱"
type = string
}
variable "location" {
description = "GCP 區域"
type = string
default = "asia-southeast1"
}
main.tf
provider "google" {
project = var.project_id
region = var.location
}
resource "google_storage_bucket" "example" {
name = var.bucket_name
location = var.location
force_destroy = true
}
staging.tfvars
project_id = "my-staging-project"
bucket_name = "staging-data-bucket"
location = "asia-east1"
執行:
terraform apply -var-file="staging.tfvars"
若要切換到其他環境,只需建立另一份 prod.tfvars
並指定即可。
拆分 .tf
檔案後,我們可以進一步透過模組化設計,把共用資源抽象出來:
module/
├── vpc/
├── gce/
├── loadbalancer/
└── ...
在不同環境中引用:
staging/
└── main.tf
prod/
└── main.tf
範例引用模組:
module "prod_vpc" {
source = "../module/vpc"
env = "prod"
}
Terraform 作為宣告式組態語言,有一套固定的**組態區塊(Configuration Blocks)**語法,每個區塊負責不同的功能。官方文件提供完整參考,常用的區塊類型包括:
provider
:定義與雲端平台或服務的連線設定。resource
:宣告要建立、修改或刪除的資源。variable
:定義可配置的參數。terraform
:包含全域設定,尤其用於指定 backend
等 state 管理。範例:
terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "prod"
}
}
provider "google" {
project = var.project_id
region = var.region
}
variable "project_id" {
description = "GCP 專案 ID"
type = string
}
resource "google_storage_bucket" "example" {
name = var.bucket_name
location = var.region
force_destroy = true
}
每個區塊都有其語法結構與作用範圍,組合起來形成完整的 Terraform 設定。
透過前面的介紹,相信你已經對部屬一組服務有大致的概念。回到開頭所說:Terraform 管理資源的核心邏輯是——「一個目錄,就是一個 state 的範圍」。
State(狀態)記錄了 Terraform 所管理的資源的實際情況,相當於資源的快照,確保每次操作都基於最新狀態。Terraform 透過 backend(後端儲存位置)來保存 state,支援本地或遠端集中管理,並在每次執行時讀取,以維持環境一致性與操作安全性。
因此,狀態管理是 Terraform 使用的核心之一。
在本地開發時,每個目錄會自動將對應服務的 state 儲存在該目錄下。然而,若將 state 檔案直接上傳至 GitHub 或其他版本控制系統,會帶來以下問題:
解決方式是指定一個固定且集中管理的儲存位置,例如雲端儲存服務(GCS、S3 等)。對於多資源、多環境的專案而言,state 儲存與目錄設計需要謹慎規劃,以確保環境隔離、協作順暢以及資源管理一致性。
好的,我幫你補上示意圖說明,讓「本地 state vs 遠端 backend」的差異更直觀。文字版示意如下,可直接放入教學文件:
1️⃣ 本地 state (Local)
infra/
├── staging/
│ ├── main.tf
│ └── terraform.tfstate <-- 本地儲存
└── prod/
├── main.tf
└── terraform.tfstate <-- 本地儲存
特點:
- 每個目錄各自管理自己的 state
- 適合單人開發或測試環境
- 多人協作容易衝突
2️⃣ 遠端 state (Backend)
infra/
├── staging/
│ └── main.tf
└── prod/
└── main.tf
Backend (GCS / S3 / Terraform Cloud / etc.)
└── terraform.tfstate <-- 集中管理
特點:
- State 統一存放在遠端儲存
- 多人協作安全可靠
- 支援鎖定(state locking),避免衝突
- 適合多環境、多資源專案
💡 小結:
- 本地 state:簡單、快速,但協作困難
- 遠端 backend:初期設定稍複雜,但適合團隊與多環境管理,推薦在生產環境使用
在系列文中,並未提供從零開始一步步部屬服務的「Hello World」式教程,原因是篇幅有限。重點放在透過概念與實作經驗,理解 Terraform 的運作邏輯與最佳實踐。
對於 Terraform,大多數教程都要求使用雲端服務(如 GCP、AWS 等)進行練習。但在官方教程中,也提供了一種利用 Docker 的方式。雖然較抽象,但從概念上來說,container 就是最小的虛擬化環境,透過 Docker 在本機運行,就可以模擬雲端環境進行 Terraform 練習,對於不方便申請雲端帳號或資源的使用者,是一個很好的替代方案。
官方教程連結:Terraform Docker Tutorial
範例設定如下:
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
}
}
}
provider "docker" {} # 在雲端情境下可替換成 GCP 或 AWS provider
resource "docker_image" "nginx" { # 對應雲端時為作業系統映像
name = "nginx:latest"
keep_locally = false
}
resource "docker_container" "nginx" { # 對應雲端時為 VM(GCE/EC2)
image = docker_image.nginx.image_id
name = "tutorial"
ports {
internal = 80
external = 8000
}
}
這個練習可以讓你在本地環境就能完整體驗 Terraform 的工作流程:初始化、計畫、套用與管理資源,而無需實際操作雲端平台。完成後,你對於多環境管理、state、backend 與模組化設計的概念都能更有感。
今天介紹了 Terraform 的檔案架構、狀態管理與練習方式,幫助建立多環境管理與模組化設計的基礎概念。
內容:
目錄與 State
多檔案讀取與模組化
.tf
檔案會被整合成單一設定,不影響執行結果。組態區塊(Configuration Blocks)
provider
、resource
、variable
、terraform
(backend)。狀態管理(State & Backend)
練習方式
今天我們聚焦於組態區塊、目錄結構與狀態管理等核心細節。在 Terraform 的世界中,每個資源都是一份設定檔,目錄則用來分組管理,就像 Linux 的「everything is a file」理念。掌握這種結構化管理,能讓多環境專案更清晰、模組化設計更可靠,也為狀態管理與協作打下穩固基礎。
期望透過今天的內容,大家能熟悉 Terraform 模組化與目錄管理的實務操作。
謝謝大家的閱讀,我們明天見!