Хорошая общая стратегия с ресурсом for_each
состоит в том, чтобы разработать структуру данных, которую вы ему передаете, так, чтобы each.value
содержал все данные для каждого экземпляра, которые вам нужны внутри блока ресурсов.
В этом случае , это означает, что выражение for_each
для вашего ресурса aws_instance
будет картой объектов, где каждый объект имеет как профиль экземпляра, так и su bnet 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
для преобразования в список при условии, что в этой ситуации на самом деле не имеет значения , который su bnet назначен каждому экземпляру, пока экземпляры в конечном итоге примерно равномерно распределены между подсетями.
Однако следует помнить о важных последствиях: если вы добавите новый элемент в var.profiles
позже, это может привести к переназначению subnet_id
для существующих экземпляров и, следовательно, потребует те экземпляры, которые необходимо воссоздать. Если вы не хотите, чтобы это было правдой, вам нужно как-то сделать более явным выбор su bnet для каждого профиля, что можно сделать, сделав var.profiles
list(string)
вместо set(string)
а затем документирование того, что новые профили должны быть добавлены только в конец этого списка, или, в качестве альтернативы, вы можете переместить решение в вызывающую сторону вашего модуля, сделав саму var.profiles
карту объектов, где вызывающий затем укажет один su bnet на профиль:
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
}