snippetterraformMinor
How to specify specific subnet in Terraform when using for each
Viewed 0 times
howeachusingforspecificsubnetspecifywhenterraform
Problem
I am trying to create an ec2 instance that will hold my Jenkins server. I want this to be in a private subnet which I created using a for each loop. Below is my subnet for each loop and my ec2 instance resource. I have also included the error message. Idea is I want it in the first private subnet.
ec2 instance
subnet resource
variable used by the subnet loop
error message seen when doing a
ec2 instance
resource "aws_instance" "jenkins" {
ami = "${var.ubuntuAMI}"
instance_type = "t3.micro"
availability_zone = "us-east-1a"
key_name = "me"
monitoring = true
vpc_security_group_ids = [aws_security_group.ssh_access.id]
disable_api_termination = true
subnet_id = "${aws_subnet.private[each.key]}"
tags = {
Name = "Jenkins"
}
}subnet resource
resource "aws_subnet" "private" {
for_each = var.subnet_numbers_private
vpc_id = aws_vpc.Main_VPC.id
availability_zone = each.key
cidr_block = cidrsubnet(aws_vpc.Main_VPC.cidr_block, 8, each.value)
tags = {
Name = "Private-${each.key}"
}
}variable used by the subnet loop
variable "subnet_numbers_private" {
description = "Map for private subnets"
default = {
"us-east-1a" = 1
"us-east-1b" = 2
"us-east-1c" = 3
}
}error message seen when doing a
terraform planThe "each" object can be used only in "resource" blocks, and only when the
"for_each" argument is set.Solution
When you want to refer to a specific instance of a resource that has multiple instances due to using
If you just want to select any one subnet from the list, without needing to specify its name directly, you can use an expression like the following to select a single key by sorting the keys lexically and taking the first one:
However, beware that if you do the above then any later changes to
From the way you wrote the question it sounds like you want just one instance in a single subnet rather than one instance per subnet, but if you did want an instance per subnet then you can achieve that by putting
In this latter case, the
for_each, you need to include the specific key of the instance you want in your references:subnet_id = aws_subnet.private["us-east-1a"].idIf you just want to select any one subnet from the list, without needing to specify its name directly, you can use an expression like the following to select a single key by sorting the keys lexically and taking the first one:
subnet_id = aws_subnet.private[keys(aws_subnet.private)[0]].idHowever, beware that if you do the above then any later changes to
var.subnet_numbers_private that affect which subnet sorts first will cause a different subnet id to be selected, which will then in turn cause Terraform to plan to replace your instance to move it into a new subnet.From the way you wrote the question it sounds like you want just one instance in a single subnet rather than one instance per subnet, but if you did want an instance per subnet then you can achieve that by putting
for_each in the aws_instance resource too, using the subnet resource itself (represented in expressions as a map) as the repetition expression:resource "aws_instance" "jenkins" {
for_each = aws_subnet.private
# ...
subnet_id = each.value.id
# ...
}In this latter case, the
aws_instance.jenkins instances will also be identified by the keys you selected for the subnets, so you'd have instances with addresses like aws_instance.jenkins["us-east-1a"] and aws_instance.jenkins["us-east-1b"] so both you and Terraform can see which instance belongs to which subnet.Code Snippets
subnet_id = aws_subnet.private["us-east-1a"].idsubnet_id = aws_subnet.private[keys(aws_subnet.private)[0]].idresource "aws_instance" "jenkins" {
for_each = aws_subnet.private
# ...
subnet_id = each.value.id
# ...
}Context
StackExchange DevOps Q#9665, answer score: 1
Revisions (0)
No revisions yet.