Terraform:如何按照对象内的定义循环 aws_instance N 次
Terraform : How to loop over aws_instance N times as defined within object
我有以下变量
variable "instance_types" {
default = {
instances : [
{
count = 1
name = "control-plane"
ami = "ami-xxxxx"
instance_type = "t2.large"
iam_instance_profile = "xxx-user"
subnet_id = "subnet-xxxxx"
},
{
count = 3
name = "worker"
ami = "ami-xxxxx"
instance_type = "t2.large"
iam_instance_profile = "xxx-user"
subnet_id = "subnet-xxxxx"
}
]
}
}
使用以下实例声明(我正在尝试迭代)
resource "aws_instance" "k8s-node" {
# Problem here : How to turn an array of 2 objects into 4 (1 control_plane, 3 workers)
for_each = {for x in var.instance_types.instances: x.count => x}
ami = lookup(each.value, "ami")
instance_type = lookup(each.value, "instance_type")
iam_instance_profile = lookup(each.value, "iam_instance_profile")
subnet_id = lookup(each.value, "subnet_id")
tags = {
Name = lookup(each.value, "name")
Type = each.key
}
}
目标: 获取 aws_instance
迭代 4 次(1 control_plane + 3 个工人)并填充 [=14= 的索引值].
问题: 无法使用所需结果正确迭代对象数组。在典型的编程语言中,这将在双 for 循环中实现。
输入变量的数据类型 map(object))
可以更容易地解决这个问题。转换后的数据结构如下所示:
variable "instance_types" {
...
default = {
"control-plane" = {
count = 1
ami = "ami-xxxxx"
instance_type = "t2.large"
iam_instance_profile = "xxx-user"
subnet_id = "subnet-xxxxx"
},
"worker" = {
count = 3
ami = "ami-xxxxx"
instance_type = "t2.large"
iam_instance_profile = "xxx-user"
subnet_id = "subnet-xxxxx"
}
}
}
请注意 object
中的 name
键包含在 map
键中以提高效率和清洁度。
如果资源在控制平面和工作节点之间分配,那么我们就完成了,可以立即在 for_each
元参数中利用此变量的值。但是,合并资源现在需要进行数据转换:
locals {
instance_types = flatten([ # need this for final structure type
for instance_key, instance in var.instance_types : [ # iterate over variable input objects
for type_count in range(1, instance.count + 1) : { # sub-iterate over objects by "count" value specified; use range function and begin at 1 for human readability
new_key = "${instance_key} ${type_count}" # for resource uniqueness
type = instance_key # for easier tag value later
ami = instance.ami # this and below retained from variable inputs
instance_type = instance.instance_type
iam_instance_profile = instance.iam_instance_profile
subnet_id = instance.subnet_id
}
]
])
}
现在我们可以使用 for_each
元参数在资源内进行迭代,并利用 for
表达式重建输入以在资源内适当使用。
resource "aws_instance" "k8s-node" {
# local.instance_types is a list of objects, and we need a map of objects with unique resource keys
for_each = { for instance_type in local.instance_types : instance_type.new_key => instance_type }
ami = each.value.ami
instance_type = each.value.instance_type
iam_instance_profile = each.value.iam_instance_profile
subnet_id = each.value.subnet_id
tags = {
Name = each.key
Type = each.value.type
}
}
这将为您提供所需的行为,您可以根据需要修改它以适应样式偏好或不同用途。
请注意,lookup
函数已被删除,因为它们仅在将默认值指定为第三个参数时才有用,这在变量声明中的对象类型中是不可能的,除非作为 0.14 中的实验性功能。
这些资源的导出资源属性的绝对命名空间为:
(module?.<declared_module_name>?.)<resource_type>.<resource_name>[<resource_key>].<attribute>
例如,给定模块内资源、第一个工作节点和私有 ip 地址导出属性:
aws_instance.k8s-node["worker 1"].private_ip
请注意,您还可以通过在 <resource_name>
处终止命名空间来访问所有资源的导出属性(保留所有资源的映射而不是访问单个资源值)。然后,您还可以在 output
声明中使用 for
表达式,为所有类似资源及其相同的导出属性创建自定义聚合输出。
{ for node_key, node in aws_instance.k8s-node : node_key => node.private_ip }
我有以下变量
variable "instance_types" {
default = {
instances : [
{
count = 1
name = "control-plane"
ami = "ami-xxxxx"
instance_type = "t2.large"
iam_instance_profile = "xxx-user"
subnet_id = "subnet-xxxxx"
},
{
count = 3
name = "worker"
ami = "ami-xxxxx"
instance_type = "t2.large"
iam_instance_profile = "xxx-user"
subnet_id = "subnet-xxxxx"
}
]
}
}
使用以下实例声明(我正在尝试迭代)
resource "aws_instance" "k8s-node" {
# Problem here : How to turn an array of 2 objects into 4 (1 control_plane, 3 workers)
for_each = {for x in var.instance_types.instances: x.count => x}
ami = lookup(each.value, "ami")
instance_type = lookup(each.value, "instance_type")
iam_instance_profile = lookup(each.value, "iam_instance_profile")
subnet_id = lookup(each.value, "subnet_id")
tags = {
Name = lookup(each.value, "name")
Type = each.key
}
}
目标: 获取 aws_instance
迭代 4 次(1 control_plane + 3 个工人)并填充 [=14= 的索引值].
问题: 无法使用所需结果正确迭代对象数组。在典型的编程语言中,这将在双 for 循环中实现。
输入变量的数据类型 map(object))
可以更容易地解决这个问题。转换后的数据结构如下所示:
variable "instance_types" {
...
default = {
"control-plane" = {
count = 1
ami = "ami-xxxxx"
instance_type = "t2.large"
iam_instance_profile = "xxx-user"
subnet_id = "subnet-xxxxx"
},
"worker" = {
count = 3
ami = "ami-xxxxx"
instance_type = "t2.large"
iam_instance_profile = "xxx-user"
subnet_id = "subnet-xxxxx"
}
}
}
请注意 object
中的 name
键包含在 map
键中以提高效率和清洁度。
如果资源在控制平面和工作节点之间分配,那么我们就完成了,可以立即在 for_each
元参数中利用此变量的值。但是,合并资源现在需要进行数据转换:
locals {
instance_types = flatten([ # need this for final structure type
for instance_key, instance in var.instance_types : [ # iterate over variable input objects
for type_count in range(1, instance.count + 1) : { # sub-iterate over objects by "count" value specified; use range function and begin at 1 for human readability
new_key = "${instance_key} ${type_count}" # for resource uniqueness
type = instance_key # for easier tag value later
ami = instance.ami # this and below retained from variable inputs
instance_type = instance.instance_type
iam_instance_profile = instance.iam_instance_profile
subnet_id = instance.subnet_id
}
]
])
}
现在我们可以使用 for_each
元参数在资源内进行迭代,并利用 for
表达式重建输入以在资源内适当使用。
resource "aws_instance" "k8s-node" {
# local.instance_types is a list of objects, and we need a map of objects with unique resource keys
for_each = { for instance_type in local.instance_types : instance_type.new_key => instance_type }
ami = each.value.ami
instance_type = each.value.instance_type
iam_instance_profile = each.value.iam_instance_profile
subnet_id = each.value.subnet_id
tags = {
Name = each.key
Type = each.value.type
}
}
这将为您提供所需的行为,您可以根据需要修改它以适应样式偏好或不同用途。
请注意,lookup
函数已被删除,因为它们仅在将默认值指定为第三个参数时才有用,这在变量声明中的对象类型中是不可能的,除非作为 0.14 中的实验性功能。
这些资源的导出资源属性的绝对命名空间为:
(module?.<declared_module_name>?.)<resource_type>.<resource_name>[<resource_key>].<attribute>
例如,给定模块内资源、第一个工作节点和私有 ip 地址导出属性:
aws_instance.k8s-node["worker 1"].private_ip
请注意,您还可以通过在 <resource_name>
处终止命名空间来访问所有资源的导出属性(保留所有资源的映射而不是访问单个资源值)。然后,您还可以在 output
声明中使用 for
表达式,为所有类似资源及其相同的导出属性创建自定义聚合输出。
{ for node_key, node in aws_instance.k8s-node : node_key => node.private_ip }