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

Terraform Workspaces

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

ทุก Terraform configuration เริ่มต้นด้วย workspace เดียวชื่อ default สร้างและสลับไปมาระหว่าง workspace ที่ตั้งชื่อเพิ่มได้ด้วยสามคำสั่งนี้

Terminal window
# Create a new workspace and switch to it immediately
terraform workspace new dev
# List every workspace; the active one is marked with an asterisk
terraform workspace list
# default
# * dev
# staging
# prod
# Switch to an existing workspace
terraform workspace select staging

แต่ละ workspace ได้ state file ของตัวเอง แต่ทุก workspace ยังอ่านไฟล์ .tf ชุดเดียวกันเป๊ะ และชี้ไปที่ backend configuration เดียวกันเป๊ะ สั่ง terraform plan ใน workspace dev จะมองแค่ state ของ dev เท่านั้น สลับไป staging แล้ว Terraform จะทำตัวเหมือนไม่เคยเห็น resource ของ staging มาก่อน เพราะในมุมของ state file นั้น ไม่เคยเห็นจริง ๆ

ชื่อ workspace ที่ active อยู่เข้าถึงได้ในตัว configuration ผ่านค่า built-in terraform.workspace การ interpolate ค่านี้ทำให้ไฟล์ .tf ชุดเดียวทำงานต่างกันไปตาม workspace ที่ select อยู่

locals {
instance_size = {
dev = "t3.micro"
staging = "t3.small"
prod = "m5.large"
}
}
resource "aws_instance" "app" {
ami = data.aws_ami.app.id
instance_type = local.instance_size[terraform.workspace]
tags = {
Name = "app-${terraform.workspace}"
}
}

ตรงนี้ DRY จริง ๆ มี aws_instance block เดียว มีจุดเดียวสำหรับแก้ bug ในนั้น แต่ instance size กับชื่อยังออกมาต่างกันตาม workspace ไม่มี directory copy-paste ไม่มี resource definition ซ้ำ

นี่คือข้อจำกัดที่ต้องจำไว้ workspace isolate แค่ state เท่านั้น ไม่เปลี่ยนอย่างอื่นเลย ทุก workspace ที่สร้างจาก configuration เดียวกันแชร์สิ่งเหล่านี้ร่วมกัน

  • backend configuration เดียวกันเป๊ะ S3 bucket เดียวกัน, region เดียวกัน, account เดียวกัน
  • provider configuration เดียวกันเป๊ะ AWS credential เดียวกัน เว้นแต่จะเขียน logic แบบ conditional เพื่อสลับเอง
  • โค้ด .tf เดียวกันเป๊ะ ไม่มี hard boundary ใด ๆ กัน workspace dev ไม่ให้มี resource block ที่ ถ้า config ผิด ก็แตะ infrastructure ระดับ production ได้เท่ากับ workspace อื่น

นี่ทำให้ workspace เหมาะกับความต่างแบบเบา ๆ ที่โครงสร้างเหมือนกันทุกอย่าง เช่น preview environment อายุสั้นต่อ feature branch ที่แค่ต้องการ state ของตัวเองกับ instance size ที่เล็กกว่า เป็น use case ที่ดี แต่เป็นตัวเลือกที่แย่ทันทีที่ environment หนึ่งต้องการ AWS account จริง ๆ ที่ต่างกัน, region ต่างกัน, หรือ credential ต่างกันจากที่อื่น เพราะ workspace แสดงความต่างแบบนั้นไม่ได้เลย เป็นแค่ชื่อ

ความเสี่ยงที่คมกว่าและเกิดขึ้นในชีวิตจริงคือเรื่องคน ไม่ใช่เรื่อง architecture active workspace คือ state ชิ้นหนึ่งที่ CLI เลือกไว้ ซึ่งอยู่นอกไฟล์ .tf ไปเลย ไม่มีอะไรกัน engineer ที่คิดว่าตัวเองอยู่ใน dev สั่ง terraform apply แล้วมาพบทีหลังว่า terminal นั้นยังค้างอยู่ใน prod จากชั่วโมงก่อนหน้า ไม่มี credential แยก ไม่มี account boundary แยก ไม่มี confirmation prompt ที่ผูกกับชื่อ workspace เลย มีแค่ string ที่ลืมง่าย

flowchart LR
  cfg["One .tf config + one backend"] --> dev["workspace: dev (own state file)"]
  cfg --> staging["workspace: staging (own state file)"]
  cfg --> prod["workspace: prod (own state file)"]
One Terraform config and backend, three workspaces, three separate state files — everything else shared
workspace ของ Terraform isolate อะไรจริง ๆ และไม่ isolate อะไร
terraform.workspace มักถูกใช้ทำอะไรใน configuration
ความเสี่ยงเฉพาะในชีวิตจริงจากการใช้ workspace แยก environment คืออะไร
ใช้ workspace เหมาะกับกรณีไหน และไม่เหมาะกับกรณีไหน