In the unique realm of Infrastructure as Code (IaC) using Terraform, understanding the concept of meta-arguments is critical. These meta-arguments, such as "count" and "for_each," play an important role in influencing how you define and maintain your infrastructure. In this blog, we will look at the fundamentals of meta-arguments, including their applications and practical use cases.
What are meta-arguments?
In Terraform, meta arguments refer to a set of special arguments that can be used to control the behavior of resources or modules. These arguments are not specific to a particular resource type and can be applied to any resource or module block in a Terraform configuration.
By default, when you define a resource block in Terraform, only one resource is produced. You can use count or for_each to manage many resources without having to create a separate block of code for each.
Here are some commonly used meta arguments in Terraform:
count
: This argument allows you to create multiple instances of a resource or module based on a given count. It takes an integer value and creates multiple instances by iterating over the block.depends_on
: This argument specifies explicit dependencies between resources or modules. It allows you to define the order in which resources are created or updated by specifying a dependency relationship.lifecycle
: This argument controls the lifecycle behavior of a resource. It includes sub-arguments such ascreate_before_destroy
andprevent_destroy
that allow you to control the creation and destruction of resources.count_index
: This argument is used in conjunction with thecount
argument and provides the index of the current resource or module instance. It allows you to access and reference individual instances within a resource or module block.for_each
: This argument allows you to create multiple instances of a resource or module based on a given map or set. It takes a map or set value and creates instances based on the keys or elements of the map or set.
Uses of meta-arguments in Terraform:
Meta arguments in Terraform provide several benefits that enhance the flexibility and control of resource and module management:
🔎Meta arguments such as count
and for_each
enable the dynamic creation of multiple instances of resources or modules based on specified conditions or input variables. This allows you to scale resources up or down based on demand or iterate over a set of values to create instances.
🔎The depends_on
meta argument allows you to define explicit dependencies between resources or modules. This ensures that Terraform creates or updates resources in the correct order, avoiding dependency issues and ensuring the desired state of your infrastructure.
🔎The provider
meta argument enables you to specify the provider configuration for a resource or module. This allows you to select a specific provider or configure provider-specific settings, providing flexibility in managing different provider versions, regions, or authentication mechanisms within your Terraform configuration.
🔎The lifecycle
meta argument provides control over the lifecycle behavior of a resource. You can use sub-arguments like create_before_destroy
and prevent_destroy
to define whether a resource should be destroyed before being created or to prevent accidental destruction of critical resources.
🔎 Meta arguments such as count_index
or for_each
index allow you to reference individual instances of resources or modules within a block. This enables you to perform operations or access attributes specific to each instance, providing granular control and flexibility in resource management.
What is count?
The count
meta argument in Terraform allows you to create multiple instances of a resource or module based on a given count. It takes an integer value and iterates over the block to create the specified number of instances.
Let's take an example to illustrate how the count
meta argument works:
resource "aws_instance" "example" {
count = 3
ami = "ami-12345678"
instance_type = "t2.micro"
tags = {
Name = "Instance ${count.index}"
}
}
In this example, we are using the aws_instance
resource from the AWS provider. The count
meta argument is set to 3, indicating that we want to create three instances of the aws_instance
.
Terraform will iterate over the block, creating three instances of the aws_instance
resource. Each instance will have the same AMI (ami-12345678
) and instance type (t2.micro
). However, we are using the count.index
reference to dynamically assign a unique name to each instance based on the iteration index
What is for_each?
In Terraform, the for_each
meta argument allows you to create multiple instances of a resource or module based on a given map or set. It iterates over the elements of the map or set and creates instances accordingly. Unlike the count
meta argument, which uses an integer value, for_each
uses a collection of unique keys.
Let's take an example to illustrate how the for_each
meta argument works:
variable "instances" {
type = set(string)
default = ["instance-1", "instance-2", "instance-3"]
}
resource "aws_instance" "example" {
for_each = var.instances
ami = "ami-12345678"
instance_type = "t2.micro"
tags = {
Name = "Instance ${each.value}"
}
}
In this example, we have a variable named instances
that is of type set(string)
.
The instances
variable is defined with a set of three strings representing instance names. The aws_instance
resource uses the for_each
meta argument, which references the var.instances
set.
The resulting instances will have the same AMI (ami-12345678
) and instance type (t2.micro
). However, we are using the each.value
reference to dynamically assign a unique name to each instance based on the key value from the set.
Task :
Create the IaC and demonstrate the use of Count and for_each
Create the IaC and demonstrate the use of Count
Step 1: Create a terraform.tf
file to declare AWS providers required for the system.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
required_version = ">= 1.2.0"
}
Step 2: Create a provider.tf
file to specify the AWS region required, for instance.
provider "aws" {
region = "us-east-2"
}
Step 3: Create a main.tf
and pass the details of the AWS instance. Using the count meta argument, you can name the instances as per the number of counts you have passed on.
resource "aws_instance" "server" {
count = 1
ami = "ami-0c7217cdde317cfec"
instance_type = "t2.micro"
tags = {
Name = "Server ${count.index}"
}
}
Step 4: Now the first step is to initialize the working directory with the necessary plugins and modules by executing terraform init
terraform init
Step 5:
terraform plan
Step 6:
terraform apply
Step7: Now, you can verify that new EC2 instances was successfully created and named as per the count argument
Step 8: Once you are done with the newly created instance, we can use terraform destroy
command that will delete the entire infrastructure.
Create infrastructure with for_each
meta-argument.
Step 1: We will use the same terraform.tf
and provider.tf
file.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-east-2"
}
Step 2: Edit main.tf
file and pass the details of AWS Instance. Using the for_each meta argument, you can name the instances as per the iteration of the locals ami ids.
locals {
ami_ids = toset([
"ami-0ddda618e961f2270",
])
}
resource "aws_instance" "server" {
for_each = local.ami_ids
ami = each.value
instance_type = "t2.micro"
tags = {
Name = "Server ${each.key}"
}
}
Step 3: Now the first step is to initialize the working directory with the necessary plugins and modules by executing terraform init
terraform init
Step 4:
terraform plan
Step 5:
terraform apply
Step6: You can see new instances was successfully created and named after ami id as we are using for_each
Step 7: Once you are done with the newly created instance, we can use terraform destroy
command that will delete the entire infrastructure.
Meta argument: multiple key-value iterations.
Step 1: We will use the same terraform.tf
and provider.tf
file.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-east-2"
}
Step 2: Create a main.tf
and pass the details of AWS providers and aws instance details. Using the for_each meta argument, you can name the instances as per the iteration of the local ami ids but here we are passing both key: value pairs.
# Multiple key value iteration
locals {
ami_ids = {
"amazonlinux" :"ami-022e1a32d3f742bd8",
"ubuntu": "ami-053b0d53c279acc90",
}
}
resource "aws_instance" "server" {
for_each = local.ami_ids
ami = each.value
instance_type = "t2.micro"
tags = {
Name = "Server ${each.key}"
}
}
Step 3: Now the first step is to initialize the working directory with the necessary plugins and modules by executing terraform init
terraform init
Step 4:
terraform plan
Step 5:
terraform apply
Step 6: You can see two new instances were successfully created by taking the name using key values of ami ids.
Step 7: Once you are done with the newly created instance, we can use terraform destroy
command that will delete the entire infrastructure.
Conclusion:
💡This blog explores the concept of meta-arguments in Terraform, focusing on count and for_each. It explains how these meta-arguments can be used to dynamically create multiple instances of resources or modules, manage dependencies, and control the lifecycle behavior of infrastructure. Step-by-step examples demonstrate the practical application of count and for_each meta-arguments in creating and managing AWS instances.
💡Finally, meta-arguments are a powerful feature of Terraform that can be used to control the behavior of resources in a flexible and granular way. Terraform users can create more robust and scalable infrastructure as code by effectively using meta-arguments.
Thank you for 📖reading my blog. 👍 Like it and share it 🔄 with your friends . Hope you find it helpful🤞
Happy learning😊😊