Day 69(DevOps) - Meta-Arguments in Terraform✅

Day 69(DevOps) - Meta-Arguments in Terraform✅

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 with 0) 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> or module.<NAME> (for example, aws_instance.server) refers to the resource block.

  • <TYPE>.<NAME>[<INDEX>] or module.<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#

Shubham Londhe