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

Terraform中基于其他资源引用的嵌套for循环实现问题

Terraform模块中ServiceAccount角色绑定的引用问题

我有一个Terraform模块,接收名为service_accounts_objects的变量。每个对象包含创建ServiceAccount的字符串,以及该ServiceAccount需要绑定的角色列表。目前已成功创建ServiceAccount,但不知道如何引用生成的SA成员来绑定对应角色。

我知道可以通过for_each = google_service_account.service_account来引用ServiceAccount资源,但资源只能用一个for_each循环,不确定嵌套循环写法是否可行。

原尝试的模块代码

模块调用代码

module "iam" {
  source  = "../../modules/iam"
  project = var.project
  service_accounts_objects = [
    {
      service_account = "service-${var.project_short}-tl"
      roles = [
        "roles/run.invoker",
        "roles/cloudsql.client",
        "roles/cloudsql.instanceUser",
        "roles/pubsub.publisher"
      ]
    },
    {
      service_account = "service-${var.project_short}-template"
      roles = [
        "roles/cloudsql.client",
        "roles/cloudsql.instanceUser",
        "roles/pubsub.publisher"
      ]
    }
  ]
}

模块资源代码

resource "google_service_account" "service_account" {
  for_each = {
    for index, sa in var.service_accounts_objects:
      sa.service_account => sa
  }
  project = var.project
  account_id = each.value.service_account
}

resource "google_project_iam_member" "member" {
  for_each = {
    for i, role in var.service_accounts_objects: 
      role.roles => role
    for j, members in google_service_account.service_account:
      members.member => members
  }
  member  = each.value.member
  project = var.project
  role    = each.value.role
}

补充的解决方案(单独调用模块)

因为没找到可行的嵌套循环方法,我改为为每个ServiceAccount单独调用模块:

模块调用代码

module "iam-service-tl" {
  source  = "../../modules/iam"
  project = var.project
  service_account_object = {
    service_account = "sa-service-tl"
    roles = [
      "roles/run.invoker",
      "roles/cloudsql.client",
      "roles/cloudsql.instanceUser",
      "roles/pubsub.publisher"
    ]
  }
}

模块变量及资源代码

variable "project" {}
variable "service_account_object" {
  description = "要创建的ServiceAccount信息"
  type = object(
    {
      service_account = string
      roles           = list(string)
    }
  )
}

resource "google_service_account" "service_account" {
  project    = var.project
  account_id = var.service_account_object.service_account
}

resource "google_project_iam_member" "member" {
  member  = google_service_account.service_account.member
  project = var.project
  for_each = toset(var.service_account_object.roles)
  role = each.value
}

最优批量处理写法

其实不需要拆分模块,通过扁平化ServiceAccount与角色的组合就能实现批量绑定,避免重复调用模块:

# 原ServiceAccount创建代码不变
resource "google_service_account" "service_account" {
  for_each = {
    for sa in var.service_accounts_objects:
      sa.service_account => sa
  }
  project    = var.project
  account_id = each.value.service_account
}

# 扁平化生成每个SA+角色的唯一组合
locals {
  sa_role_combinations = flatten([
    for sa_id, sa in google_service_account.service_account:
      [for role in sa.value.roles:
        {
          sa_id  = sa_id
          role   = role
          member = sa.member
        }
      ]
  ])
}

# 基于扁平化后的组合创建IAM绑定
resource "google_project_iam_member" "member" {
  for_each = {
    for combo in local.sa_role_combinations:
      "${combo.sa_id}-${combo.role}" => combo
  }
  member  = each.value.member
  project = var.project
  role    = each.value.role
}

说明

  • 使用flatten将每个ServiceAccount的角色列表展开为单个SA+角色的对象,确保每个IAM绑定都是唯一的
  • 通过"${combo.sa_id}-${combo.role}"作为for_each的键,避免重复资源
  • 直接引用google_service_account.service_account的member属性,无需复杂嵌套循环

内容的提问来源于stack exchange,提问作者José Lacerda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 12:05:07