Input Variables
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”input variable คือ parameter ที่มีชื่อและมี type ชัดเจน ทำให้ config เดียวกันสร้าง infrastructure ต่างกันได้ตามคนเรียกและค่าที่ส่งเข้ามา
ประกาศ variable block
หัวข้อที่มีชื่อว่า “ประกาศ variable block”variable block มีสี่ส่วนที่ควรรู้ไว้ให้แม่น type กำหนดรูปร่างของค่าที่ยอมรับได้ default เป็นค่า fallback เวลาไม่มีใครส่งค่ามา description ไว้บอกความตั้งใจให้คนอ่านคนถัดไป และ sensitive ซ่อนค่าจาก CLI output ส่วนใหญ่
variable "environment" { type = string description = "Deployment environment name, e.g. dev, staging, prod" default = "dev"}
variable "instance_count" { type = number description = "Number of Compute Engine instances to launch" default = 2}
variable "enable_deletion_protection" { type = bool description = "Whether to enable deletion protection on the Compute Engine instance" default = true}
variable "allowed_ports" { type = list(number) description = "TCP ports allowed inbound on the firewall rule" default = [22, 443]}
variable "resource_labels" { type = map(string) description = "Labels applied to every resource in this configuration" default = { project = "payments" team = "platform" }}
variable "db_config" { type = object({ database_version = string tier = string disk_size_gb = number }) description = "Structured configuration for the Cloud SQL instance" default = { database_version = "POSTGRES_15" tier = "db-custom-1-3840" disk_size_gb = 20 }}
variable "db_password" { type = string description = "Password for the Cloud SQL application user" sensitive = true}object({...}) ควรพูดถึงแยกไว้ต่างหาก เป็น structure ที่มี type และรูปร่างตายตัว ทุก key ที่ list ไว้ต้อง required (เว้นแต่จะใส่ default ผ่าน optional()) และ Terraform ปฏิเสธค่าที่ caller ส่งมาผิดรูปร่างตั้งแต่ตอน plan ก่อนที่จะไปเรียก GCP API เลยด้วยซ้ำ
sensitive = true บน db_password มีผลแค่กับการ แสดงผล เท่านั้น Terraform จะซ่อนค่าใน output ของ plan/apply และใน CLI ให้เป็น (sensitive value) แต่ไม่ได้เข้ารหัสหรือตัดค่าออกจาก state file — module เรื่อง state management พูดไปแล้วว่า state เก็บทุก attribute ของทุก resource ที่ manage อยู่เป็น plain text ในไฟล์ JSON รวมถึงค่าที่มาจาก sensitive variable ด้วย ให้มอง sensitive = true เป็นแค่การป้องกันตอนแสดงผลบน terminal กับ CI log ไม่ใช่ตัวแทนของ remote backend ที่ควบคุม access ได้ดีอยู่แล้ว
ตรวจสอบ variable ด้วย validation block
หัวข้อที่มีชื่อว่า “ตรวจสอบ variable ด้วย validation block”default หรือ type constraint เช็คได้แค่รูปร่างของค่า ไม่ได้เช็คว่าค่านั้นสมเหตุสมผลไหม validation block เพิ่ม condition แบบ custom กับ error_message เฉพาะเจาะจง ทำให้ caller ได้ feedback ทันทีตอน plan แทนที่จะเจอ error งง ๆ จากลึก ๆ ใน Google provider
variable "zone" { type = string description = "GCP zone the resources are deployed into, e.g. us-central1-a"
validation { condition = can(regex("^[a-z]+-[a-z0-9]+-[a-z]$", var.zone)) error_message = "zone must look like a GCP zone, e.g. us-central1-a or europe-west1-b." }}
variable "environment" { type = string description = "Deployment environment name"
validation { condition = contains(["dev", "staging", "prod"], var.environment) error_message = "environment must be one of: dev, staging, prod." }}ถ้าไม่มี validation block แรก การส่ง zone = "not-a-real-zone" จะผ่าน terraform plan ไปเฉย ๆ แล้วไปพังตอน Terraform เรียก Google provider จริง ๆ เพื่อสร้าง resource ใน zone นั้น — feedback loop ช้ากว่ามาก และ error message ก็เฉพาะเจาะจงน้อยกว่า “zone must look like a GCP zone” มาก can() ที่ wrap ไว้ทำหน้าที่แปลง error จาก regex() ให้กลายเป็น false แทนที่จะ error ตรง ๆ ซึ่งตรงกับสิ่งที่ condition expression ต้องการพอดี เพราะต้อง evaluate ออกมาเป็น true หรือ false เสมอ ห้าม raise error
ตั้งค่า variable และใครชนะ
หัวข้อที่มีชื่อว่า “ตั้งค่า variable และใครชนะ”Terraform ยอมให้ตั้งค่า variable ตัวเดียวกันจากหลายที่พร้อมกัน แล้วแก้ conflict ด้วยลำดับความสำคัญที่ตายตัว เรียงจากสำคัญที่สุด (ชนะ) ไปน้อยที่สุด:
-varและ-var-fileบน command line ตามลำดับที่ใส่ — วิธีที่ explicit ที่สุดและชั่วคราวที่สุด- ไฟล์
*.auto.tfvars/*.auto.tfvars.jsonที่ auto-load จาก working directory ตามลำดับตัวอักษรของชื่อไฟล์ terraform.tfvars/terraform.tfvars.jsonที่ auto-load ถ้ามีไฟล์นี้อยู่- environment variable
TF_VAR_<name>— มีประโยชน์กับ CI pipeline และกับค่าที่ไม่อยากให้อยู่ในไฟล์เลย defaultของ variable เอง — ใช้ก็ต่อเมื่อไม่มีอะไรข้างบนส่งค่ามาเลย
# Highest precedence: an explicit CLI flag for this one runterraform apply -var="zone=europe-west1-b"
# Or point at a specific tfvars fileterraform apply -var-file="prod.tfvars"
# Environment variable equivalent of setting zoneexport TF_VAR_zone="us-east1-b"terraform applyถ้า zone ถูกตั้งไว้ใน terraform.tfvars, ตั้งอีกทีใน prod.auto.tfvars, แล้วตั้งอีกทีผ่าน -var บน command line ค่าจาก -var จะชนะ Terraform ไม่ได้ merge ค่าแบบ scalar ข้ามแหล่งกัน แต่เลือกแหล่งที่ priority สูงสุดที่มีค่าอยู่เท่านั้น collection type อย่าง map กับ object เป็นข้อยกเว้นที่ควรจำไว้สำหรับบทหลัง ๆ — เครื่องมือบางตัว merge ค่าที่ nested กันแทนที่จะ override ทั้งก้อน แต่สำหรับแหล่งข้อมูลปกติข้างบนนี้ ค่าที่ประกาศไว้ในแหล่งที่ priority สูงกว่าจะแทนที่ค่าจากแหล่งที่ priority ต่ำกว่าไปเลยสำหรับ variable ตัวนั้น
flowchart LR a["-var / -var-file (CLI flag)"] --> r["Resolved value of var.zone"] b["*.auto.tfvars (alphabetical)"] --> r c["terraform.tfvars"] --> r d["TF_VAR_zone (env var)"] --> r e["default in the variable block"] --> r r --> res["google_compute_instance.web"]