Introduction:)
🚀 #Day63 of #90DaysOfDevOps 🛠️
Exploring Terraform Meta-Arguments! Today, dive into the powerful meta-arguments of Terraform—key configuration options that add flexibility and control to your infrastructure. From managing dependencies to dynamic resource creation, let's unleash the true potential of Terraform!
What are Meta-Arguments in Terraform?
In Terraform, meta-arguments are special configuration options that can be applied to resources and modules to control their behavior within a Terraform configuration.
These meta-arguments provide additional functionality and customization options beyond the basic configuration of a resource or module.
Type of Meta-Arguments in Terraform
There are 5 Meta-Arguments in Terraform, which are as follows:
count
depends_on
for_each
lifecycle
provider
count
In Terraform, a resource block configures only one infrastructure object by default. We can define the meta-argument if we want multiple resources with the same configurations. This will reduce the overhead of duplicating the resource block a number of times.
count
require a whole number and will then create that resource that number of times. To identify each of them, we use the count.index
which is the index number corresponds to each resource. The index ranges from 0 to count-1.
HandsOn
Create a new Terraform configuration file, e.g.,
aws_instance.tf
If we want to create the multiple instance usining same configuration
resource "aws_instance" "example" { ami = "ami-0557a15b87f6559cf" instance_type = "t2.micro" count = 3 # Create 3 instances tags = { Name = "example-instance-${count.index + 1}" } }
In this example:
count = 3
specifies that three instances of theaws_instance
resource will be created.${count.index + 1}
is used to generate a unique name for each instance by incorporating the instance index. Thecount.index
starts from 0, so adding 1 ensures that the instances are named sequentially
Run the following Terraform commands in your terminal:
terraform init terraform plan terraform apply
Before init make sure you aws required configuration blocks
As we see after using the terraform plan, it generate the 3 instances with their names
Verify
As we see instance has created with unique names
depend_on
Terraform has a feature of identifying resource dependency. This means that Terraform internally knows the sequence in which the dependent resources needs to be created whereas the independent resources are created parallelly.
But in some scenarios, some dependencies are there that cannot be automatically inferred by Terraform. In these scenarios, a resource relies on some other resource’s behaviour but it doesn’t access any of the resource’s data in arguments.
For those dependencies, we’ll use depends_on
meta-argument to explicitly define the dependency.
In simple explanation, depend_on is used when you need one resource to be created or updated before another.
Note: depends_on
meta-argument must be a list of references to other resources in the same calling resource.
Syntax:
depends_on = [resource_type.resource_name, ...]
HandsOn
Create a new Terraform configuration , and add the following content:
resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" tags = { Name = "example-instance" } } resource "aws_security_group" "example_sg" { name = "example-sg" description = "Example Security Group" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } # Explicitly depend on the aws_instance resource depends_on = [aws_instance.example] }
In this example,
theaws_security_group
resource explicitly depends on theaws_instance
resource usingdepends_on
.
This ensures that Terraform will create or update theaws_instance
resource before attempting to manage theaws_security_group
resource.After planning the configuration we see that first ec2 instance will created then the security group
for_each
As specified in the count meta-argument, that the default behaviour of a resource is to create a single infrastructure object which can be overridden by using count
, but there is one more flexible way of doing the same which is by using for_each
meta argument.
Note: The for_each
meta argument accepts a map or set of strings.
Syntax:
resource "resource_type" "resource_name" {
for_each = <map or set>
# Resource configuration
}
HandsOn
Create a new Terraform configuration , and add the following content:
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}" } }
Plan the configuration
terraform plan
lifecycle
The lifecycle
meta-argument defines the lifecycle for the resource. As per the resource behaviour, Terraform can do the following:
create a resource
destroy a resource
updated resource in place
update resource by deleting existing and create new
Here are some key aspects and options provided by the lifecycle
block:
create_before_destroy
Attribute: (Type: Bool)Controls whether Terraform creates the replacement resource before destroying the old one during updates.
Example:
lifecycle { create_before_destroy = true }
prevent_destroy
Attribute: (Type: Bool)Prevents Terraform from destroying the resource. This can be useful to avoid accidental deletion of critical resources.
Example:
lifecycle { prevent_destroy = true }
ignore_changes
Attribute: (Type: List(Attribute Names))Instructs Terraform to ignore changes to specific attributes during updates. This can be useful for certain attributes that might change outside of Terraform's control.
Example:
lifecycle { ignore_changes = [attribute_name] }
HandsOn
Create a new Terraform configuration , and add the following content:
resource "aws_instance" "example" { ami = "ami-12345678" instance_type = "t2.micro" lifecycle { create_before_destroy = true prevent_destroy = false ignore_changes = [tags] } }
Plan the configuration
provider
provider
meta-argument specifies which provider to use for a resource. This is useful when you are using multiple providers which is usually used when you are creating multi-region resources.
To differentiate those providers, you use an alias
field.
The resource then references the same alias
field of the provider as provider.alias
to tell which one to use.
HandsOn
Create a new Terraform configuration , and add the following content:
## Default Provider provider "aws" { region = "us-east-1" } ## Another Provider provider "aws" { alias = "mumbai" region = "ap-south-1" } ## Referencing the other provider resource "google_compute_instance" "example" { provider = aws.mumbai }
what Happens When You Apply This Code?
When you apply this Terraform configuration using
terraform apply
, the following will happen:The default AWS provider with the region "us-east-1" is configured.
Another AWS provider with the alias "mumbai" and the region "ap-south-1" is configured.
The instance is created using the AWS provider configuration with the "mumbai" alias.
Choosing Between for_each
and count
in Terraform
for_each: Used for dynamic resource creation with different configurations for each instance.
count: Used for duplicating the block with the same configuration for each instance.
Short Explanations:-
count
:
Purpose: Controls the number of instances of a resource to create.
Use Case: Useful when you need to create multiple copies of the same resource, such as multiple EC2 instances.
depends_on
:
Purpose: Specifies explicit dependencies between resources, ensuring proper sequencing during creation and updates.
Use Case: Useful when you have dependencies between resources, and you need one resource to be created or updated before another.
provider
:
Purpose: Specifies the provider alias for a particular resource, allowing the use of multiple providers of the same type within a configuration.
Use Case: Useful in scenarios where you have multiple environments or cloud providers.
lifecycle
:
Purpose: Provides advanced control over the lifecycle of a resource, including options like
create_before_destroy
andprevent_destroy
.Use Case: Useful when you need fine-grained control over resource replacement and destruction behavior.
for_each
:
Purpose: Allows dynamic creation of multiple instances of a resource based on a map or set of strings.
Use Case: Useful when you want to create resources dynamically based on input data or variables.
Connect with me:)
Thank you for diving into this blog with me! I trust you found the information both helpful and enlightening. To stay updated on the latest in DevOps 🚀, make sure to follow me. Remember, staying informed means staying ahead in the dynamic world of DevOps!
Feel free to connect with me on:
For more updates and engaging discussions on DevOps, let's connect! 🚀 #DevOpsCommunity