ศัพท์ของคอร์สนี้ครอบคลุมสามชั้น: Terraform core (resource, provider, state, module, plan/apply/destroy) ที่ทำงานเหมือนกันทุก cloud; Terragrunt (unit, dependency, root config, stack) ที่ทำให้หลาย environment ยังคง DRY; และส่วนที่เฉพาะ GCP (generation-based locking ของ gcs backend, google เทียบกับ google-beta, Secret Manager) ที่จะเข้าใจได้ก็ต่อเมื่อรู้ว่ากำลังอ่าน provider ไหนอยู่ เวลาอ่านบทเรียนแล้วเจอคำที่ไม่คุ้น หรือไม่แน่ใจว่ายังใช้ได้อยู่กับ Terraform 1.16 / Terragrunt 1.1 ไหม ให้กลับมาดูที่นี่
Term ความหมาย บทเรียน Application Default Credentials (ADC) ลำดับการค้นหา credential ที่ provider google/google-beta ใช้เวลาไม่ได้ config credentials/service-account key ตรง ๆ — ตอน dev ในเครื่องคือ token จาก gcloud auth application-default login; ตอนรันใน GCP/CI ที่มี Workload Identity Federation ก็ใช้ service account ที่แนบไว้ให้เองอัตโนมัติ Secrets and Credential Management apply terraform apply รัน action ทั้งหมดในแผนต่อ infrastructure จริง — เป็นคำสั่งเดียวใน core workflow ที่ create, update หรือ destroy อะไรจริง ๆ; ถ้าไม่มี plan file ที่เซฟไว้ มันจะสร้างให้ก่อนแล้วถาม confirmThe Terraform Workflow backend plugin ที่ตัดสินว่า state ของ Terraform เก็บ ที่ไหน และ operation ที่ทำกับมันถูก lock ยังไง — config ครั้งเดียวใน block terraform { backend "gcs" {} }; เปลี่ยน argument ใน block ต้องรัน terraform init ใหม่ (ใส่ -migrate-state ถ้าจะย้าย state เดิม) Remote Backends and Locking
Term ความหมาย บทเรียน Cloud Build (GCP-native CI/CD) ตัวรัน CI/CD ที่ Google Cloud จัดการให้ config ผ่าน cloudbuild.yaml ต่อเข้ากับ resource google_cloudbuild_trigger — ทางเลือกแบบ native ของ GCP แทนการรัน plan/apply ของ Terraform จาก GitHub Actions หรือ CI ภายนอกระบบอื่น CI/CD for Infrastructure catalog / scaffold terragrunt catalog เปิดดู module repository ชุดที่ config ไว้ แล้ว scaffold unit ใหม่จากมันแบบ interactive — เขียน terragrunt.hcl กับ inputs เริ่มต้นให้เลย แทนที่จะต้องเขียน unit เองตั้งแต่ต้นทุกครั้งTerragrunt HCL and the Root Config checkov static-analysis scanner (Bridgecrew/Palo Alto) ที่รันกับ Terraform source ก่อน จะ plan เช็ค policy ที่ built-in มาให้ (GCS bucket ที่เปิด public, persistent disk ที่ไม่เข้ารหัส, firewall rule ที่เปิดกว้างเกินไป, …) — รันผ่าน checkov -d . หรือ GitHub Action ของมัน ซึ่งต้อง pin ไว้ที่ ref ใดหนึ่ง ไม่ใช้ @master เพราะมันเปลี่ยน policy แบบ breaking ได้ทุกครั้งที่ push Policy as Code and Static Analysis configuration_aliasesประกาศไว้ใน required_providers block ของ module ระบุชื่อ provider alias (เช่น google.us_west1, google.us_east1) ที่ module คาดว่าผู้เรียกจะส่งเข้ามาผ่าน argument providers = {} — ถ้าไม่มีตัวนี้ provider ที่ alias ไว้จะข้าม module boundary ไปไม่ได้เลย Module Composition and Sources countวิธีเก่าแบบใช้ index เพื่อแปลง resource/module block เดียวให้กลายเป็นสำเนาที่เกือบเหมือนกัน N ชุด (resource.name[0], [1], …) — เปราะบางเวลาสลับลำดับ เพราะเอา element กลางออกจาก list จะเลื่อน index ของทุกตัวที่ตามมา ทำให้ resource พวกนั้นถูก destroy แล้วสร้างใหม่ Count and For Each create_before_destroymeta-argument lifecycle { create_before_destroy = true } สลับลำดับ replace จาก destroy-ก่อน-แล้ว-ค่อย-create เป็น create-ก่อน — ต้องใช้เมื่อ resource เก่าต้องยังให้บริการ traffic อยู่ หรือยังต้องมีอยู่เพราะอย่างอื่นยัง reference มันจนกว่า resource ใหม่จะพร้อม HCL, Providers, and Resources
Term ความหมาย บทเรียน data source การ lookup แบบ read-only (data "google_compute_image" "..." {}) ที่ดึงข้อมูลเกี่ยวกับ resource ที่ Terraform ไม่ได้จัดการ — ไม่ว่าจะเป็นของที่มีอยู่แล้ว (VPC ที่แชร์กัน) หรือค่าที่ provider คำนวณให้ (image family ที่ตรงกับ filter) — และ Terraform จะไม่มีวัน create, update หรือ destroy มันได้เอง HCL, Providers, and Resources deletion_policyattribute ระดับ resource (DELETE/PREVENT/ABANDON) ที่ resource ของ Google บางตัวมีให้ override พฤติกรรม destroy default ของ provider เอง — อย่าง google_project เอง deletion_policy ของมัน default เป็น PREVENT เลยทำให้ plan ที่จะลบ project fail ออกมาตรง ๆ เว้นแต่จะตั้งเป็น DELETE ชัดเจน (หรือ ABANDON ที่แค่เอาออกจาก state โดยไม่แตะ project จริง) HCL, Providers, and Resources -detailed-exitcodeflag บน terraform plan ที่เปลี่ยน exit code จาก 0/1 ธรรมดา เป็น 0 (ไม่มีอะไรเปลี่ยน), 1 (error) หรือ 2 (มีการเปลี่ยนแปลง) — สิ่งที่ CI pipeline เช็คจริง ๆ เพื่อตัดสินว่า plan ต้องมีขั้นตอน approve จากคนหรือข้ามไปได้เลย CI/CD for Infrastructure dependency / dependencies block dependency ของ Terragrunt อ่าน outputs ของอีก unit มาเป็น input (หลังจากรัน plan/apply ของมันเองก่อน); block dependencies (พหูพจน์) แค่การันตีลำดับกับ unit หนึ่งตัวหรือมากกว่าโดยไม่ดึง output ออกมา Dependencies Between Units destroy terraform destroy (หรือ apply -destroy) plan แล้ว execute การลบ resource ทุกตัวที่ track อยู่ใน state ตอนนี้ — pipeline plan/apply เดียวกับการเปลี่ยนแปลงปกติ แค่ทุก action ถูกตั้งเป็น deleteThe Terraform Workflow drift ความต่างระหว่างสิ่งที่อยู่ใน state กับสิ่งที่มีอยู่จริงใน GCP — เกิดจากการเปลี่ยนผ่าน console เอง, เครื่องมืออื่น หรือ process นอกระบบ — มีแค่ terraform plan/refresh เท่านั้นที่เห็นมัน เพราะ Terraform ไม่เคย poll ต่อเนื่องด้วยตัวเอง Drift Detection and Import dynamic block สร้าง nested block ซ้ำ (เช่น ingress {} หลายอันในหนึ่ง security group) จาก list หรือ map ตอน runtime — เทียบเท่า for_each แต่ใช้กับ nested block บน resource เพราะ nested block ของ resource เองใส่ for_each ตรง ๆ ไม่ได้ Count and For Each
Term ความหมาย บทเรียน ephemeral resource แบบ ephemeral "..." {} หรือ variable/output ที่เป็น ephemeral = true (Terraform 1.10+) มีอยู่แค่ระหว่าง plan/apply ครั้งเดียว — ไม่ถูกเขียนลง state หรือ plan file เลย — กลไกที่ credential อายุสั้นหรือ password ที่ generate มาไหลผ่านได้โดยไม่ลงดิสก์เลย Sensitive Data and Team Workflows error_hookhook ของ Terragrunt (ข้างใน terraform { error_hook "..." {} }) ที่รันเฉพาะตอนคำสั่ง Terraform ที่ wrap ไว้ fail โดย match กับ error output ด้วย regex ใน on_errors — ใช้ทำ cleanup หรือแจ้งเตือนที่ before_hook/after_hook ธรรมดาทำไม่ได้ Terragrunt HCL and the Root Config --filterflag ปัจจุบันของ Terragrunt สำหรับจำกัดว่า run --all จะทำกับ unit ไหนบ้าง (ตาม path, ทิศทาง dependency หรือ query ที่เซฟไว้) — ตัวแทนของคู่เก่าที่ตอนนี้ถูกเอาออกแล้วอย่าง --terragrunt-include-dir/--terragrunt-exclude-dir Running Many Units at Once find_in_parent_folders function find_in_parent_folders() ใน block include เดินขึ้นจาก directory ของ unit เพื่อหาไฟล์ที่ระบุชื่อไว้ (ปกติคือ root.hcl) — กลไกที่ทำให้ทุก unit include root config เดียวกันได้โดยไม่ต้อง hardcode relative path ที่จะพังเวลา unit ย้ายที่ DRY Configuration with include find / list terragrunt find กับ terragrunt list ค้นหา unit ใต้ tree ปัจจุบัน (จะเอาออกมาเป็น JSON หรือกรองตาม dependency ก็ได้) — คำสั่ง discovery แบบ read-only ที่อยู่เบื้องหลัง --filter และเบื้องหลัง tooling ของ editor/CI ที่ต้อง enumerate unit โดยไม่ต้องรันอะไรเลยRunning Many Units at Once for_eachแปลง resource/module block เดียวให้กลายเป็นหนึ่ง instance ต่อหนึ่ง entry ของ map หรือ set ของ string โดย key ด้วย key ของ map นั้น (resource.name["prod"]) แทนที่จะเป็น index ตัวเลข — เอา entry ออกกระทบแค่ instance นั้นตัวเดียว ต่างจาก count Count and For Each force-unlock terraform force-unlock <lock-id> เอา state lock ที่ค้างอยู่ออกด้วย ID โดยไม่ต้องรัน plan/apply — ทางออกฉุกเฉินสำหรับ lock ที่ค้างจาก process ที่ crash หรือ CI job ที่ถูกฆ่า และเป็นคำสั่งเดียวที่ถ้าใช้กับ lock ที่ยังถูกถืออยู่จริง ๆ จะทำ state พังได้Remote Backends and Locking
Term ความหมาย บทเรียน GCS backend prefix สิ่งที่เทียบเท่ากับ key ของ S3 backend บน gcs backend: path prefix ข้างใน bucket ที่ backend เก็บ state object ไว้ (โดยปกติ Terragrunt ต่อ unit จะใช้หนึ่ง prefix ต่อหนึ่ง unit มากกว่าจะแยก bucket ต่อ unit) Remote Backends and Locking generate block generate "..." {} ของ Terragrunt เขียนไฟล์ (provider block, backend block, version constraint) ลงใน working directory ของ unit ก่อน Terraform จะรัน — กลไกที่ทำให้ทุก unit แชร์ provider/backend boilerplate เดียวกันที่ define ไว้ครั้งเดียวใน root.hcl Terragrunt HCL and the Root Config google vs google-beta provider google ครอบคลุม resource/field ที่ GA (generally available) แล้ว; google-beta เป็น provider แยกต่างหาก (resource กับ schema เดียวกัน) ที่เพิ่ม field/resource แบบ beta/preview เข้ามาด้วย — resource ที่ใช้ field แบบ beta-only ต้องประกาศ provider = google-beta ตรง ๆ ไม่ fallback ให้เองอัตโนมัติ HCL, Providers, and Resources google_project_serviceเปิดใช้งาน Google Cloud API ตัวใดตัวหนึ่ง (เช่น compute.googleapis.com) บน project — resource ที่ต้องพึ่ง API ที่ provider ส่วนใหญ่คิดว่า “เปิดอยู่แล้ว” ต้องมีตัวนี้เป็น prerequisite ชัดเจน ไม่งั้น apply ครั้งแรกจะ fail ด้วย error ว่า API ยังไม่เปิด HCL, Providers, and Resources HCP Terraform แพลตฟอร์ม remote-execution ที่ HashiCorp จัดการให้ (เดิมชื่อ Terraform Cloud): รัน plan/apply บน worker ของตัวเอง, เก็บ state และกั้น apply ไว้หลัง approval กับ Sentinel policy — ทางเลือกแบบ managed แทนการ self-host gcs backend บวก CI pipeline เอง CI/CD for Infrastructure ignore_changes ข้างใน lifecycle {}, ignore_changes = [tags] (หรือ list ของ attribute ที่ระบุ) บอก Terraform ให้เลิก report — และเลิก revert — drift เฉพาะ attribute พวกนั้น ใช้บ่อยตอนที่ process อื่น (autoscaling, Lambda ที่ tag ให้) เป็นเจ้าของมันอยู่แล้วจริง ๆ Drift Detection and Import import block block import { to = ..., id = ... } แบบ declarative (Terraform 1.5+) เอา resource ที่มีอยู่แล้วเข้ามาอยู่ใต้การจัดการโดยใส่มันไว้ใน plan/apply ปกติ แทนคำสั่ง terraform import แบบเดิมที่เป็น imperative — review ได้ใน PR ก่อนจะมีอะไรเปลี่ยนจริง Drift Detection and Import include block include "root" { path = find_in_parent_folders() } ของ Terragrunt ดึง config จากไฟล์ .hcl อื่นเข้ามาใน unit ปัจจุบัน รวม generate/remote_state/inputs ของมันเข้าด้วย — กลไก DRY หลัก คู่กับ dependency สำหรับ tree ที่มีหลาย unit DRY Configuration with include Infracost ประเมิน cost ต่อเดือนที่เปลี่ยนไปถ้า plan นี้เกิดขึ้นจริง โดยจับคู่ resource ที่วางแผนจะเปลี่ยนกับข้อมูลราคาของ cloud — รันกับ output ของ terraform show -json มักถูกโพสต์เป็น PR comment คู่กับ policy-as-code gate Policy as Code and Static Analysis
Term ความหมาย บทเรียน labels กลไกติด tag ของ GCP (map แบบ flat ของ key/value string บน resource ส่วนใหญ่) — เทียบเท่าตรง ๆ กับ “tags” ของ AWS/Azure แค่เปลี่ยนชื่อ และมีกฎเรื่อง character set ของ key/value ที่เข้มกว่า HCL, Providers, and Resources lifecycle meta-argument block lifecycle {} ที่มีให้ทุก resource เก็บ create_before_destroy, prevent_destroy, ignore_changes และ replace_triggered_by — จุดเดียวที่ Terraform ให้ override พฤติกรรม replace/destroy default ต่อ resource ได้ HCL, Providers, and Resources local block locals {} ตั้งชื่อ expression ครั้งเดียวเพื่อเอามาใช้ซ้ำทั่ว module โดยไม่ต้องเขียนซ้ำ — ไม่ใช่ input หรือ output เลย เป็นแค่ค่าที่ computed ภายในเท่านั้น Outputs and Locals lock record ที่ backend เขียนก่อนเริ่ม operation ที่แก้ state กันไม่ให้ plan/apply ที่รันพร้อมกันตัวที่สองมาอ่าน/เขียน state เดียวกันในเวลาเดียวกัน — lock ของ gcs backend ใช้ generation number ของ state object เป็นเงื่อนไขแบบ optimistic-concurrency — built-in มาตั้งแต่ backend เวอร์ชันแรก ๆ ไม่ต้องสร้าง lock resource แยกเลย ต่างจากประวัติของ S3 backend ที่เคยต้องพึ่ง DynamoDB table Remote Backends and Locking
Term ความหมาย บทเรียน mock_outputs ข้างใน block dependency ของ Terragrunt, mock_outputs ใส่ค่าปลอมให้ output ของ dependency นั้นเพื่อให้คำสั่งอย่าง validate/plan รันได้แม้ dependency จะยังไม่เคยถูก apply มาก่อน — ถูกจำกัดไว้ default ให้ใช้กับ plan เท่านั้นผ่าน mock_outputs_allowed_terraform_commands เพื่อไม่ให้ apply จริงรันเข้ากับข้อมูลปลอมแบบเงียบ ๆ Dependencies Between Units mock_providerconstruct ของ terraform test (1.7+) ที่แทน provider จริงด้วย mock ที่คืนค่า placeholder ที่ compute ให้ หรือ override ที่ระบุตรง ๆ — กลไกที่ทำให้ test รัน plan/apply ได้โดยไม่ต้องมี credential จริงหรือยิง API จริงเลย Testing Modules module กลุ่มไฟล์ .tf ที่ reuse ได้ ครบในตัวเอง รับ input เป็น variable และ expose output ออกมา — เรียกจากที่อื่นด้วย block module "name" { source = ... } เป็นหน่วยของการ compose และ reuse ที่อยู่เหนือ resource เดียว Writing a Reusable Module moved block block moved { from = ..., to = ... } แบบ declarative (Terraform 1.1+) บันทึกการ rename หรือย้าย resource/module ใน state ให้เป็นการ refactor ไม่ใช่ destroy+create — review ได้ใน plan และปล่อยไว้ใน config ได้เรื่อย ๆ อย่างปลอดภัยสำหรับใครก็ตามที่ apply จาก state เก่ากว่า Drift Detection and Import null_resource (legacy)วิธีก่อน 1.4 ในการแนบพฤติกรรม provisioner/triggers โดยไม่มี infrastructure จริงรองรับ — ถูกแทนที่ด้วย terraform_data ที่ทำงานแบบเดียวกันในฐานะส่วนหนึ่งของ Terraform core โดยตรง แทนที่จะต้องพึ่ง provider แยกต่างหาก Testing Modules
Term ความหมาย บทเรียน OIDC OpenID Connect: CI pipeline แลก token identity ที่ platform ออกให้ อายุสั้น กับ credential ของ cloud แบบชั่วคราว ผ่าน trust relationship ที่ config ไว้ครั้งเดียว — กลไกที่เอา cloud access key อายุยืนออกจาก CI secret ไปเลย Secrets and Credential Management output expose ค่าจาก module (หรือ root module ซึ่ง terraform output จะอ่านมัน) ให้กับสิ่งที่เรียกมันมา — block dependency ของ Terragrunt อ่าน output ของ unit แบบนี้เป๊ะ ๆ Outputs and Locals override_resourceconstruct ของ terraform test ที่แทนที่ค่าที่ plan ไว้ของ resource ตัวใดตัวหนึ่ง (แทนที่จะเป็น provider ทั้งตัวแบบ mock_provider) — ใช้ตอนที่มีแค่ resource เดียวใน plan ที่ส่วนใหญ่เป็นของจริงต้องการค่าแทนตัว Testing Modules
Term ความหมาย บทเรียน plan terraform plan คำนวณและแสดง action ที่ต้องทำเพื่อไปถึง desired state โดยไม่รันอะไรเลย — เป็น read-only ต่อ infrastructure จริง แม้จะอ่าน state ปัจจุบันและ (ถ้าไม่ใส่ -refresh=false) refresh มันด้วยThe Terraform Workflow plugin cache TF_PLUGIN_CACHE_DIR (หรือ plugin_cache_dir ใน CLI config) ชี้ให้ทุก terraform init ใช้ directory เดียวที่เก็บ provider binary ที่ดาวน์โหลดมาแล้วร่วมกัน แทนที่จะดาวน์โหลด provider version เดิมซ้ำเข้า .terraform/providers ของทุกโปรเจกต์เอง — ประหยัดเวลาและ bandwidth ได้จริง แต่ไม่เคยปลอดภัยถ้าให้ init สองอันรันพร้อมกันโดยไม่มีการป้องกันInstalling Terraform and Project Structure precondition / postcondition block condition {} ของ precondition เช็คสมมติฐาน ก่อน resource/data source/output จะถูก evaluate (เช่น “AMI ตัวนี้ต้องอยู่ใน account”); postcondition เช็คผลลัพธ์ หลัง — ทั้งคู่ทำให้ plan/apply fail พร้อม message ที่กำหนดเองทันทีที่ expression เป็นเท็จ แทนที่จะไปโผล่เป็น error ที่งงตรงปลายทาง Expressions, Functions, and Conditionals prevent_destroymeta-argument lifecycle { prevent_destroy = true } ทำให้ Terraform ปฏิเสธที่จะ plan การ destroy resource นั้นเลย — plan error ออกมาแทนที่จะป้องกันแบบเงียบ ๆ ดังนั้นการ refactor ด้วย moved/removed รอบ ๆ มันก็ยังต้องระวังอยู่ HCL, Providers, and Resources project / location (provider defaults) & auto-createresource ส่วนใหญ่ของ google รับ argument project/region/zone ของตัวเองได้ แต่ถ้าไม่ใส่ก็ fallback ไปใช้ default ของ provider block แบบเงียบ ๆ — และแยกกันไปอีกเรื่องคือ project ใหม่ของ GCP จะ auto-create default VPC (auto_create_network บน google_project ค่า default เป็น true) พร้อม subnet แบบ auto-mode ในทุก region เว้นแต่จะปิดไว้ตรง ๆ HCL, Providers, and Resources provider plugin ที่แปล HCL resource/data-source block ให้กลายเป็น API call จริงเข้าระบบใดระบบหนึ่ง — aws, azurerm, google และอีกหลายร้อยตัว แต่ละตัว version และติดตั้งแยกจาก Terraform core เอง HCL, Providers, and Resources provider alias config ที่สองหรือสามของ provider เดียวกัน ตั้งชื่อผ่าน alias = "..." ใน block provider {} แล้ว reference บน resource ด้วย provider = google.us_west1 — วิธีที่ config เดียวจัดการ resource ข้ามเช่นสองภูมิภาคของ GCP ใน apply เดียว HCL, Providers, and Resources provider protocol สัญญา RPC ที่ version ไว้ (protocol v6 ตั้งแต่ Terraform 1.4+/provider ปัจจุบัน) ระหว่าง Terraform core กับ provider plugin ใด ๆ — เหตุผลที่ provider binary ที่ build มากับ protocol 6 โหลดเข้า CLI ที่พูดได้แค่ protocol 5 ไม่ได้ ไม่เกี่ยวกับ semantic version ของ provider เอง Module Versioning and Registries
Term ความหมาย บทเรียน refresh อ่าน state จริงของทุก resource ที่จัดการอยู่จาก provider ใหม่ แล้ว reconcile เข้า state file ของ Terraform — เกิดขึ้นอัตโนมัติเป็นส่วนหนึ่งของ plan/apply เว้นแต่ใส่ -refresh=false หรือสั่งตรง ๆ ผ่าน terraform apply -refresh-only Drift Detection and Import registry Terraform Registry (registry.terraform.io) host provider กับ module ที่ version แล้วและค้นหาได้แบบ public — module source อย่าง terraform-google-modules/network/google resolve มาจากที่นี่โดย default ไม่ต้องใส่ Git URL เต็ม Module Versioning and Registries remote_state block remote_state { backend = "gcs" ... } ของ Terragrunt generate backend block ของ Terraform ที่เทียบเท่ากันให้ทุก unit ที่ include มัน เก็บ config bucket/prefix ไว้ที่เดียวจริง ๆ แทนที่จะ copy-paste ไปทุก unit Terragrunt HCL and the Root Config removed block block removed { from = ... } แบบ declarative (Terraform 1.7+) เอา resource ออกจาก state — ใส่ lifecycle { destroy = false/true } ซ้อนไว้ข้างในก็ได้ — โดยไม่ต้องมี config ของ resource นั้นเหลืออยู่เลยก็ได้ เป็นตัวแทนที่ปลอดภัยของ terraform state rm เวลา config ก็ถูกลบไปด้วย Drift Detection and Import render terragrunt render print config ของ unit ที่ resolve เสร็จเรียบร้อยแล้ว (หลัง include, generate และ evaluate function) ออกมาเป็น JSON หรือ HCL — วิธีดูว่า unit จะรันอะไรจริง ๆ โดยไม่ต้อง trigger plan/applyRunning Many Units at Once replace_triggered_by ข้างใน lifecycle {}, replace_triggered_by = [google_compute_instance_template.this] บังคับให้ resource นี้ถูก replace ทุกครั้งที่ resource/attribute ที่ reference ไว้เปลี่ยน — แม้ argument ของ resource นี้เองจะไม่ได้เปลี่ยนอะไรเลยก็ตาม HCL, Providers, and Resources resource building block หลัก: block resource "google_compute_instance" "this" {} ประกาศ object จริงหนึ่งตัวที่ถูกจัดการ ซึ่ง lifecycle เต็ม (create/read/update/delete) ของมัน Terraform เป็นเจ้าของทั้งหมดตั้งแต่ต้นจนจบ HCL, Providers, and Resources root module ไฟล์ .tf ใน directory ที่เรารัน terraform จริง ๆ — module อื่นทุกตัวเป็น child module ที่ไปถึงผ่านมันเท่านั้น และเป็นที่เดียวที่ block provider {} หรือ backend configuration จะอยู่ได้ Writing a Reusable Module root.hcl ชื่อตามธรรมเนียม (แทนที่ pattern เก่าที่ใช้ terragrunt.hcl เป็น root) สำหรับไฟล์ Terragrunt บนสุดของ tree ที่ block include ของทุก unit หามันเจอผ่าน find_in_parent_folders() — เก็บ remote_state, generate และ provider config ที่แชร์กัน Terragrunt HCL and the Root Config run --all (formerly run-all/plan-all)รันคำสั่ง Terraform ข้ามทุก unit ใต้ directory ปัจจุบันตามลำดับ dependency — syntax ปัจจุบันคือ terragrunt run --all apply; รูปแบบเก่าที่แยกตาม command (terragrunt plan-all, terragrunt run-all apply) เป็นคำสั่งที่ไม่รู้จักบน Terragrunt 1.1 Running Many Units at Once
Term ความหมาย บทเรียน Secret Manager secret_data_wo คู่ write-only (Terraform 1.11+) ของ secret_data บน google_secret_manager_secret_version — ค่าถูกส่งไปหา Secret Manager โดยไม่ถูกเก็บลง state หรือ plan file เลย คู่กับ secret_data_wo_version ที่ต้องขยับเพื่อ push ค่าใหม่ Secrets and Credential Management sensitive ตั้ง variable/output ด้วย sensitive = true จะซ่อนค่าออกจาก CLI output กับ log ของ plan/apply — แต่มันยังถูกเก็บเป็น plaintext อยู่ใน state file เอง นี่คือเหตุผลที่ sensitive state ต้องมี encryption ระดับ backend ด้วย Sensitive Data and Team Workflows Sentinel / OPA policy-as-code engine ที่ evaluate output show -json ของ plan กับกฎที่องค์กรเขียนเองก่อนจะให้ apply ผ่านไปได้ — Sentinel เป็น engine built-in ของ HCP Terraform; Open Policy Agent (ผ่าน conftest) เป็นตัวแทนแบบ open-source ที่ไม่ผูกกับ platform ไหน Policy as Code and Static Analysis show -json terraform show -json <planfile> render plan (หรือ state) ที่เซฟไว้ออกมาเป็น JSON ที่เครื่องอ่านได้ — สิ่งที่ Sentinel/OPA, Infracost และ CI gate ที่เขียนเองส่วนใหญ่ parse จริง ๆ แทนที่จะ scrape output ของ plan แบบที่คนอ่านThe Terraform Workflow state record แบบ JSON (terraform.tfstate หรือของเทียบเท่าบน remote backend) ที่ map resource/module ทุกตัวใน config ไปหา object จริงที่มันจัดการ — source of truth เดียวของ Terraform ว่ามันสร้างอะไรไปแล้วบ้าง ไม่เคย derive ใหม่ด้วยการ scan cloud account เลย The State File
Term ความหมาย บทเรียน .terraform.lock.hclบันทึก provider version ที่ตรงเป๊ะและ checksum ของมัน (ทุก platform เว้นแต่ตัดออกด้วย -platform) ที่ตอบโจทย์ terraform init — commit เข้า version control ไว้เพื่อไม่ให้ init อีกครั้งบนเครื่องอื่น resolve provider build ที่ต่างกันและยังไม่ verify แบบเงียบ ๆ Module Versioning and Registries terraform graph emit dependency graph ที่ Terraform สร้างจริงสำหรับ config ปัจจุบัน ในรูปแบบ DOT ส่งต่อให้ Graphviz (terraform graph | dot -Tsvg) เพื่อดูภาพว่าทำไม resource ตัวหนึ่งถึง depend กับอีกตัว The Terraform Workflow terraform-google-modules/network v18 subnetsbreaking change ของ major version 18 ของ community VPC module ตัวนี้: subnets (list ที่บอกว่าจะสร้าง subnet อะไรบ้าง) กลายเป็น argument ที่บังคับต้องใส่ ไม่มี default ให้แล้ว — การเรียกแบบ v17 ที่ไม่ใส่มันแล้วพึ่ง auto-mode subnetting จะ plan ไม่ผ่านเลยจนกว่าจะใส่ subnets ตรง ๆ Module Versioning and Registries terraform testtest runner ที่ built-in มาให้ (ไฟล์ .tftest.hcl, Terraform 1.6+) ที่ plan และ apply ก็ได้ต่อ config จริงหรือ mock แล้ว assert ผลลัพธ์ — รันด้วย terraform test ไม่ต้องมี testing framework แยกเลย Testing Modules .tftest.hclนามสกุลไฟล์ที่ terraform test มองหา: block run หนึ่งอันหรือมากกว่า แต่ละอันมี command (plan หรือ apply) และ block assert ที่เช็ค condition กับค่าที่ plan หรือ apply ของ run นั้น Testing Modules terraform_dataresource ที่เป็น first-class ไม่ผูกกับ provider ไหน (Terraform 1.4+) เก็บค่า input/triggers_replace ที่ต้องการได้เลยโดยไม่มี infrastructure จริงอยู่ข้างหลัง — ตัวแทนของ null_resource ของ community เดิม ใช้บ่อยเพื่อบังคับให้ resource ที่ depend อยู่ถูก replace หรือพา provisioner behavior ไปด้วย Testing Modules terraform_remote_statedata source ที่อ่าน state ของ config อื่น (พร้อม output ของมัน) ตรง ๆ จาก backend ของมันเลย — เทียบเท่ากับสิ่งที่ block dependency ของ Terragrunt ทำผ่าน mock_outputs กับการเดินสายที่ generate ให้ แต่เป็น Terraform ธรรมดา Remote Backends and Locking terragrunt stack / terragrunt.stack.hcl ไฟล์ terragrunt.stack.hcl ประกาศชุด block unit/stack ที่ terragrunt stack generate ขยายออกมาเป็น directory tree ของ unit จริง (ใต้ .terragrunt-stack/) ก่อนที่ stack run จะ apply มัน — วิธี template “หนึ่ง stack ของ unit” ในระดับที่สูงกว่าการ copy-paste directory ต่อ environment Running Many Units at Once tflint linter สำหรับ Terraform source ที่จับความผิดพลาดเฉพาะ provider (machine type ที่เลิกใช้แล้ว, string ของ GCP region ที่ผิด) ที่ plan/apply จับไม่ได้ และ terraform validate — ซึ่งเช็คแค่ syntax ของ HCL กับความสอดคล้องภายใน — ก็จับไม่ได้เหมือนกัน Policy as Code and Static Analysis
Term ความหมาย บทเรียน unit ชื่อของ Terragrunt สำหรับ directory หนึ่งที่มี terragrunt.hcl หนึ่งไฟล์ บวก Terraform module ที่มันชี้ไปผ่าน terraform { source = ... } — สิ่งที่ run --all, dependency และ --filter ทำงานด้วย เทียบเท่ากับ root module ใน Terraform ธรรมดา Terragrunt HCL and the Root Config validation block validation { condition = ..., error_message = ... } ของ variable ปฏิเสธค่าที่ไม่ถูกต้องตอน plan พร้อม message ที่กำหนดเอง; ตั้งแต่ Terraform 1.9 condition นี้ reference variable ตัวอื่นได้ด้วย กฎที่ต้องเช็คข้าม variable เลยไม่ต้องหาทางเลี่ยงผ่าน precondition อีกต่อไป Input Variables variable input ที่ตั้งชื่อและมี type ให้ module หรือ root config ให้ค่าผ่าน .tfvars, -var, environment variable (TF_VAR_name) หรือ default — ทางเดียวที่ข้อมูลไหล เข้า module จากภายนอก Input Variables version constraint (~>) operator แบบ pessimistic-constraint: ~> 6.66 ยอมรับ 6.66.x (patch upgrade เท่านั้น) ส่วน ~> 6.0 ยอมรับ 6.x ทั้งหมด (minor upgrade ด้วย) — วิธีมาตรฐาน pin provider ให้หลวมพอจะได้ bugfix แต่ไม่ได้ major version ที่ breaking Module Versioning and Registries Workload Identity Federation (WIF) กลไก federated identity ของ GCP: workload identity pool + provider เชื่อถือ OIDC issuer ของ CI platform ตัวหนึ่ง ให้ pipeline impersonate service account ผ่าน token อายุสั้นได้ — ตัวแทนมาตรฐานแทนการดาวน์โหลดแล้วเก็บ service-account JSON key ไว้เป็น CI secret Secrets and Credential Management workspace กลไก built-in ของ Terraform (terraform workspace new/select) สำหรับรัน config เดียวกับ state file ที่ตั้งชื่อไว้หลายตัวบน backend เดียวกัน — คอร์สนี้สอน pattern directory-per-environment ของ Terragrunt แทน เพราะ workspace แชร์ backend config กับโค้ดเดียวกันทุก environment แบบเงียบ ๆ ซึ่งมักเป็น tradeoff ที่ผิดสำหรับ prod เทียบกับ non-prod Terraform Workspaces write-only variable/attribute ที่ marked write_only = true (Terraform 1.11+) รับค่าตอน input ได้แต่ไม่เคยถูกเก็บลง state หรือ plan file เลย คู่กับ argument _version ที่ต้องขยับเพื่อบอกว่า “ค่า write-only นี้เปลี่ยนแล้ว ส่งใหม่” Sensitive Data and Team Workflows
Mark as complete