<p>When you want to refer to a specific instance of a resource that has multiple instances due to using <code>for_each</code>, you need to include the specific key of the instance you want in your references:</p>

<pre><code>  subnet_id = aws_subnet.private["us-east-1a"].id
</code></pre>

<p>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:</p>

<pre><code>  subnet_id = aws_subnet.private[keys(aws_subnet.private)[0]].id
</code></pre>

<p>However, beware that if you do the above then any later changes to <code>var.subnet_numbers_private</code> 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.</p>

<hr>

<p>From the way you wrote the question it sounds like you want just one instance in a single subnet rather than one instance <em>per</em> subnet, but if you did want an instance per subnet then you can achieve that by putting <code>for_each</code> in the <code>aws_instance</code> resource too, using the subnet resource itself (represented in expressions as a map) as the repetition expression:</p>

<pre><code>resource "aws_instance" "jenkins" {
  for_each = aws_subnet.private

  # ...
  subnet_id = each.value.id
  # ...
}
</code></pre>

<p>In this latter case, the <code>aws_instance.jenkins</code> instances will also be identified by the keys you selected for the subnets, so you'd have instances with addresses like <code>aws_instance.jenkins["us-east-1a"]</code> and <code>aws_instance.jenkins["us-east-1b"]</code> so both you and Terraform can see which instance belongs to which subnet.</p>

CC BY-SA 4.0
2019-11-04T17:05:38.333Z
2019-11-04T17:05:38.333Z
Martin Atkins
<p>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.</p>

<p>ec2 instance</p>

<pre><code>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"
  }
}
</code></pre>

<p>subnet resource</p>

<pre><code>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}"
  }
}
</code></pre>

<p>variable used by the subnet loop</p>

<pre><code>variable "subnet_numbers_private" {
  description = "Map for private subnets"
  default     = {
    "us-east-1a" = 1
    "us-east-1b" = 2
    "us-east-1c" = 3
  }
}
</code></pre>

<p>error message seen when doing a <code>terraform plan</code></p>

<pre><code>The "each" object can be used only in "resource" blocks, and only when the
"for_each" argument is set.
</code></pre>

<terraform>
How to specify specific subnet in Terraform when using for each
joshk132
# How to specify specific subnet in Terraform when using for each

(Asked by: username_0 on 2019-11-03)

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
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 plan
The "each" object can be used only in "resource" blocks, and only when the
"for_each" argument is set.

**Tags:** terraform


---

## 1 answers

### Answer by username_1 on 2019-11-04. Score: 1 | Accepted answer

When you want to refer to a specific instance of a resource that has multiple instances due to using 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"].id

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:
  subnet_id = aws_subnet.private[keys(aws_subnet.private)[0]].id

However, 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.


---

