Terraform Day 7: Terraform Functions Part: 2

ยท

3 min read

This Blog demonstrates the usage of various Terraform functions such as lookup, count, and condition, along with implementing file provisioners (remote-exec, local-exec). The goal is to dynamically manage infrastructure using variables, conditional logic, and provisioning tasks.

Project Structure

  • ec2.tf: Main file to create EC2 instances.

  • variables.tf: Define variables such as AMIs, instance type, keyname, and environment.

  • terraform.tfvars: Assign values to variables such as AMI IDs for different regions and the environment.

  • null.tf: Implements null_resource to run scripts without recreating instances.

  • userdata.sh: Script to install software on EC2 instances after they are created.

Terraform Functions Overview

1. AMI Lookup

The lookup function helps dynamically retrieve AMI IDs based on the region.

Example:

variable "amis" {
  type = map(string)
}

# In terraform.tfvars
amis = {
  us-east-1 = "ami-0abcd1234efgh5678"
  us-east-2 = "ami-0wxyz1234mnop5678"
}

# In ec2.tf
ami = lookup(var.amis, var.aws_region)

This setup allows us to deploy EC2 instances using region-specific AMIs. For example, AMIs in us-east-1 may not work in us-east-2.

2. Instance Count with Subnet Mapping

We declare three subnets, and each subnet must map to one EC2 instance. By using count, we can define how many instances to create based on the length of subnets.

count = length(var.public_cidr_block)

subnet_id = element(var.subnets, count.index)

3. Conditional Deployment

Using a condition, we can decide how many instances to create based on the environment.

count = var.environment == "Prod" ? 3 : 1

This means if the environment is Prod, 3 instances are created; otherwise, 1 instance is created.

Provisioners

File Provisioning with remote-exec

We use provisioners to apply scripts after EC2 instances are created without recreating the instances.

  • User Data: Initially, the user data script is passed during instance creation.

  • Provisioners: To avoid recreating instances for every change, we use null_resource to run scripts or commands on existing instances.

Example:

resource "null_resource" "cluster" {
  count = length(var.public_cidr_block)

  provisioner "remote-exec" {
    connection {
      type     = "ssh"
      user     = "ec2-user"
      private_key = file("path/to/key.pem")
      host     = aws_instance.example.public_ip
    }
    inline = [
      "sudo bash /tmp/script.sh"
    ]
  }
}

Tainting Resources

If we need to recreate a resource, we can use Terraform's taint feature. Marking a resource as "tainted" forces Terraform to recreate it during the next apply.

Example:

terraform taint null_resource.cluster

This marks the resource as needing recreation, allowing the new script to be applied without affecting the rest of the infrastructure.

Commands

terraform init      # Initialize Terraform
terraform fmt       # Format the code
terraform validate  # Validate the configuration
terraform apply     # Apply the configuration

Taint Example

terraform taint null_resource.cluster
terraform apply

Next Steps

  • Explore Terraform Modules for better structuring and reuse of code.

Interview Tips

What is taint in Terraform? Taint marks a resource for recreation. You can manually taint a resource using the terraform taint command, causing Terraform to destroy and recreate it during the next apply. Conversely, you can "untaint" a resource to prevent it from being recreated.

ย