You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过传入变量让Terraform动态引用资源或数据源块?

问题描述

我在一个Terraform工作区中有一个Kafka集群,希望通过Terraform创建并管理它,同时在另一个工作区中引用该集群。现咨询是否可实现下述理想配置——通过传入变量让Terraform动态引用资源块或数据源块,从而简化重复配置。

现有配置

main.tf

resource "confluent_environment" "env" {
  display_name = var.env_name
}

// cluster type for dev-main and dev-qa => basic
// cluster type for prod => standard
resource "confluent_kafka_cluster" "cluster" {
  count = var.env_name != "prod-data" ? 1 : 0
  display_name = "${var.env_name}-cluster"
  availability = "SINGLE_ZONE"
  cloud        = "AWS"
  region       = "us-east-1"

  dynamic "basic" {
    for_each = var.env_name != "prod" ? [1] : []
    content {}
  }
  dynamic "standard" {
    for_each = var.env_name == "prod" ? [1] : []
    content {}
  }

  environment {
    id = confluent_environment.env.id
  }
}

// 'app-manager' service account is required in this configuration to create topics and create service accounts
resource "confluent_service_account" "app_manager" {
  count = var.env_name != "prod-data" ? 1 : 0
  display_name = "${var.env_name}-app-manager"
  description  = "Service account to manage Kafka cluster"
}

resource "confluent_role_binding" "app_manager_kafka_cluster_admin" {
  count = var.env_name != "prod-data" ? 1 : 0
  principal   = "User:${confluent_service_account.app_manager.id}"
  role_name   = "CloudClusterAdmin"
  crn_pattern = confluent_kafka_cluster.cluster.rbac_crn
}

prod_data_main.tf

data "confluent_kafka_cluster" "cluster" {
  count = var.env_name == "prod-data" ? 1 : 0

  display_name = "prod-cluster"
  environment {
    id = confluent_environment.env.id
  }
}

// create service accounts
resource "confluent_service_account" "app_manager_prod_data" {
  count = var.env_name == "prod-data" ? 1 : 0
  display_name = "${var.env_name}-app-manager"
  description  = "Service account to manage Kafka cluster"
}

resource "confluent_role_binding" "app_manager_kafka_cluster_admin_prod_data" {
  count = var.env_name == "prod-data" ? 1 : 0
  principal   = "User:${confluent_service_account.app_manager_prod_data.id}"
  role_name   = "CloudClusterAdmin"
  crn_pattern = data.confluent_kafka_cluster.cluster.rbac_crn
}
理想配置效果
locals {
  crn_pattern = var.env_name != "prod-data" ? "confluent_kafka_cluster.cluster.rbac_crn" : "data.confluent_kafka_cluster.cluster.rbac_crn"
} 

resource "confluent_environment" "env" {
  display_name = var.env_name
}

// cluster type for dev-main and dev-qa => basic
// cluster type for prod => standard
resource "confluent_kafka_cluster" "cluster" {
  count = var.env_name != "prod-data" ? 1 : 0
  display_name = "${var.env_name}-cluster"
  availability = "SINGLE_ZONE"
  cloud        = "AWS"
  region       = "us-east-1"

  dynamic "basic" {
    for_each = var.env_name != "prod" ? [1] : []
    content {}
  }
  dynamic "standard" {
    for_each = var.env_name == "prod" ? [1] : []
    content {}
  }

  environment {
    id = confluent_environment.env.id
  }
}

data "confluent_kafka_cluster" "cluster" {
  count = var.env_name == "prod-data" ? 1 : 0

  display_name = "prod-cluster"
  environment {
    id = confluent_environment.env.id
  }
}

// 'app-manager' service account is required in this configuration to create topics and create service accounts
resource "confluent_service_account" "app_manager" {
  display_name = "${var.env_name}-app-manager"
  description  = "Service account to manage Kafka cluster"
}

resource "confluent_role_binding" "app_manager_kafka_cluster_admin" {
  principal   = "User:${confluent_service_account.app_manager.id}"
  role_name   = "CloudClusterAdmin"
  crn_pattern = local.crn_pattern
}
实现方案

你的理想配置思路完全可行,但需要调整local.crn_pattern的写法——不能直接用字符串引用资源属性,得通过Terraform的条件表达式直接引用对应资源/数据源的属性值。

修正后的完整配置如下:

locals {
  # 根据环境变量选择对应集群的CRN
  cluster_crn = var.env_name != "prod-data" ? confluent_kafka_cluster.cluster[0].rbac_crn : data.confluent_kafka_cluster.cluster[0].rbac_crn
} 

resource "confluent_environment" "env" {
  display_name = var.env_name
}

// cluster type for dev-main and dev-qa => basic
// cluster type for prod => standard
resource "confluent_kafka_cluster" "cluster" {
  count = var.env_name != "prod-data" ? 1 : 0
  display_name = "${var.env_name}-cluster"
  availability = "SINGLE_ZONE"
  cloud        = "AWS"
  region       = "us-east-1"

  dynamic "basic" {
    for_each = var.env_name != "prod" ? [1] : []
    content {}
  }
  dynamic "standard" {
    for_each = var.env_name == "prod" ? [1] : []
    content {}
  }

  environment {
    id = confluent_environment.env.id
  }
}

data "confluent_kafka_cluster" "cluster" {
  count = var.env_name == "prod-data" ? 1 : 0

  display_name = "prod-cluster"
  environment {
    id = confluent_environment.env.id
  }
}

// 'app-manager' service account is required in this configuration to create topics and create service accounts
resource "confluent_service_account" "app_manager" {
  display_name = "${var.env_name}-app-manager"
  description  = "Service account to manage Kafka cluster"
}

resource "confluent_role_binding" "app_manager_kafka_cluster_admin" {
  principal   = "User:${confluent_service_account.app_manager.id}"
  role_name   = "CloudClusterAdmin"
  crn_pattern = local.cluster_crn
}

关键调整点:

  • 把local.crn_pattern改为直接引用资源/数据源的属性值,而非字符串。因为Terraform会在执行阶段解析资源属性,字符串无法识别为资源引用。
  • 由于资源和数据源都用了count,需要通过索引[0]来访问唯一实例的属性(因为count只会是0或1)。
  • 移除了重复的服务账号和角色绑定资源,通过统一的confluent_service_account.app_manager和confluent_role_binding.app_manager_kafka_cluster_admin实现多环境适配。

这样配置后,当var.env_name为prod-data时,Terraform会使用数据源引用现有集群;其他环境则创建新集群,同时统一管理服务账号和角色绑定,完全实现你想要的简化效果。

内容的提问来源于stack exchange,提问作者AlexLordThorsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:57:09