When you define a resource block in Terraform, by default, this specifies one resource that will be created. To manage several of the same resources, you can use either count or for_each, which removes the need to write a separate block of code for each one. Using these options reduces overhead and makes your code neater.
Count
The count meta-argument accepts a whole number and creates the number of instances of the resource specified.
When each instance is created, it has its own distinct infrastructure object associated with it, so each can be managed separately. When the configuration is applied, each object can be created, destroyed, or updated as appropriate.
eg.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "server" {
count = 4
ami = "ami-08c40ec9ead489470"
instance_type = "t2.micro"
tags = {
Name = "Server ${count.index}"
}
}
for_each
Like the count argument, the for_each meta-argument creates multiple instances of a module or resource block. However, instead of specifying the number of resources, the for_each meta-argument accepts a map or a set of strings. This is useful when multiple resources are required that have different values. Consider our Active directory groups example, with each group requiring a different owner.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-east-1"
}
locals {
ami_ids = toset([
"ami-0b0dcb5067f052a63",
"ami-08c40ec9ead489470",
])
}
resource "aws_instance" "server" {
for_each = local.ami_ids
ami = each.key
instance_type = "t2.micro"
tags = {
Name = "Server ${each.key}"
}
}
Multiple key value iteration
locals {
ami_ids = {
"linux" :"ami-0b0dcb5067f052a63",
"ubuntu": "ami-08c40ec9ead489470",
}
}
resource "aws_instance" "server" {
for_each = local.ami_ids
ami = each.value
instance_type = "t2.micro"
tags = {
Name = "Server ${each.key}"
}
}
Task-01
Create the above Infrastructure as code and demonstrate the use of Count and for_each.
Meta argument- count
terraform configuration that creates four AWS EC2 instances with the same configuration but with different tags indicating their names. This is a valid configuration that will create four EC2 instances in the "us-east-1" region with the specified AMI and instance type.
It defines the AWS provider with the region set to "us-east-1."
It creates an AWS EC2 instance resource named "server" with a
count
of 4, which means it will create four instances with the same configuration.Each instance uses the specified AMI ("ami-08c40ec9ead489470") and instance type ("t2.micro").
It assigns tags to each instance with a name that includes an index (0 to 3) to make each instance's name unique.
After you apply this Terraform configuration with terraform apply
, it will create the four EC2 instances in the "us-east-1" region,
Four new EC2 instances were successfully created.
Meta argument - for_each
We define a "locals" block to create a set of AMI IDs for our instances. We use the "toset" function to convert an array of strings into a set of strings.
In the "resource" block, we define the "aws_instance" resource and use the "for_each" meta-argument to create an instance for each AMI ID in our "ami_ids" map. The "ami" attribute is set to the current key in the map (i.e., the AMI ID), and the "instance_type" attribute is set to "t2.micro". We also use the "tags" attribute to set a unique name for each instance using the current key in the map.
Two new instances were successfully created.
With multiple key-value iterations.
"for_each" meta-argument with a map that has multiple key-value pairs to create instances with different AMIs. In this case, we use a map with two key-value pairs, where each key is a string that represents the name of the AMI, and each value is the actual AMI ID.
Inside the "resource" block, we use the "each.value" variable to access the current value in the map (i.e., the AMI ID), and set the "ami" attribute to it. We also use the "each.key" variable to access the current key in the map (i.e., the AMI name), and use it to set a unique name for each instance using the "tags" attribute.
Using the "for_each" meta-argument with maps can be very useful for creating multiple instances with different configurations in a single block of code.
Run terraform apply
Write about meta-arguments and their use in Terraform.
In Terraform, "meta-arguments" (also known as "meta-arguments" or "lifecycle meta-arguments") are special configuration settings that can be applied to resources and modules to control various aspects of resource behaviour and lifecycle. These meta-arguments do not directly affect the resource's attributes or configuration but influence how Terraform manages and interacts with those resources. Meta-arguments allow you to customize resource behaviour, dependencies, and actions in your Terraform configurations.
Here are some common meta-arguments and their use in Terraform:
count: The
count
meta-argument allows you to create multiple instances of a resource with the same configuration. You can use it to create multiple instances with a similar setup, each with a unique name or other attributes.resource "aws_instance" "example" { count = 3 ami = "ami-12345678" instance_type = "t2.micro" }
depends_on: The
depends_on
meta-argument explicitly defines the dependencies between resources. It ensures that one resource is created or updated only after another resource is in a certain state.resource "aws_instance" "web_server" { ami = "ami-12345678" instance_type = "t2.micro" } resource "aws_security_group" "example" { # ... } # Ensure the security group is created before the EC2 instance depends_on = [aws_security_group.example]
lifecycle: The
lifecycle
meta-argument allows you to control resource lifecycle actions, such as creating, updating, or destroying resources under specific conditions or with specific configurations.resource "aws_instance" "example" { ami = "ami-12345678" instance_type = "t2.micro" # Avoid destroying this resource lifecycle { prevent_destroy = true } }
for_each: The
for_each
meta-argument allows you to create multiple instances of a resource using a map or set of values as the input. It's useful for dynamic resource creation based on external data or configuration.resource "aws_instance" "example" { for_each = { instance1 = "ami-12345678" instance2 = "ami-87654321" } ami = each.value instance_type = "t2.micro" }
provider: The
provider
meta-argument allows you to specify which provider to use for a resource when you have multiple providers of the same type (e.g., multiple AWS accounts).resource "aws_instance" "example" { provider = aws.us_west ami = "ami-12345678" instance_type = "t2.micro" }
These meta-arguments provide flexibility and control over your infrastructure's configuration and lifecycle management. They are powerful tools for handling complex resource relationships, dynamic resource creation, and fine-tuning how Terraform interacts with your infrastructure resources. Understanding and using meta-arguments effectively can help you create and manage infrastructure resources that meet your specific requirements.
Happy Learning!