ศัพท์ของคอร์สนี้ครอบคลุมสามชั้น: Terraform core (resource, provider, state, module, plan/apply/destroy) ที่ทำงานเหมือนกันทุก cloud; Terragrunt (unit, dependency, root config, stack) ที่ทำให้หลาย environment ยังคง DRY; และส่วนที่เฉพาะ Azure (blob-lease locking ของ azurerm backend, Azure Verified Modules, Key Vault) ที่จะเข้าใจได้ก็ต่อเมื่อรู้ว่ากำลังอ่าน provider ไหนอยู่ เวลาอ่านบทเรียนแล้วเจอคำที่ไม่คุ้น หรือไม่แน่ใจว่ายังใช้ได้อยู่กับ Terraform 1.16 / Terragrunt 1.1 ไหม ให้กลับมาดูที่นี่
Term ความหมาย บทเรียน apply terraform apply รัน action ทั้งหมดในแผนต่อ infrastructure จริง — เป็นคำสั่งเดียวใน core workflow ที่ create, update หรือ destroy อะไรจริง ๆ; ถ้าไม่มี plan file ที่เซฟไว้ มันจะสร้างให้ก่อนแล้วถาม confirmThe Terraform Workflow Azure Verified Modules (AVM) module catalog ที่ Microsoft support อย่างเป็นทางการ publish เข้า Terraform Registry ในชื่อ Azure/avm-res-<provider>-<resource>/azurerm (เช่น Azure/avm-res-keyvault-vault/azurerm) — ตัวแทนของ module จาก community อย่าง Azure/vnet ที่ archived ไปแล้ว ทดสอบและดูแลโดย Microsoft เองโดยตรงแทนที่จะเป็น community Module Versioning and Registries Azure/vnet (archived)module จาก community registry ที่เคยเป็นวิธี default ในการสร้าง VNet — ตอนนี้ archived แล้วหันไปใช้ Azure Verified Modules แทน บทเรียนหรือโปรเจกต์จริงที่ pin มันไว้วันนี้คือ pin module ที่ไม่ได้รับ fix แล้ว Module Versioning and Registries azurerm vs azapi azurerm คือ provider ที่ mature และ curate ครอบคลุม resource ส่วนใหญ่ของ Azure ด้วย schema ที่ออกแบบมาให้ใช้ง่าย; azapi map เข้ากับ Azure Resource Manager REST API เกือบตรง ๆ แทน ทำให้เข้าถึง resource ใหม่หรือ preview ได้ก่อนที่ azurerm จะรองรับแบบเต็มตัวHCL, Providers, and Resources backend plugin ที่ตัดสินว่า state ของ Terraform เก็บ ที่ไหน และ operation ที่ทำกับมันถูก lock ยังไง — config ครั้งเดียวใน block terraform { backend "azurerm" {} }; เปลี่ยน argument ใน block ต้องรัน terraform init ใหม่ (ใส่ -migrate-state ถ้าจะย้าย state เดิม) Remote Backends and Locking
Term ความหมาย บทเรียน 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 มาให้ (storage container ที่เปิดให้เข้าถึงแบบ public, managed disk ที่ไม่เข้ารหัส, NSG ที่เปิดกว้างเกินไป, …) — รันผ่าน checkov -d . หรือ GitHub Action ของมัน ซึ่งต้อง pin ไว้ที่ ref ใดหนึ่ง ไม่ใช้ @master เพราะมันเปลี่ยน policy แบบ breaking ได้ทุกครั้งที่ push Policy as Code and Static Analysis configuration_aliasesประกาศไว้ใน required_providers block ของ module ระบุชื่อ provider alias (เช่น azurerm.westeurope, azurerm.eastus) ที่ 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 "azurerm_image" "..." {}) ที่ดึงข้อมูลเกี่ยวกับ resource ที่ Terraform ไม่ได้จัดการ — ไม่ว่าจะเป็นของที่มีอยู่แล้ว (VNet ที่แชร์กัน) หรือค่าที่ provider คำนวณให้ (image ID ที่ตรงกับ filter) — และ Terraform จะไม่มีวัน create, update หรือ destroy มันได้เอง 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 กับสิ่งที่มีอยู่จริงใน Azure — เกิดจากการเปลี่ยนผ่าน 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 features {}block ที่ต้องมีข้างใน config ของ azurerm provider (จะเว้นว่างหรือใส่ sub-block ปรับพฤติกรรม resource เฉพาะตัวก็ได้ เช่น resource_group { prevent_deletion_if_contains_resources }) — terraform init/plan ปฏิเสธที่จะรันเลยถ้าไม่มีมัน แม้จะเว้นว่างไว้ก็ตาม HCL, Providers, and Resources --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 ความหมาย บทเรียน 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 HCP Terraform แพลตฟอร์ม remote-execution ที่ HashiCorp จัดการให้ (เดิมชื่อ Terraform Cloud): รัน plan/apply บน worker ของตัวเอง, เก็บ state และกั้น apply ไว้หลัง approval กับ Sentinel policy — ทางเลือกแบบ managed แทนการ self-host azurerm 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 ความหมาย บทเรียน Key Vault (azurerm_key_vault) ที่เก็บ secret/key/certificate ที่ Azure จัดการให้; azurerm_key_vault_secret คือ resource ที่บทเรียนใช้เขียนค่าเข้าไป — การเข้าถึงคุมด้วย access policy แบบเก่า หรือถ้าเป็น vault ใหม่คุมด้วย Azure RBAC role assignment บนตัว vault เอง Secrets and Credential Management 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 ของ azurerm backend คือ blob lease ที่ขอบน state blob เอง — เปิดใช้ให้โดย default ไม่ต้องสร้าง lock resource แยกเลย ต่างจากประวัติของ S3 backend ที่เคยต้องพึ่ง DynamoDB table Remote Backends and Locking
Term ความหมาย บทเรียน Managed Identity (system vs user-assigned) identity ของ Azure AD ที่แนบกับ resource (VM, Function App) ให้มัน authenticate กับ Azure service อื่นได้โดยไม่ต้องเก็บ credential ใด ๆ เลย — แบบ system-assigned ถูกสร้างและลบไปพร้อม resource; แบบ user-assigned เป็น resource แยกตัวเองที่แชร์กันหลาย resource ได้ Secrets and Credential Management 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 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 = azurerm.westeurope — วิธีที่ config เดียวจัดการ resource ข้ามเช่นสองภูมิภาคของ Azure ใน 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 อย่าง Azure/avm-res-network-virtualnetwork/azurerm resolve มาจากที่นี่โดย default ไม่ต้องใส่ Git URL เต็ม Module Versioning and Registries remote_state block remote_state { backend = "azurerm" ... } ของ Terragrunt generate backend block ของ Terraform ที่เทียบเท่ากันให้ทุก unit ที่ include มัน เก็บ config storage account/container/key ไว้ที่เดียวจริง ๆ แทนที่จะ 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 = [azurerm_linux_virtual_machine_scale_set.this] บังคับให้ resource นี้ถูก replace ทุกครั้งที่ resource/attribute ที่ reference ไว้เปลี่ยน — แม้ argument ของ resource นี้เองจะไม่ได้เปลี่ยนอะไรเลยก็ตาม HCL, Providers, and Resources resource building block หลัก: block resource "azurerm_linux_virtual_machine" "this" {} ประกาศ object จริงหนึ่งตัวที่ถูกจัดการ ซึ่ง lifecycle เต็ม (create/read/update/delete) ของมัน Terraform เป็นเจ้าของทั้งหมดตั้งแต่ต้นจนจบ HCL, Providers, and Resources resource group (azurerm_resource_group) ตู้คอนเทนเนอร์ที่ resource อื่นทุกตัวของ Azure ในคอร์สนี้อยู่ข้างใน คุมทั้งการลบ (ลบ group ก็ลบทุกอย่างข้างในไปด้วย), การเข้าถึง (scope ที่ใช้ตั้ง RBAC บ่อย ๆ) และมักเป็นค่า default ของ location ให้ resource ที่ไม่ได้ตั้งของตัวเองด้วย 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 ความหมาย บทเรียน 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 storage account backend lease กลไกเบื้องหลัง locking ที่ built-in ของ azurerm backend: Terraform ขอ blob lease บน state blob ใน storage account/container ที่ config ไว้ก่อนจะเขียน แล้วปล่อยคืนเมื่อ operation จบ — ไม่ต้องสร้าง lock resource หรือ table แยกเลย ต่างจากประวัติของ S3 backend ที่เคยพึ่ง DynamoDB Remote Backends and Locking subscription_idargument ที่ต้องใส่ตรง ๆ บน block azurerm provider ระบุว่า resource ทุกตัวใน config นี้ถูกสร้างใน Azure subscription ไหน — ถ้าไม่ใส่แล้วปล่อยให้ใช้ subscription ที่ Azure CLI ล็อกอินอยู่ตอนนั้น เป็นสาเหตุที่พบบ่อยที่ plan ไปรันผิด subscription HCL, Providers, and Resources
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 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 (VM SKU ที่เลิกใช้แล้ว, string ของ Azure 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 use_oidc / use_cli (provider auth)flag แบบ boolean บน config ของ azurerm provider (และ backend) เลือกว่ามัน authenticate ยังไง — use_oidc สำหรับ token แบบ federated จาก CI, use_cli สำหรับ identity ที่ az login ตั้งไว้ในเครื่องอยู่แล้ว — แทนที่จะเป็น client secret แบบ static ที่นอนอยู่ใน variable หรือ CI secret store Remote Backends and Locking 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 (OIDC for CI) การ implement federated identity ของ Azure: federated credential บน App Registration เชื่อถือ OIDC issuer/subject ของ CI platform ตัวใดตัวหนึ่งโดยเฉพาะ ทำให้ pipeline แลก token อายุสั้นของตัวเองกับ Azure AD access token ได้ — กลไกเฉพาะของ Azure ที่อยู่เบื้องหลังศัพท์ทั่วไป OIDC 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