全部產品
Search
文件中心

Terraform:depends_on

更新時間:Mar 22, 2025

本文檔介紹了 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,可前往瞭解更多細節。