在前面幾天,我們從概念著手了解了 Terraform 的運作方式、狀態檔、Remote State,再一步步練習實作,從建立 VM、設定 Provider、活用 Variables 與 Data Sources 到輸出 Outputs。
不過目前的這些練習大多是「單點操作」:一個 VM、一個 Bucket,或是查詢單一資源資訊。
而今天要談的 資源建立順序,就是把這些零散的元件「串起來」的最後一塊拼圖。因為在真實環境裡,資源往往不是孤立存在的,而是彼此有上下游依賴:VM 要依賴 VPC、CI/CD 要依賴 Bucket、Database 要在初始化前先啟動。
我們可以想像一下:
這樣會發生什麼?結果是錯誤、重試、甚至 pipeline 卡住。
而 Terraform 提供了兩種方式來管理資源之間的關係:隱含依賴(implicit dependencies) 與 顯式依賴(depends_on)。
Terraform 很聰明,只要你在資源參數中引用了另一個資源的屬性,它就會自動知道兩者之間的依賴關係。
resource "google_compute_network" "vpc" {
name = "my-vpc"
}
resource "google_compute_instance" "vm" {
name = "my-vm"
machine_type = "e2-micro"
zone = "asia-east1-b"
network_interface {
network = google_compute_network.vpc.name
}
}
這裡 VM 需要用到 VPC 的名稱,Terraform 會自動判斷出:必須先建立 VPC,才能建立 VM。
我們不需要寫任何 depends_on
。因為大部分情況下,隱含依賴就足夠了!
問題是有些時候「參數沒有引用到資源」,但實際上卻有依賴關係。
這時候 Terraform 就沒辦法自己推導,需要我們手動加上 depends_on
。
resource "google_storage_bucket" "bucket" {
name = "my-app-bucket"
location = "ASIA"
}
resource "null_resource" "notify" {
provisioner "local-exec" {
command = "echo 'Bucket 建立完成!'"
}
depends_on = [google_storage_bucket.bucket]
}
這裡的 null_resource
沒有直接用到 bucket.name
,所以 Terraform 不會自動建立依賴關係。
但我們邏輯上需要等 Bucket 建好,才去通知或做後續流程,因此必須手動加上 depends_on
。
當我們幫資源加 IAM 權限時,Terraform 可能會同時執行「建立資源」和「設定 IAM」,導致 Race Condition。
resource "google_storage_bucket" "bucket" {
name = "my-app-bucket"
location = "ASIA"
}
resource "google_storage_bucket_iam_binding" "binding" {
bucket = google_storage_bucket.bucket.name
role = "roles/storage.admin"
members = ["user:dev@example.com"]
depends_on = [google_storage_bucket.bucket]
沒有 depends_on
可能會發生錯誤:「Bucket 還不存在,但 IAM 綁定已經在跑」。
很多人第一次踩坑的地方就是 Cloud SQL 或 RDS。
resource "null_resource" "init_db" {
provisioner "local-exec" {
command = "psql -h ${google_sql_database_instance.db.public_ip_address} -U root -d mydb -f init.sql"
}
depends_on = [google_sql_database_instance.db]
}
如果沒有加 depends_on
,Terraform 可能會同時建立 DB instance 和跑初始化 SQL,結果就是:
「連不到 DB」→ pipeline 失敗。
團隊在 CI/CD 裡跑 Terraform 建立 GCS Bucket,然後立刻執行測試去上傳檔案。
結果 Terraform 還在建立 Bucket 的時候,測試就已經跑起來,當然會失敗。
解法就是:
depends_on
,確保測試資源在 Bucket 後才跑terraform output
確認資源存在後再繼續整理幾點建議供大家參考:
Terraform 的資源關係管理就是在確保:
實務上,80% 情況靠隱含依賴就夠了,但那 20% 沒處理好,往往就是 CI/CD pipeline 裡最難 debug 的「隱藏炸彈」。所以能掌握好這個觀念,就能避免資源建立的 Race Condition,讓 Terraform 配置更穩定、更可預期~
🐈🐈🐈
好啦~學到這裡 Terraform 的基礎操作就告一段落了,目前累積的這些能力已經足以在專案裡建立一些小型基礎設施。不過,當專案開始變大,或多人協作時,光靠這些單一檔案的寫法很快就會變得混亂。這時候就需要更進一步的技巧 —— 模組化(Modules)與專案架構設計。
所以!明天我們要進入 模組與架構篇 的實作練習,一起來看看如何把這些基礎能力組織成更有結構、可重複使用的 Terraform 專案~🤩