- OpenTofu 语言
- 元参数
- count 元参数
count
元参数
给定的资源或模块块不能同时使用 count
和 for_each
。
默认情况下,一个 资源块 配置一个真实的基础设施对象。(类似地,一个 模块块 将子模块的内容包含到配置中一次。)但是,有时您希望管理几个类似的对象(例如计算实例的固定池),而无需为每个对象编写一个单独的块。OpenTofu 有两种方法可以做到这一点:count
和 for_each
。
如果资源或模块块包含一个值为整数的 count
参数,OpenTofu 将创建多个实例。
基本语法
count
是由 OpenTofu 语言定义的元参数。它可以与模块和每种资源类型一起使用。
count
元参数接受一个整数,并创建该数量的资源或模块实例。每个实例都有一个与之关联的不同基础设施对象,并且在应用配置时,每个实例都会被分别创建、更新或销毁。
resource "aws_instance" "server" {
count = 4 # create four similar EC2 instances
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
tags = {
Name = "Server ${count.index}"
}
}
count
对象
在设置了 count
的块中,可以在表达式中使用额外的 count
对象,以便您可以修改每个实例的配置。此对象具有一个属性
count.index
- 与此实例对应的不同的索引号(从0
开始)。
在 count
中使用表达式
count
元参数接受数字 表达式。但是,与大多数参数不同,count
值必须在 OpenTofu 执行任何远程资源操作之前就知道。这意味着 count
不能引用在应用配置后才知道的任何资源属性(例如,在创建对象时由远程 API 生成的唯一 ID)。
引用实例
当设置 count
时,OpenTofu 区分块本身及其关联的多个资源或模块实例。实例由一个索引号标识,从 0
开始。
<TYPE>.<NAME>
或module.<NAME>
(例如,aws_instance.server
)引用资源块。<TYPE>.<NAME>[<INDEX>]
或module.<NAME>[<INDEX>]
(例如,aws_instance.server[0]
、aws_instance.server[1]
等)引用单个实例。
这与没有 count
或 for_each
的资源和模块不同,后者无需索引或键即可引用。
类似地,来自具有多个实例的子模块的资源在计划输出和其他 UI 中显示时,前面会加上 module.<NAME>[<KEY>]
。对于没有 count
或 for_each
的模块,地址将不包含模块索引,因为模块的名称足以引用该模块。
在嵌套的 provisioner
或 connection
块中,特殊的 self
对象引用当前的资源实例,而不是整个资源块。
何时使用 for_each
而不是 count
如果您的实例几乎完全相同,则 count
是合适的。如果其中一些参数需要不同的值,而这些值不能直接从整数派生,则使用 for_each
更安全。
在 for_each
可用之前,通常从列表的长度派生 count
并使用 count.index
来查找原始列表值
variable "subnet_ids" {
type = list(string)
}
resource "aws_instance" "server" {
# Create one instance for each subnet
count = length(var.subnet_ids)
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
subnet_id = var.subnet_ids[count.index]
tags = {
Name = "Server ${count.index}"
}
}
这很脆弱,因为资源实例仍然由其索引而不是列表中的字符串值标识。如果从列表中间删除了一个元素,则该元素之后的每个实例都将看到其 subnet_id
值发生变化,从而导致比预期更多的远程对象更改。使用 for_each
可以提供相同的功能,而无需额外的更改。