在 terraform 中循环跨模块
loop across modules in terraform
我需要在 GCP 中构建大约 30 个发布子主题,为发布子主题创建每个模块是一个繁琐的过程,有没有更好的处理方法?
module "a" {
source = ""
project_id = var.project_id
topic = var.a["topic_name"]
topic_labels = var.a["topic_labels"]
pull_subscriptions = [
{
name = var.a["pull_subscription_name"]
ack_deadline_seconds = var.a["ack_deadline_seconds"]
max_delivery_attempts = var.a["max_delivery_attempts"]
maximum_backoff = var.maximum_backoff
minimum_backoff = var.minimum_backoff
expiration_policy = var.expiration_policy
enable_message_ordering = true
}
]
}
module "b" {
source = ""
project_id = var.project_id
topic = var.b["topic_name"]
topic_labels = var.b["topic_labels"]
pull_subscriptions = [
{
name = var.b["pull_subscription_name"]
ack_deadline_seconds = var.b["ack_deadline_seconds"]
max_delivery_attempts = var.b["max_delivery_attempts"]
maximum_backoff = var.maximum_backoff
minimum_backoff = var.minimum_backoff
expiration_policy = var.expiration_policy
enable_message_ordering = true
}
]
}
在 tfvars 中将值传递给上述模块,如下所示:
a = {
topic_name = "abc"
topic_labels = { env : "prod", purpose : "a" }
pull_subscription_name = "abc-sub"
ack_deadline_seconds = 600
max_delivery_attempts = 3
}
b = {
topic_name = "bcd"
topic_labels = { env : "prod", purpose : "b" }
pull_subscription_name = "bcd-sub"
ack_deadline_seconds = 600
max_delivery_attempts = 3
}
我们能否以某种方式组合 tfvars 中的变量并传入单个模块?
我还想知道维护上述 terraform 脚本以单独保存它们或利用一个模块创建 50 个主题的最佳实践?
谢谢!
您可以为模块使用 for_each
元参数:
https://www.terraform.io/docs/language/meta-arguments/for_each.html
您的变量可以是 for_each
可以通过的一组地图。
话虽这么说,这可能会变得过于复杂,IaC 的一个重要方面是保持简单和明确,因为它在某种程度上是自我记录(这不是省略记录您的工作的正当理由) .
对于两个单独的变量,您的选择有点受限,因为 Terraform 无法将这两个单独的变量视为以系统方式连接。 (每个变量,与 Terraform 中的其他对象一样,完全独立于解决依赖性的观点。)
但是,如果您可以将其重组为地图类型的单个变量,那么您可以使用 resource for_each
系统地为地图的每个元素声明一个实例:
variable "topics" {
type = map(object({
labels = map(string)
pull_subscription_name = string
ack_deadline_seconds = number
max_delivery_attempts = number
}))
}
module "topic" {
source = "..."
for_each = var.topics
project_id = var.project_id
topic = each.key
topic_labels = each.value.labels
pull_subscriptions = [
{
name = each.value.pull_scription_name
ack_deadline_seconds = each.value.ack_deadline_seconds
max_delivery_attempts = each.value.max_delivery_attempts
maximum_backoff = var.maximum_backoff
minimum_backoff = var.minimum_backoff
expiration_policy = var.expiration_policy
enable_message_ordering = true
}
]
}
对于此示例,我假设您的 topic_name
属性将是实例的合适的唯一键,因此我将其从声明的对象类型中删除,目的是将其放入映射键中。换句话说,此 topics
变量的值应如下所示:
topics = {
abc = {
labels = { env = "prod", purpose = "a" }
pull_subscription_name = "abc-sub"
ack_deadline_seconds = 600
max_delivery_attempts = 3
}
bcd = {
labels = { env = "prod", purpose = "b" }
pull_subscription_name = "bcd-sub"
ack_deadline_seconds = 600
max_delivery_attempts = 3
}
}
由此,Terraform 将了解您打算使用以下地址声明模块实例:
module.topic["abc"]
module.topic["bcd"]
因为主题名称是地址的一部分,Terraform 可以识别编辑现有主题对象(不更改其名称)和地图中的 adding/removing 主题之间的区别,将其转换为相应的计划模块内声明的资源实例。
如果重要的是您能够更改远程系统知道的主题名称而无需 Terraform 了解作为单独的删除和创建操作,您可以恢复name
作为该对象类型的属性,然后改为设置 topic = each.value.name
,然后地图键将 仅 用于在 Terraform 中进行跟踪,并且在远程系统中根本不可见.
我需要在 GCP 中构建大约 30 个发布子主题,为发布子主题创建每个模块是一个繁琐的过程,有没有更好的处理方法?
module "a" {
source = ""
project_id = var.project_id
topic = var.a["topic_name"]
topic_labels = var.a["topic_labels"]
pull_subscriptions = [
{
name = var.a["pull_subscription_name"]
ack_deadline_seconds = var.a["ack_deadline_seconds"]
max_delivery_attempts = var.a["max_delivery_attempts"]
maximum_backoff = var.maximum_backoff
minimum_backoff = var.minimum_backoff
expiration_policy = var.expiration_policy
enable_message_ordering = true
}
]
}
module "b" {
source = ""
project_id = var.project_id
topic = var.b["topic_name"]
topic_labels = var.b["topic_labels"]
pull_subscriptions = [
{
name = var.b["pull_subscription_name"]
ack_deadline_seconds = var.b["ack_deadline_seconds"]
max_delivery_attempts = var.b["max_delivery_attempts"]
maximum_backoff = var.maximum_backoff
minimum_backoff = var.minimum_backoff
expiration_policy = var.expiration_policy
enable_message_ordering = true
}
]
}
在 tfvars 中将值传递给上述模块,如下所示:
a = {
topic_name = "abc"
topic_labels = { env : "prod", purpose : "a" }
pull_subscription_name = "abc-sub"
ack_deadline_seconds = 600
max_delivery_attempts = 3
}
b = {
topic_name = "bcd"
topic_labels = { env : "prod", purpose : "b" }
pull_subscription_name = "bcd-sub"
ack_deadline_seconds = 600
max_delivery_attempts = 3
}
我们能否以某种方式组合 tfvars 中的变量并传入单个模块?
我还想知道维护上述 terraform 脚本以单独保存它们或利用一个模块创建 50 个主题的最佳实践?
谢谢!
您可以为模块使用 for_each
元参数:
https://www.terraform.io/docs/language/meta-arguments/for_each.html
您的变量可以是 for_each
可以通过的一组地图。
话虽这么说,这可能会变得过于复杂,IaC 的一个重要方面是保持简单和明确,因为它在某种程度上是自我记录(这不是省略记录您的工作的正当理由) .
对于两个单独的变量,您的选择有点受限,因为 Terraform 无法将这两个单独的变量视为以系统方式连接。 (每个变量,与 Terraform 中的其他对象一样,完全独立于解决依赖性的观点。)
但是,如果您可以将其重组为地图类型的单个变量,那么您可以使用 resource for_each
系统地为地图的每个元素声明一个实例:
variable "topics" {
type = map(object({
labels = map(string)
pull_subscription_name = string
ack_deadline_seconds = number
max_delivery_attempts = number
}))
}
module "topic" {
source = "..."
for_each = var.topics
project_id = var.project_id
topic = each.key
topic_labels = each.value.labels
pull_subscriptions = [
{
name = each.value.pull_scription_name
ack_deadline_seconds = each.value.ack_deadline_seconds
max_delivery_attempts = each.value.max_delivery_attempts
maximum_backoff = var.maximum_backoff
minimum_backoff = var.minimum_backoff
expiration_policy = var.expiration_policy
enable_message_ordering = true
}
]
}
对于此示例,我假设您的 topic_name
属性将是实例的合适的唯一键,因此我将其从声明的对象类型中删除,目的是将其放入映射键中。换句话说,此 topics
变量的值应如下所示:
topics = {
abc = {
labels = { env = "prod", purpose = "a" }
pull_subscription_name = "abc-sub"
ack_deadline_seconds = 600
max_delivery_attempts = 3
}
bcd = {
labels = { env = "prod", purpose = "b" }
pull_subscription_name = "bcd-sub"
ack_deadline_seconds = 600
max_delivery_attempts = 3
}
}
由此,Terraform 将了解您打算使用以下地址声明模块实例:
module.topic["abc"]
module.topic["bcd"]
因为主题名称是地址的一部分,Terraform 可以识别编辑现有主题对象(不更改其名称)和地图中的 adding/removing 主题之间的区别,将其转换为相应的计划模块内声明的资源实例。
如果重要的是您能够更改远程系统知道的主题名称而无需 Terraform 了解作为单独的删除和创建操作,您可以恢复name
作为该对象类型的属性,然后改为设置 topic = each.value.name
,然后地图键将 仅 用于在 Terraform 中进行跟踪,并且在远程系统中根本不可见.