Bird
Raised Fist0
Terraformcloud~5 mins

For_each for map-based instances in Terraform - Commands & Configuration

Choose your learning style10 modes available
Introduction
When you want to create multiple similar resources in Terraform, you can use for_each with a map to define each instance with a unique key and specific values. This helps manage resources efficiently without repeating code.
When you need to create multiple virtual machines with different names and settings in one configuration file.
When you want to manage several cloud storage buckets, each with unique properties, using a single resource block.
When you want to deploy multiple network interfaces with different IP addresses using one resource definition.
When you want to update or delete specific instances easily by referring to their keys in the map.
When you want to keep your Terraform code clean and avoid duplication by looping over a map of configurations.
Config File - main.tf
main.tf
variable "servers" {
  type = map(object({
    instance_type = string
    ami           = string
  }))
  default = {
    server1 = {
      instance_type = "t2.micro"
      ami           = "ami-0c55b159cbfafe1f0"
    }
    server2 = {
      instance_type = "t2.small"
      ami           = "ami-0c55b159cbfafe1f0"
    }
  }
}

resource "aws_instance" "example" {
  for_each = var.servers

  ami           = each.value.ami
  instance_type = each.value.instance_type
  tags = {
    Name = each.key
  }
}

This Terraform file defines a variable servers as a map where each key is a server name and the value is an object with instance details.

The aws_instance resource uses for_each to create one instance per map entry.

each.key is the server name, and each.value holds the instance properties like AMI and instance type.

Commands
This command initializes the Terraform working directory, downloads necessary provider plugins, and prepares the environment for deployment.
Terminal
terraform init
Expected OutputExpected
Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/aws... - Installing hashicorp/aws v4.0.0... - Installed hashicorp/aws v4.0.0 (signed by HashiCorp) Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure.
This command shows what Terraform will create or change based on the configuration, without making any actual changes yet.
Terminal
terraform plan
Expected OutputExpected
An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_instance.example["server1"] will be created + resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + tags = { + "Name" = "server1" } } # aws_instance.example["server2"] will be created + resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.small" + tags = { + "Name" = "server2" } } Plan: 2 to add, 0 to change, 0 to destroy.
This command applies the planned changes and creates the resources defined in the configuration automatically without asking for confirmation.
Terminal
terraform apply -auto-approve
Expected OutputExpected
aws_instance.example["server1"]: Creating... aws_instance.example["server2"]: Creating... aws_instance.example["server1"]: Creation complete after 10s [id=i-0abcd1234efgh5678] aws_instance.example["server2"]: Creation complete after 12s [id=i-0abcd1234efgh5679] Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
→
-auto-approve - Skips interactive approval before applying changes
This command lists all resources currently tracked in Terraform's state, showing the created instances with their keys.
Terminal
terraform state list
Expected OutputExpected
aws_instance.example["server1"] aws_instance.example["server2"]
Key Concept

If you remember nothing else from this pattern, remember: using for_each with a map lets you create multiple uniquely named resources from one block by looping over keys and values.

Common Mistakes
Using a list instead of a map with for_each when unique keys are needed
Lists use numeric indexes which can cause resource replacement if order changes, making management harder.
Use a map with meaningful keys to ensure stable resource identities and easier updates.
Trying to access each.key or each.value outside a for_each resource block
each.key and each.value only exist inside the resource using for_each, so referencing them elsewhere causes errors.
Use these expressions only inside the resource block that has for_each defined.
Summary
Define a map variable with keys as resource names and values as their properties.
Use for_each in the resource block to loop over the map and create one resource per key.
Run terraform init, plan, and apply to deploy all instances with unique names and settings.

Practice

(1/5)
1. What does for_each do when used with a map in Terraform?
easy
A. Creates resources only for the first key in the map
B. Deletes all resources in the map
C. Combines all map entries into a single resource
D. Creates one resource for each key-value pair in the map

Solution

  1. Step 1: Understand the role of for_each with maps

    for_each iterates over each key-value pair in a map to create multiple resources.
  2. Step 2: Recognize resource creation behavior

    Each key-value pair results in one resource instance, using each.key and each.value inside the resource block.
  3. Final Answer:

    Creates one resource for each key-value pair in the map -> Option D
  4. Quick Check:

    for_each with map = one resource per pair [OK]
Hint: Remember: for_each maps keys to separate resources [OK]
Common Mistakes:
  • Thinking for_each merges all map entries into one resource
  • Assuming for_each deletes resources
  • Believing for_each only uses the first map key
