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

The Terraform Workflow

สี่คำสั่งครอบคลุมงานที่คุณทำเกือบทุกวัน terraform init เตรียม working directory ให้พร้อม terraform plan แสดง dry-run diff ให้ดู terraform apply ลงมือทำจริง และ terraform destroy รื้อทุกอย่างที่ configuration จัดการอยู่ทิ้ง

terraform init คือคำสั่งแรกที่คุณรันในทุกไดเรกทอรี และรันอีกครั้งหลังเพิ่ม provider หรือ module ใหม่ คำสั่งนี้อ่าน required_providers block, ดาวน์โหลด provider plugin ที่ตรงกัน แล้วเตรียม backend ที่เก็บ state ให้พร้อม

Terminal window
terraform init

terraform plan คือ dry run โดยอ่าน real AWS state, เทียบกับ configuration ของคุณ แล้วพิมพ์ diff ออกมา คือ resource ไหนจะถูกสร้าง อัปเดต in-place หรือลบ โดยยังไม่เปลี่ยนแปลงอะไรจริง

Terminal window
terraform plan
# example output
Terraform will perform the following actions:
# aws_s3_bucket.reports will be created
+ resource "aws_s3_bucket" "reports" {
+ bucket = "acme-monthly-reports"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.

terraform apply รัน plan จริง โดยคำนวณ diff ใหม่อีกครั้ง (ยกเว้นคุณส่ง saved plan file เข้าไปตามที่จะพูดถึงด้านล่าง) แสดงให้คุณดู ถามยืนยัน แล้วค่อยเรียก AWS API จริงเพื่อสร้าง อัปเดต หรือลบ resource

Terminal window
terraform apply

terraform destroy คือด้านตรงข้ามของ apply โดยคำนวณ plan เพื่อลบทุก resource ที่ configuration นี้จัดการอยู่ และหลังยืนยันแล้วก็ลบทิ้ง

Terminal window
terraform destroy
flowchart LR
  init["terraform init"] --> plan["terraform plan"]
  plan --> review{"Review the diff"}
  review --> apply["terraform apply"]
  apply --> real["Real infrastructure updated"]
  init -.-> destroy["terraform destroy"]
  destroy -.-> gone["Managed resources removed"]
The core Terraform workflow, with destroy as a separate path

terraform apply เฉย ๆ จะคำนวณ plan ของตัวเองใหม่ทันทีก่อนรันจริง ระหว่างช่วงเวลาที่คุณ review output ของ plan กับตอนที่มีคนรัน apply โลกจริงอาจเปลี่ยนไปแล้ว คนอื่น apply การเปลี่ยนแปลงที่ขัดกัน quota ของ AWS เปลี่ยน หรืออะไรก็ได้ plan ที่ apply คำนวณใหม่ตอนนั้นอาจไม่ใช่อันเดียวกับที่คุณ review ไปแล้ว

การ save plan ลงไฟล์ปิดช่องว่างนี้ คุณสั่ง apply ให้รันตรงไฟล์นั้นได้เลย โดยไม่คำนวณใหม่

Terminal window
terraform plan -out=tfplan
terraform apply tfplan

รูปแบบนี้สำคัญที่สุดใน CI/CD pipeline สามารถรัน plan -out=tfplan, โพสต์ diff ให้คน review และรัน apply tfplan หลังได้รับ approve เท่านั้น ทำให้มั่นใจได้ว่าสิ่งที่ apply ไปคือสิ่งที่คนอนุมัติเป๊ะ ๆ

ตอนที่ terraform init resolve version constraint ใน required_providers Terraform จะเขียนเวอร์ชันที่เลือกและ cryptographic checksum ลงใน .terraform.lock.hcl ในไดเรกทอรีเดียวกับ configuration ของคุณ

# .terraform.lock.hcl (excerpt — Terraform manages this file's contents)
provider "registry.terraform.io/hashicorp/aws" {
version = "5.55.0"
constraints = "~> 5.0"
hashes = [
"h1:examplehashvaluegeneratedbyterraforminit=",
]
}

ไฟล์นี้ควรถูก commit เข้า version control เพราะเป็น provider-level analogue ของ package-lock.json หรือ Gemfile.lock ถ้าไม่มีไฟล์นี้ การรัน terraform init แต่ละครั้ง — โน้ตบุ๊กคุณวันนี้ โน้ตบุ๊กเพื่อนร่วมทีมพรุ่งนี้ CI runner สัปดาห์หน้า — อาจ resolve ~> 5.0 ไปคนละ patch release กัน และความต่างเล็ก ๆ ของ behavior ใน provider ก็อาจทำให้เครื่องคนอื่นได้ plan ที่ต่างออกไปโดยไม่มีเหตุผลที่มองเห็น เมื่อ commit lock file ไว้ ทุกครั้งที่ init จะติดตั้งเวอร์ชันเดิมเป๊ะ ๆ จนกว่าจะมีคนตั้งใจรัน terraform init -upgrade เพื่อขยับ constraint ไปข้างหน้า

terraform plan ทำอะไรจริง ๆ
ทำไมถึงควร save plan ลงไฟล์ด้วย plan -out=tfplan ก่อนรัน apply
.terraform.lock.hcl มีไว้ทำอะไร และควร commit เข้า git หรือไม่
terraform destroy ทำอะไร