Terraform循环使用for_each



如果使用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 )

将实例放置在不同的子网中,但我认为countfor_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.indexelement元素一起使用依赖于每个项目都有自己的索引,但一组字符串的情况并非如此,因此在上面的文章中,我使用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
}

}

相关内容

  • 没有找到相关文章

最新更新