Dependencies Between Units
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”dependency block ทำให้ unit หนึ่งอ่าน output ของอีก unit ข้าม state boundary ที่แยกทั้งสองออกจากกันได้ และ Terragrunt ก็ใช้ block เดียวกันนี้คำนวณลำดับที่ unit ต่าง ๆ ต้องถูก apply
ทำไม module composition ถึงไม่พอแล้ว
หัวข้อที่มีชื่อว่า “ทำไม module composition ถึงไม่พอแล้ว”ใน module Modules คุณเห็น output-to-input composition แล้ว output ของ module หนึ่งป้อนตรงเข้า input argument ของอีก module ภายใน main.tf เดียว evaluate เป็น Terraform plan เดียวกับ state ไฟล์เดียว วิธีนั้นทำงานได้เพราะทั้งสอง module อยู่ใน apply เดียวกัน
Terragrunt unit ตั้งใจทำลาย assumption นั้นทิ้ง unit vpc กับ unit ec2 ต่างมี terragrunt.hcl ของตัวเองและ state ไฟล์แยกของตัวเอง apply กันอย่างอิสระ module.vpc.outputs.vpc_id ที่อ้างอิงตรง ๆ แบบตอนอยู่ใน Terraform config เดียว จากมุมมองของ unit ec2 reference นั้นไม่มีอยู่จริงเลย เพราะไม่มี config ไฟล์ที่ share กันให้ reference นั้นอยู่ข้างใน ต้องมีอะไรสักอย่างอ่านข้าม state boundary นั้นตรง ๆ และสิ่งนั้นคือ dependency block
dependency: อ่านข้าม state boundary
หัวข้อที่มีชื่อว่า “dependency: อ่านข้าม state boundary”include "root" { path = find_in_parent_folders("root.hcl")}
terraform {}
dependency "vpc" { config_path = "../vpc"
mock_outputs = { vpc_id = "mock-vpc-id" }
mock_outputs_allowed_terraform_commands = ["plan"]}
inputs = { vpc_id = dependency.vpc.outputs.vpc_id}config_path ชี้ไปที่ directory ของอีก unit หนึ่ง ไม่ใช่ Terraform module แต่เป็น Terragrunt unit ก่อนรัน Terragrunt จะรัน terraform output กับ state จริงของ unit นั้น แล้ว expose ทุก output ที่เจอเป็น dependency.vpc.outputs.<name> ให้ใช้ได้ทุกที่ใน config ของ unit นี้ รวมถึงข้างใน inputs ด้วย
mock_outputs: ทำให้ plan สำเร็จได้ก่อน dependency จะมีจริง
หัวข้อที่มีชื่อว่า “mock_outputs: ทำให้ plan สำเร็จได้ก่อน dependency จะมีจริง”dependency.vpc.outputs.vpc_id จะมีค่าจริงก็ต่อเมื่อ unit vpc ถูก apply ไปแล้วอย่างน้อยหนึ่งครั้ง มีสองสถานการณ์ที่ทำลาย assumption นี้ คือตอนตั้ง environment ใหม่เอี่ยมครั้งแรก ที่ยังไม่มีอะไรถูก apply เลย และตอน CI validate pull request ที่แก้แค่ไฟล์ของ unit ec2 ซึ่งไม่มีใครอยากให้ plan fail แค่เพราะ unit อื่นที่ไม่เกี่ยวข้องยังไม่ถูก apply ใน environment นั้น
mock_outputs มาปิด gap นี้พอดี โดยให้ค่า placeholder ที่ Terragrunt สลับใช้แทนทุกครั้งที่ output จริงยังไม่มี และ mock_outputs_allowed_terraform_commands จำกัดว่า command ไหนถึง fallback ไปใช้ค่านั้นได้ ["plan"] ข้างบนแปลว่า plan บน ec2 สำเร็จได้ด้วย vpc_id = "mock-vpc-id" แม้ยังไม่มี state จริงของ vpc เลย ส่วน apply ยังคงปฏิเสธไม่ยอมรันกับค่าปลอม และบังคับให้ dependency จริงถูก apply ก่อนเสมอ
Terragrunt คำนวณลำดับ unit ให้เองอัตโนมัติยังไง
หัวข้อที่มีชื่อว่า “Terragrunt คำนวณลำดับ unit ให้เองอัตโนมัติยังไง”Terraform เองก็คำนวณลำดับการรันภายใน state เดียวอยู่แล้ว คือ dependency graph ระหว่าง resource แต่ละตัว dependency block ส่งข้อมูลแบบเดียวกันนี้ให้ Terragrunt ในระดับที่สูงขึ้นมาอีกชั้น คือระหว่าง unit ทั้งก้อน เพราะ ec2 ประกาศ dependency ไปที่ vpc Terragrunt ก็รู้ว่าต้อง apply vpc ก่อน ขยายแบบนี้ไปทั่ว tree ที่มีหลายสิบ unit จริง ๆ Terragrunt จะสร้างกราฟเต็มรูปแบบจากทุก dependency block ที่เจอ แล้วเดินตามลำดับที่ถูกต้องเวลามี command ไหนก็ตามที่แตะมากกว่าหนึ่ง unit พร้อมกัน ซึ่งจะพูดถึงเต็ม ๆ ในบทถัดไป โดยไม่ต้องมีใครจำหรือ maintain ลำดับนั้นด้วยมือเอง
flowchart LR vpcstate["vpc unit state (applied separately)"] --> vpcout["vpc outputs: vpc_id"] vpcout --> dep["ec2 terragrunt.hcl: dependency vpc block"] dep --> ecin["ec2 inputs: vpc_id = dependency.vpc.outputs.vpc_id"] mock["mock_outputs: vpc_id = mock-vpc-id"] -.->|lets plan succeed before vpc is applied| dep