A Beginner's Guide to Terraform Loops: Deploying Multiple Resources and Using Conditional Logic
Introuduction
Terraform provides powerful constructs for automating and scaling your infrastructure. Among these, loops and conditionals help you avoid repetition by programmatically managing resources. In this guide, we'll dive into Terraform loops, covering the count
and for_each
parameters, conditional deployments, and advanced looping techniques.
Why Use Loops in Terraform?
Efficiency: Automate repetitive tasks by deploying multiple instances of a resource with just a few lines of code.
Flexibility: Dynamically deploy resources based on input variables or environment configurations.
Simplification: Reduce boilerplate code by looping over lists or maps and iterating over infrastructure resources.
Terraform Loops: count
vs. for_each
Terraform provides two main constructs for looping over resources: count
and for_each
. Let's explore both.
1. Loops with the count
Parameter
The count
parameter allows you to deploy multiple instances of the same resource. For example, you can create multiple EC2 instances with a single resource block by specifying how many instances should be deployed.
Example: Deploying Multiple EC2 Instances with count
resource "aws_instance" "web" {
count = 3
ami = "ami-12345678"
instance_type = "t2.micro"
tags = {
Name = "web-${count.index}"
}
}
In this example:
Terraform will deploy 3 EC2 instances.
The
count.index
is used to name each instance uniquely.
2. Loops with the for_each
Parameter
The for_each
parameter allows you to loop over a list or map, deploying a unique resource for each element in the collection. This is especially useful when you want to manage a variable number of resources based on dynamic input.
Example: Deploying S3 Buckets with for_each
resource "aws_s3_bucket" "buckets" {
for_each = {
dev = "dev-bucket"
prod = "prod-bucket"
test = "test-bucket"
}
bucket = each.value
tags = {
Name = each.value
Environment = each.key
}
}
In this example:
Terraform deploys three S3 buckets (for
dev
,prod
, andtest
).The bucket name and environment are dynamically set based on the map.
Advanced Looping in Terraform
Beyond count
and for_each
, Terraform offers additional looping constructs, such as for
expressions and the for
string directive.
1. Loops with for
Expressions
for
expressions are used to transform and filter lists and maps in Terraform. They allow you to iterate over a collection and produce a new collection based on the results.
Example: Filtering a List with a for
Expression
variable "instance_types" {
type = list(string)
default = ["t2.micro", "t2.small", "t2.medium", "t2.large"]
}
output "filtered_instance_types" {
value = [for instance in var.instance_types : instance if instance != "t2.large"]
}
In this example:
- Terraform filters out
t2.large
from the list of instance types and outputs the remaining types.
2. Loops with the for
String Directive
Terraform also supports looping over strings with the for
directive, which can be useful for constructing strings dynamically.
Example: Constructing a Comma-Separated String with for
variable "regions" {
type = list(string)
default = ["us-west-1", "us-east-1", "eu-west-1"]
}
output "regions_string" {
value = join(", ", [for region in var.regions : region])
}
In this example:
- Terraform joins the list of regions into a single comma-separated string.
Conditional Deployments in Terraform
In addition to loops, Terraform allows you to control the deployment of resources conditionally based on input variables or other criteria. Conditional logic helps you manage different environments or configurations dynamically.
1. Using Conditionals with count
You can use conditionals with the count
parameter to decide whether to deploy a resource.
Example: Conditional Resource Deployment with count
variable "create_bucket" {
type = bool
default = true
}
resource "aws_s3_bucket" "example" {
count = var.create_bucket ? 1 : 0
bucket = "conditional-bucket"
}
In this example:
- The S3 bucket will only be deployed if the
create_bucket
variable is set totrue
.
2. Using Conditionals with for_each
You can also apply conditionals with for_each
to control resource deployment based on dynamic criteria.
Example: Deploying Resources Based on Environment with for_each
variable "environments" {
type = list(string)
default = ["dev", "prod"]
}
resource "aws_instance" "web" {
for_each = { for env in var.environments : env => env if env != "dev" }
ami = "ami-12345678"
instance_type = "t2.micro"
tags = {
Name = "web-${each.key}"
}
}
In this example:
- Terraform deploys an EC2 instance for each environment, but skips the
dev
environment.
Putting It All Together
Here's a complete Terraform configuration that demonstrates various loops and conditionals in action.
provider "aws" {
region = "us-west-2"
}
variable "instance_types" {
type = list(string)
default = ["t2.micro", "t2.small", "t2.medium"]
}
variable "deploy_in_prod" {
type = bool
default = false
}
resource "aws_instance" "web" {
count = var.deploy_in_prod ? length(var.instance_types) : 0
instance_type = var.instance_types[count.index]
ami = "ami-12345678"
tags = {
Name = "web-instance-${count.index}"
}
}
resource "aws_s3_bucket" "buckets" {
for_each = { for type in var.instance_types : type => type if type != "t2.medium" }
bucket = "${each.value}-bucket"
tags = {
Name = "${each.value}-bucket"
}
}
output "instance_tags" {
value = [for instance in aws_instance.web : instance.tags["Name"]]
}
In this configuration:
EC2 instances are only deployed if
deploy_in_prod
is set totrue
.The S3 bucket is deployed for all instance types except
t2.medium
.The
output
block returns the names of the deployed EC2 instances.
Conclusion
Terraform's looping constructs—count
, for_each
, for
expressions, and string directives—enable you to write cleaner, more scalable infrastructure code. Combined with conditionals, they allow you to manage dynamic infrastructure configurations based on your specific needs.
By understanding how to effectively use loops and conditionals, you can simplify your Terraform configurations, making them more maintainable and adaptable to different environments. With this knowledge, you're now ready to start automating repetitive tasks and deploying scalable infrastructure with Terraform.