122
Jan. 25, 2024, 11:16 a.m.
Почему for_each, а не count при создании ресурсов terraform
Задача: переписать код с ипользованием count на for_each
Исходно имеем такой код модуля, который создает ssh-key и ec2.
resource "aws_instance" "module" {
count = length(var.names)
ami = var.ami
instance_type = var.instance_type
subnet_id = var.subnet_id
vpc_security_group_ids = var.vpc_security_group_ids
user_data = file(var.user_data)
key_name = aws_key_pair.module[count.index].id
root_block_device {
volume_size = var.volume_size
volume_type = var.volume_type
}
# cpu_options {
# core_count = var.core_count
# threads_per_core = var.threads_per_core
# }
tags = {
Name = var.names[count.index]
}
}
resource "aws_key_pair" "module" {
count = length(var.names)
key_name = "key-for-${var.names[count.index]}-ec2"
public_key = var.public_key
}
Файл переменных
variable "latest_image" {
type = string
default = "debian-12-amd64-*"
}
variable "ami" {
type = string
default = ""
}
variable "instance_type" {
type = string
default = "t3a.nano"
}
variable "subnet_id" {
type = string
default = ""
}
variable "vpc_security_group_ids" {
type = list(any)
default = []
}
variable "user_data" {
type = string
default = "user_data.sh"
}
variable "volume_size" {
type = number
default = 16
}
variable "volume_type" {
type = string
default = "gp2"
}
# variable "core_count" {
# type = number
# default = 1
# }
# variable "threads_per_core" {
# type = number
# default = 1
# }
variable "names" {
type = list(string)
default = []
}
variable "public_key" {
type = string
default = ""
}
Файл вывода
output "ec2_id" {
value = aws_instance.module[*].id
}
output "ec2_public_ip" {
value = aws_instance.module[*].public_ip
}
output "ec2_private_ip" {
value = aws_instance.module[*].private_ip
}
С одной стороны кажется что всё хорошо, если создадим массив ["one", "two", "three"]
. Если мы захотим пересоздать или поменять название у two
тогда все последующие ресурсы после него будут пересозданы, что приведёт к неудобным последсвиям. Поэтому предлагаю такой код, он выполняет всё тоже самое но при изменении одного элемента массива не приведёт к тому что будут задеты другие.
resource "aws_instance" "module" {
for_each = toset(var.names)
ami = var.ami
instance_type = var.instance_type
subnet_id = var.subnet_id
vpc_security_group_ids = var.vpc_security_group_ids
user_data = file(var.user_data)
key_name = aws_key_pair.module[each.key].id
root_block_device {
volume_size = var.volume_size
volume_type = var.volume_type
}
tags = {
Name = each.key
}
}
resource "aws_key_pair" "module" {
for_each = toset(var.names)
key_name = "key-for-${each.key}-ec2"
public_key = var.public_key
}
variable "latest_image" {
type = string
default = "debian-12-amd64-*"
}
variable "ami" {
type = string
default = ""
}
variable "instance_type" {
type = string
default = "t3a.nano"
}
variable "subnet_id" {
type = string
default = ""
}
variable "vpc_security_group_ids" {
type = list(any)
default = []
}
variable "user_data" {
type = string
default = "user_data.sh"
}
variable "volume_size" {
type = number
default = 16
}
variable "volume_type" {
type = string
default = "gp2"
}
# variable "core_count" {
# type = number
# default = 1
# }
# variable "threads_per_core" {
# type = number
# default = 1
# }
variable "names" {
type = list(string)
default = []
}
variable "public_key" {
type = string
default = ""
}
output "ec2_id" {
value = { for name, instance in aws_instance.module : name => instance.id }
}
output "ec2_public_ip" {
value = { for name, instance in aws_instance.module : name => instance.public_ip }
}
output "ec2_private_ip" {
value = { for name, instance in aws_instance.module : name => instance.private_ip }
}