Meta-Arguments
If a resource or module block includes a count
argument whose value is a whole number, Terraform will create that many instances.
Basic Syntax
count
is a meta-argument defined by the Terraform language. It can be used with modules and with every resource type.
The count
meta-argument accepts a whole number, and creates that many instances of the resource or module. Each instance has a distinct infrastructure object associated with it, and each is separately created, updated, or destroyed when the configuration is applied.
resource "aws_instance" "server" {
count = 4 # create four similar EC2 instances
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
tags = {
Name = "Server ${count.index}"
}
}
The count
Object
In blocks where count
is set, an additional count
object is available in expressions, so you can modify the configuration of each instance. This object has one attribute:
count.index
— The distinct index number (starting with0
) corresponding to this instance.
Using Expressions in count
The count
meta-argument accepts numeric expressions. However, unlike most arguments, the count
value must be known before Terraform performs any remote resource actions. This means count
can't refer to any resource attributes that aren't known until after a configuration is applied (such as a unique ID generated by the remote API when an object is created).
Referring to Instances
When count
is set, Terraform distinguishes between the block itself and the multiple resource or module instances associated with it. Instances are identified by an index number, starting with 0
.
<TYPE>.<NAME>
ormodule.<NAME>
(for example,aws_instance.server
) refers to the resource block.<TYPE>.<NAME>[<INDEX>]
ormodule.<NAME>[<INDEX>]
(for example,aws_instance.server[0]
,aws_instance.server[1]
, etc.) refers to individual instances.
This is different from resources and modules without count
or for_each
, which can be referenced without an index or key.
Similarly, resources from child modules with multiple instances are prefixed with module.<NAME>[<KEY>]
when displayed in plan output and elsewhere in the UI. For a module without count
or for_each
, the address will not contain the module index as the module's name suffices to reference the module.
Task-01
Create the above Infrastructure as code and demonstrate the use of Count and for_each.
Hands on with count/each
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}"
}
}
terraform init
terraform plan
terraform apply
count.index
— The distinct index number (starting with 0
) corresponding to this instance.
Here are the instances as count=4
for_each
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}"
}
}
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 init
terraform plan
terraform apply
#Multiple key value iteration(main.tf)
We can use the "for_each" meta-argument with a map that has multiple key-value pairs to create instances with different AMIs. In this case, we used 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 used 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.
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-east-1"
}
#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}"
}
}
Navigate to AWS console and verify if instances created.
When to Use for_each
Instead of count
If your instances are almost identical, count
is appropriate. If some of their arguments need distinct values that can't be directly derived from an integer, it's safer to use for_each
.
Before for_each
was available, it was common to derive count
from the length of a list and use count.index
to look up the original list value.
Write about meta-arguments and its use in Terraform.
Coming to Meta-Arguments, they helps us in achieving certain requirements within the resource block.
There are 5 Meta-Arguments in Terraform which are as follows:
depends_on
count
for_each
provider
lifecycle
Meta-arguments are special arguments in Terraform that are used to control how resources are created, updated, or destroyed. They are not specific to any particular resource type, but rather provide a way to configure behavior across all resources in a Terraform configuration.
The main use of meta-arguments in Terraform is to control the dependencies between resources. For example, the "depends_on" meta-argument can be used to specify that a resource depends on another resource. This can be useful when creating resources that require other resources to exist first, such as a load balancer that depends on an auto scaling group.
Another common use of meta-arguments is to control the order in which resources are created. The "count" and "for_each" meta-arguments can be used to create multiple instances of a resource, and the "lifecycle" meta-argument can be used to control when resources are created, updated, or destroyed.
The "provider" meta-argument is also a very important meta-argument in Terraform. It is used to specify the provider that should be used to manage a particular resource. Providers are plugins that Terraform uses to manage resources, such as AWS, Google Cloud, or Azure.
Overall, meta-arguments are a powerful feature of Terraform that can be used to control the behavior of resources in a flexible and granular way. By using meta-arguments effectively, Terraform users can create more robust and scalable infrastructure as code.
linkdin:https://www.linkedin.com/in/gajanan-barure-7351a4140
Happy Learning :)
Thank you for reading!! Hope you find this helpful.
#day69#90daysofdevops#devopscommunity#