如果您使用 for_each 而不是 count,如何获取子网 id? 就我而言,我正在做这样的事情
resource "aws_instance" "k8s" {
for_each = var.profiles
ami = data.aws_ami.latest-ubuntu.id
instance_type = "t2.medium"
iam_instance_profile = "${each.value}"
subnet_id = ??????????????
vpc_security_group_ids = [var.security_group]
key_name = var.keyname
connection {
type = "ssh"
host = self.public_ip
user = "ubuntu"
private_key = file(var.private_key_path)
}
tags = {
Name = "${each.key}"
}
}
这是因为我正在创建类似的实例,但需要为它们分配不同的实例配置文件。
理想情况下,我会做类似的事情
subnet_id = element(var.subnets, count.index )
将实例放置在不同的子网中,但我不认为 count 和 for_each 可以在同一个块定义中使用。
我必须划分子网和 4 个实例,并且希望循环遍历子网,将每个实例放在一个子网中。
有什么想法吗?
如果
var.profiles
是一个列表,你可以使用each.key
来获取每个元素的索引。
资源
for_each
的一个良好通用策略是设计您传递给它的数据结构,以便 each.value
包含资源块内所需的所有每个实例数据。
在这种情况下,这意味着您的
for_each
资源的 aws_instance
表达式将是一个对象映射,其中每个对象都具有实例配置文件和子网 ID。
for
表达式,将 var.profiles
(大概是 set(string)
值)转换为对象映射,从而获得您想要的结果。例如:
resource "aws_instance" "k8s" {
for_each = {
# This assigns a subnet to each of the profiles
# by first sorting them by name to produce a list
# and then selecting subnets based on the order
# of the sort result.
for i, profile_name in sort(var.profiles) : profile_name => {
iam_instance_profile = profile_name
subnet_id = element(var.subnets, i)
}
}
ami = data.aws_ami.latest-ubuntu.id
instance_type = "t2.medium"
iam_instance_profile = each.value.iam_instance_profile
subnet_id = each.value.subnet_id
vpc_security_group_ids = [var.security_group]
key_name = var.keyname
}
将
count.index
与 element
元素一起使用依赖于每个项目都有自己的索引,但一组字符串的情况并非如此,因此在上面我使用 sort
转换为列表,假设对于这种情况,将哪个子网分配给每个实例并不重要,只要实例最终大致均匀地分布在子网。
但是,需要记住这一点的一个重要含义:如果稍后向
var.profiles
添加新项目,则可能会导致现有实例的 subnet_id
被重新分配,因此需要重新创建这些实例。如果您不希望这是真的,那么您需要以某种方式更明确地选择每个配置文件的子网,这可以通过使 var.profiles
成为 list(string)
而不是 set(string)
然后记录来完成新的配置文件只能添加到该列表的末尾,或者您可以通过将 var.profiles
本身设置为地图,将决策移至模块的调用者中然后调用者将为每个配置文件指定一个子网的对象:
variable "profiles" {
type = map(object({
subnet_id = string
}))
}
在这种情况下,您的资源块将变得更简单,因为变量值已经具有合适的形状:
resource "aws_instance" "k8s" {
for_each = var.profiles
ami = data.aws_ami.latest-ubuntu.id
instance_type = "t2.medium"
iam_instance_profile = each.key
subnet_id = each.value.subnet_id
vpc_security_group_ids = [var.security_group]
key_name = var.keyname
}
您可以将个人资料作为对象列表提供:
例如:
variable "profiles" {
type = list(object({
name = string
key = string
}))
default =
[
{name = "exemple" , key = "exemplekey" },
{name = "exemple2" , key = "exemplekey2" }
]
}
像这样,
each.key
将包含列表中元素的索引,each.value
将包含对象{name,key}
所以你的代码会是这样的
resource "aws_instance" "k8s" {
for_each = var.profiles
ami = data.aws_ami.latest-ubuntu.id
instance_type = "t2.medium"
iam_instance_profile = each.value
subnet_id = element(var.subnets , each.key)
vpc_security_group_ids = [var.security_group]
key_name = var.keyname
connection {
type = "ssh"
host = self.public_ip
user = "ubuntu"
private_key = file(var.private_key_path)
}
tags = {
Name = each.value.key
}
}