如果使用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
包含资源块中所需的所有每个实例的数据。
在这种情况下,这意味着aws_instance
资源的for_each
表达式将是对象的映射,其中每个对象都有一个实例配置文件和一个子网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
}
}