本文檔介紹了 depends_on 的用法、使用情境、處理機制以及在阿里雲環境中的具體樣本
概述
depends_on 是 Terraform 中的一個元參數,用於明確聲明資源或模組之間的依賴關係,處理 Terraform 無法自動推斷的隱藏資源或模組依賴關係。
在 Terraform 的工作流程中,大多數依賴關係是通過隱式引用(一個資源的屬性值使用另一個資源的屬性)自動推斷的,但有些依賴關係無法被 Terraform 自動檢測。只有當資源或模組(Module) 依賴於另一個資源的行為,但在其參數中沒有訪問該資源的任何屬性時,才需要顯式指定依賴關係。例如,當一個資源的功能依賴於另一個資源或者模組的完整建立,但在代碼中沒有直接引用該資源或者模組時,就需要使用 depends_on。
本文檔介紹了 depends_on 的用法、使用情境、處理機制以及在阿里雲環境中的具體樣本。通過正確使用 depends_on,可以確保資源按照預期順序建立和銷毀,避免由於依賴關係不明確而導致的部署問題。
使用須知
depends_on 元參數指示 Terraform 在執行聲明依賴關係的對象的操作之前,完成依賴對象上的所有操作(包括讀取操作)。當依賴對象是整個模組時,depends_on 會影響 Terraform 處理與該模組關聯的所有資源和資料來源的順序。
應將 depends_on 作為最後的手段,因為它可能導致 Terraform 建立更保守的計劃,替換比必要更多的資源。例如,由於不確定上遊對象會發生什麼變化,Terraform 可能會將更多值視為未知("known after apply")。當您為模組使用 depends_on 時,這種情況尤其可能發生。
我們建議在可能的情況下使用運算式引用來隱式表達依賴關係,而不是使用 depends_on。運算式引用讓 Terraform 瞭解引用來自哪個值,並且即使上遊對象的其他部分有計劃的更改,如果該特定值沒有更改,也可以避免計劃更改。
使用方法
您可以在Module塊和所有資源塊中使用 depends_on 元參數,無論資源類型如何。它需要對同一調用模組中的其他資源或子模組的引用列表。此列表不能包含任意運算式,因為 Terraform 需要在瞭解資源關係之前知道 depends_on 值,因此也必須在安全評估運算式之前知道。
我們建議始終包含一個注釋,解釋為什麼使用 depends_on 是必要的。
資源間依賴樣本
以下樣本使用 depends_on 處理對 RAM 角色策略附加的"隱藏"依賴:
# 建立 RAM 角色
resource "alicloud_ram_role" "example" {
name = "terraform-example"
description = "Example role for demonstrating depends_on"
document = <<EOF
{
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": [
"ecs.aliyuncs.com"
]
}
}
],
"Version": "1"
}
EOF
}
# 附加系統策略到 RAM 角色
resource "alicloud_ram_role_policy_attachment" "system_policy" {
policy_name = "AliyunOSSReadOnlyAccess"
policy_type = "System"
role_name = alicloud_ram_role.example.name
}
# 建立自訂策略
resource "alicloud_ram_policy" "custom_policy" {
policy_name = "example-custom-policy"
description = "Custom policy for OSS access"
policy_document = <<EOF
{
"Statement": [
{
"Action": "oss:GetObject",
"Effect": "Allow",
"Resource": "acs:oss:*:*:example-bucket/*"
}
],
"Version": "1"
}
EOF
}
# 將自訂策略附加到角色
resource "alicloud_ram_role_policy_attachment" "custom_policy_attachment" {
policy_name = alicloud_ram_policy.custom_policy.name
policy_type = "Custom"
role_name = alicloud_ram_role.example.name
}
# 建立 ECS 執行個體
resource "alicloud_instance" "example" {
instance_name = "tf-example"
instance_type = "ecs.s6-c1m2.small"
image_id = "aliyun_2_1903_x64_20G_alibase_20230523.vhd"
vswitch_id = "vsw-abc123456"
# Terraform 可以從此推斷執行個體與角色之間的依賴關係
role_name = alicloud_ram_role.example.name
# 然而,如果在此 ECS 執行個體中啟動並執行軟體需要特定的角色許可權才能正常啟動
# (例如,需要從 OSS 讀取啟動配置),那麼還存在對策略附加的"隱藏"依賴關係,
# Terraform 無法自動推斷,因此必須顯式聲明:
depends_on = [
alicloud_ram_role_policy_attachment.system_policy,
alicloud_ram_role_policy_attachment.custom_policy_attachment
]
}模組間依賴樣本
當一個模組的功能依賴於另一個模組的完整部署,但沒有直接引用其輸出時:
# 部署基礎網路模組
module "network" {
source = "./modules/network"
vpc_cidr = "10.0.0.0/16"
# 其他參數...
}
# 部署安全性群組模組
module "security_groups" {
source = "./modules/security_groups"
vpc_id = module.network.vpc_id
# Terraform 可以推斷此依賴,因為我們引用了網路模組的輸出
}
# 部署應用模組
module "application" {
source = "./modules/application"
subnet_ids = module.network.subnet_ids
sg_id = module.security_groups.app_sg_id
# 如果應用部署需要等待特定的資料庫初始化過程完成,
# 但沒有直接引用資料庫模組的任何輸出,則需要顯式依賴
depends_on = [
module.database
]
}
# 部署資料庫模組
module "database" {
source = "./modules/database"
subnet_ids = module.network.database_subnet_ids
sg_id = module.security_groups.db_sg_id
}通過明智地使用 depends_on,您可以確保資源按正確的順序建立,即使它們之間的依賴關係不明顯。但請記住,始終優先使用直接引用來建立依賴關係,僅在真正需要時才使用 depends_on。
註:本文參考自 Terraform 官方文檔 depends_on,可前往瞭解更多細節。