Learn how to efficiently provision and manage multiple cloud resources using Terraform's powerful for loop functionality.
Terraform's for_each
meta-argument provides a powerful way to create multiple resources with varying configurations without repetitive code. This approach leverages data structures like maps or lists to define the configuration for each resource instance.
To create multiple resources in Terraform using a loop, you can use the for_each
meta-argument.
First, define a data structure like a map or a list to hold the configuration for each resource:
variable "servers" {
default = {
"server1" = {
instance_type = "t2.micro"
ami = "ami-0c55b159bfd0c7bd0"
},
"server2" = {
instance_type = "t2.small"
ami = "ami-0c55b159bfd0c7bd0"
}
}
}
Then, in your resource block, use for_each
to iterate over the data structure:
resource "aws_instance" "app_server" {
for_each = var.servers
name = each.key
instance_type = each.value.instance_type
ami = each.value.ami
}
Within the resource block, you can access the current element's key and value using each.key
and each.value
, respectively.
This approach allows you to create multiple instances of a resource with different configurations based on the provided data structure.
This Terraform code defines infrastructure on AWS. It sets up two EC2 instances (virtual servers) with different types and a shared AMI. The code uses a variable to define server configurations, making it easy to manage multiple instances. Each instance is tagged for identification.
# Configure the AWS Provider
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
# Configure the AWS Region
provider "aws" {
region = "us-west-2" # Replace with your desired region
}
# Define a variable to hold server configurations
variable "servers" {
default = {
"server1" = {
instance_type = "t2.micro"
ami = "ami-0c55b159bfd0c7bd0" # Replace with your desired AMI ID
},
"server2" = {
instance_type = "t2.small"
ami = "ami-0c55b159bfd0c7bd0" # Replace with your desired AMI ID
}
}
}
# Create AWS instances using the for_each loop
resource "aws_instance" "app_server" {
for_each = var.servers
ami = each.value.ami
instance_type = each.value.instance_type
name = each.key
tags = {
Name = "App Server - ${each.key}"
}
}
Explanation:
servers
: This variable defines a map where each key represents a server name and the value is an object containing the instance type and AMI ID for that server.aws_instance
:
for_each = var.servers
: This line iterates over the servers
map.ami = each.value.ami
: Sets the AMI ID for each instance based on the ami
value in the servers
map.instance_type = each.value.instance_type
: Sets the instance type for each instance based on the instance_type
value in the servers
map.name = each.key
: Assigns a unique name to each instance using the key from the servers
map.tags
: Adds a tag "Name" to each instance for easy identification.How to run:
.tf
file (e.g., main.tf
).terraform init
to initialize the Terraform working directory.terraform apply
to create the resources.This code will create two EC2 instances on AWS, one named "server1" with type "t2.micro" and another named "server2" with type "t2.small", both using the specified AMI.
General:
for_each
is to avoid code repetition when creating multiple resources with similar configurations but varying parameters.for_each
, consider if count
would be a simpler solution. Use count
for creating multiple instances of a resource with identical configurations.for_each
with template interpolation to dynamically generate unique names for files, scripts, or other resources.for_each
loop, Terraform will halt the execution. Consider using the try()
function within the loop for more robust error handling.Data Structures:
for_each
with nested data structures to create complex resource relationships.for_each
with outputs from other resources or data sources for more dynamic configurations.Best Practices:
for_each
logic within a Terraform module for better organization and reusability.for_each
loop behaves as expected.Beyond the Basics:
for_each
with conditional expressions to create resources selectively based on specific criteria.for_each
with other Terraform features like flatten()
and nested loops. However, this can lead to complex code and should be used with caution.By understanding these nuances and best practices, you can leverage the full potential of for_each
to write efficient and maintainable Terraform code.
This article explains how to create multiple resources in Terraform using the for_each
meta-argument and a loop.
Key Points:
variable "servers"
) to store the configuration for each resource you want to create. Each element in the data structure represents a single resource.for_each
Meta-Argument: In your resource block (e.g., resource "aws_instance" "app_server"
), use for_each
and assign it to your data structure variable (e.g., for_each = var.servers
).each.key
to access the current element's key (e.g., "server1") and each.value
to access its corresponding value (e.g., {instance_type = "t2.micro", ami = "ami-0c55b159bfd0c7bd0"}
).Example:
The provided code snippet demonstrates creating two AWS instances ("server1" and "server2") with different instance types ("t2.micro" and "t2.small") using a map variable and the for_each
loop.
By combining the for_each
meta-argument with data structures, Terraform empowers you to manage infrastructure as code more efficiently. This approach reduces code duplication, enhances readability, and allows for flexible resource provisioning based on your specific needs. Understanding the nuances of for_each
, such as its use with different data structures and its interaction with other Terraform features, will significantly enhance your ability to write clean, maintainable, and powerful infrastructure code.