Terraform Workspaces
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”workspace ของ Terraform ทำให้ configuration เดียวและ backend เดียวสร้าง state file ที่แยกจากกันได้หลายชุด สลับด้วยชื่อผ่าน CLI โดยไม่ต้องทำโค้ด .tf ซ้ำเลยสักบรรทัด
สร้างและสลับ workspace
หัวข้อที่มีชื่อว่า “สร้างและสลับ workspace”ทุก Terraform configuration เริ่มต้นด้วย workspace เดียวชื่อ default สร้างและสลับไปมาระหว่าง workspace ที่ตั้งชื่อเพิ่มได้ด้วยสามคำสั่งนี้
# Create a new workspace and switch to it immediatelyterraform workspace new dev
# List every workspace; the active one is marked with an asteriskterraform workspace list# default# * dev# staging# prod
# Switch to an existing workspaceterraform workspace select stagingแต่ละ workspace ได้ state file ของตัวเอง แต่ทุก workspace ยังอ่านไฟล์ .tf ชุดเดียวกันเป๊ะ และชี้ไปที่ backend configuration เดียวกันเป๊ะ สั่ง terraform plan ใน workspace dev จะมองแค่ state ของ dev เท่านั้น สลับไป staging แล้ว Terraform จะทำตัวเหมือนไม่เคยเห็น resource ของ staging มาก่อน เพราะในมุมของ state file นั้น ไม่เคยเห็นจริง ๆ
ปรับพฤติกรรมด้วย terraform.workspace
หัวข้อที่มีชื่อว่า “ปรับพฤติกรรมด้วย terraform.workspace”ชื่อ 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
หัวข้อที่มีชื่อว่า “สิ่งที่ workspace ไม่ isolate”นี่คือข้อจำกัดที่ต้องจำไว้ workspace isolate แค่ state เท่านั้น ไม่เปลี่ยนอย่างอื่นเลย ทุก workspace ที่สร้างจาก configuration เดียวกันแชร์สิ่งเหล่านี้ร่วมกัน
- backend configuration เดียวกันเป๊ะ S3 bucket เดียวกัน, region เดียวกัน, account เดียวกัน
- provider configuration เดียวกันเป๊ะ AWS credential เดียวกัน เว้นแต่จะเขียน logic แบบ conditional เพื่อสลับเอง
- โค้ด
.tfเดียวกันเป๊ะ ไม่มี hard boundary ใด ๆ กัน workspacedevไม่ให้มี 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)"]