2. Which of the following is the correct syntax to use for_each with a map in a Terraform resource?
easy
A. resource "aws_instance" "example" { for_each = { key1 = "val1", key2 = "val2" } }
B. resource "aws_instance" "example" { for_each = ("key1", "key2") }
C. resource "aws_instance" "example" { for_each = "key1" }
D. resource "aws_instance" "example" { for_each = ["one", "two"] }

Solution

  1. Step 1: Identify valid for_each types

    for_each accepts a map or set of strings, but here we focus on map usage.
  2. Step 2: Check syntax correctness

    resource "aws_instance" "example" { for_each = { key1 = "val1", key2 = "val2" } } uses a map with key-value pairs correctly inside curly braces, which is valid Terraform syntax.
  3. Final Answer:

    resource "aws_instance" "example" { for_each = { key1 = "val1", key2 = "val2" } } -> Option A
  4. Quick Check:

    Map syntax with curly braces = correct for_each [OK]
Hint: Use curly braces for maps in for_each [OK]
Common Mistakes:
  • Using square brackets for maps instead of curly braces
  • Passing a single string instead of a map
  • Using parentheses which are invalid here
3. Given the Terraform snippet:
variable "servers" {
  default = {
    web = "10.0.0.1"
    db  = "10.0.0.2"
  }
}

resource "aws_instance" "example" {
  for_each = var.servers
  ami           = "ami-123456"
  instance_type = "t2.micro"
  tags = {
    Name = each.key
    IP   = each.value
  }
}

What will be the value of the tag Name for the instance with IP 10.0.0.2?
medium
A. web
B. 10.0.0.2
C. db
D. example

Solution

  1. Step 1: Map keys to IP addresses

    The map has keys 'web' and 'db' with values '10.0.0.1' and '10.0.0.2' respectively.
  2. Step 2: Match IP to key

    The IP '10.0.0.2' corresponds to the key 'db', so the tag Name will be 'db'.
  3. Final Answer:

    db -> Option C
  4. Quick Check:

    each.key for IP 10.0.0.2 = db [OK]
Hint: Match IP value to map key for Name tag [OK]
Common Mistakes:
  • Confusing key and value in the map
  • Using IP as the Name tag instead of the key
  • Assuming static tag values
4. What is wrong with this Terraform resource using for_each on a map?
resource "aws_instance" "example" {
  for_each = { "one" = "10.0.0.1", "two" = "10.0.0.2" }
  ami           = "ami-123456"
  instance_type = "t2.micro"
  tags = {
    Name = each.value
  }
  count = 2
}
medium
A. Using both for_each and count together causes an error
B. The map syntax is invalid
C. Missing each.key in tags
D. AMI ID is incorrect

Solution

  1. Step 1: Check resource meta-arguments

    Terraform does not allow using both for_each and count in the same resource block.
  2. Step 2: Identify the error cause

    The presence of count = 2 alongside for_each causes a configuration error.
  3. Final Answer:

    Using both for_each and count together causes an error -> Option A
  4. Quick Check:

    for_each and count cannot coexist [OK]
Hint: Never mix for_each and count in one resource [OK]
Common Mistakes:
  • Thinking map syntax is wrong
  • Believing missing each.key causes error
  • Assuming AMI ID is the problem
5. You have a map of server roles and IPs:
servers = {
  app1 = "10.0.1.1"
  app2 = ""
  app3 = "10.0.1.3"
  app4 = null
}

You want to create AWS instances only for servers with valid IPs using for_each. Which expression correctly filters the map to exclude empty or null IPs?
hard
A. for_each = var.servers
B. for_each = { for k, v in var.servers : k => v if v != "" && v != null }
C. for_each = { for k, v in var.servers : k => v if v == "" || v == null }
D. for_each = [ for v in var.servers : v if v != "" ]

Solution

  1. Step 1: Understand filtering with for expressions

    Use a for expression with an if condition to filter out empty strings and null values from the map.
  2. Step 2: Check each option

    for_each = { for k, v in var.servers : k => v if v != "" && v != null } correctly filters keys where value is neither empty string nor null, producing a valid filtered map for for_each.
  3. Final Answer:

    for_each = { for k, v in var.servers : k => v if v != "" && v != null } -> Option B
  4. Quick Check:

    Filter map with if condition to exclude empty/null [OK]
Hint: Filter map with for and if to exclude empty/null [OK]
Common Mistakes:
  • Not filtering out empty or null values
  • Using list comprehension instead of map
  • Filtering for empty/null instead of excluding them
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard