ข้ามไปยังเนื้อหา

Terraform Workspaces

Terraform workspace ทำให้ configuration เดียวสร้าง state file แยกกันได้หลายอันโดยสลับด้วยชื่อ แต่ทุก workspace ยังรันผ่าน backend เดียวกัน provider configuration เดียวกัน และโค้ด .tf เดียวกันเป๊ะ

แทนที่จะ copy-paste ทั้ง directory ต่อ environment workspace ให้คุณเก็บชุดไฟล์ .tf ไว้ชุดเดียว แล้วแค่สลับว่า Terraform จะอ่านและเขียน state file ชื่อไหน

Terminal window
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
terraform workspace list
# default
# * dev
# staging
# prod
terraform workspace select staging
terraform apply

terraform workspace new <name> สร้าง workspace แล้วสลับไปใช้ทันที terraform workspace select <name> สลับ workspace ที่ active อยู่โดยไม่สร้างใหม่ terraform workspace list แสดง workspace ทั้งหมดที่มีอยู่ พร้อมเครื่องหมาย asterisk บอกว่าตัวไหน active อยู่ workspace ที่ active ถูก track ไว้ในเครื่องของคุณเองที่ directory .terraform และทุก plan หรือ apply ที่คุณรันจะแตะแค่ state ของ workspace นั้นเท่านั้น state ของ dev กับ state ของ prod คือคนละไฟล์กันเลย ถึงแม้ทั้งคู่จะมาจาก main.tf เดียวกัน

Terraform expose ชื่อ workspace ที่ active อยู่เป็นค่า built-in ชื่อ terraform.workspace ซึ่งคุณ interpolate เข้าไปในชื่อ resource, label, หรือ lookup map ได้โดยตรง เพื่อเปลี่ยน behavior ต่อ workspace โดยไม่ต้องเขียนโค้ดแยกกันสำหรับแต่ละอัน

locals {
machine_types = {
dev = "e2-small"
staging = "e2-medium"
prod = "e2-standard-4"
}
}
resource "google_compute_instance" "app" {
name = "app-${terraform.workspace}"
machine_type = lookup(local.machine_types, terraform.workspace, "e2-small")
zone = "us-central1-a"
boot_disk {
initialize_params {
image = "debian-cloud/debian-12"
}
}
}

สลับไปที่ workspace prod แล้ว resource block เดียวกันนี้จะตั้งชื่อ instance เป็น app-prod และเลือกขนาดเป็น e2-standard-4 สลับไปที่ dev แล้วโค้ดเดียวกันเป๊ะจะได้ app-dev ขนาด e2-small ไม่มีอะไรในไฟล์ .tf เองเปลี่ยนระหว่าง environment เลย มีแค่ workspace ที่ active เท่านั้นที่เปลี่ยน

ตรงนี้คือจุดที่พลาดง่าย block backend, block provider "google", และโค้ด .tf ทุกบรรทัดที่เหลือ ถูกใช้ร่วมกันโดยไม่เปลี่ยนเลยข้ามทุก workspace

terraform {
backend "gcs" {
bucket = "acme-terraform-state"
prefix = "app"
}
}
provider "google" {
project = "acme-shared-project"
region = "us-central1"
}

Terraform จัดการแยก state object ของแต่ละ workspace ไว้ในเครื่องเดียวกันโดยอัตโนมัติ ทำให้ dev, staging, prod ไม่ทับ state file กันเอง แต่ bucket เอง, project ใน block provider "google", และ credential ที่ Terraform ใช้ authenticate เหมือนกันเป๊ะไม่ว่า workspace ไหนจะ active อยู่ ตรงนี้ไม่มี boundary แข็ง ๆ เลยสักนิด ไม่มีอะไรกันไม่ให้คนที่อยู่ใน workspace dev คิดว่ากำลังจะแก้ instance ทดสอบที่ทิ้งได้ ทั้งที่จริง ๆ ทุก workspace ใช้ GCP project acme-shared-project เดียวกันและ resource ที่ใกล้เคียง prod จริงที่อยู่ในนั้นร่วมกัน การเลือก terraform workspace select ผิดตามด้วย apply คือความผิดพลาดที่เกิดขึ้นได้ง่ายมาก และ workspace เองไม่มีทางป้องกันให้คุณเลย

flowchart TD
  config["Single main.tf + backend + provider google.project = acme-shared-project"]
  config -->|terraform workspace select dev| devState["dev state file"]
  config -->|terraform workspace select staging| stagingState["staging state file"]
  config -->|terraform workspace select prod| prodState["prod state file"]
  devState -.->|same backend, same project| shared["acme-shared-project"]
  stagingState -.->|same backend, same project| shared
  prodState -.->|same backend, same project| shared
One Terraform configuration and backend, three workspaces, three state files, one shared GCP project
Terraform workspace ให้สิ่งที่แยกกันจริงคืออะไร
terraform.workspace มักถูกใช้ทำอะไร
ความเสี่ยงจริงในโลกจริงที่ Terraform workspace สร้างขึ้นมาโดยเฉพาะคืออะไร
สิ่งไหนที่เหมือนกันเป๊ะข้ามทุก workspace ใน configuration เดียว