Terraform: Evolving my Infrastructure as Code Practice with Terraform

In my previous post, I documented getting started with Terraform coming from an AWS CloudFormation background.

As I continue my Terraform learning journey from a CloudFormation background, two concepts that took more effort to grasp are variables and modules. Both offer powerful capabilities for customization and reusability — let’s break it down!

What are Variables?

Terraform variables provide a way to make parts of your configuration customizable at runtime, so you don’t have to hardcode values. For example, you can define a variable to control EC2 instance type:

variable "instance_type" {
  default = "t3.micro" 
}

resource "aws_instance" "app" {
  instance_type = var.instance_type
}

Now users can override the value “t3.micro” default via CLI, environment variable, input prompts etc. By exposing instance types, or database names, as variables, many configurations can reuse your Terraform code!

Assigning an input value to a variable looks like:

terraform apply -var="instance_type=t2.small"

Why use Modules?

Terraform modules help organize and encapsulate reusable pieces of infrastructure in one place. For example, a VPC module:

module "vpc"{
  source              = "../vpc"
  vpc_cidr            = var.vpc_cidr
  public_subnet_cidr  = var.public_subnet_cidr
  private_subnet_cidr = var.private_subnet_cidr
}

module "ec2_instance" {
  source              = "../ec2-instance"
  ami_id              = var.ami_id
  instance_type       = var.instance_type
  instance_name       = var.instance_name
  security_group_name = var.security_group_name
}

This allows easy reuse of the VPC, EC2 definitions across environments. Modules also encourage separation of concerns, testing in isolation, and make collaboration easier via self-contained packages.

Deploying an EC2 Instance and VPC

I have created a set of modules for various AWS services (Ex., VPC, EC2.., etc.)

I have modified my Terraform GitHub repo — (https://github.com/kbrepository/handson_terraform) to add a VPC and an EC2 instance declaration. This includes referencing the variables:

VPC Configuration
## VPC Configuration

resource "aws_vpc" "ExampleVPC" {
  cidr_block = var.vpc_cidr
  tags = {
    Name = var.vpc_tag
  }
}

resource "aws_subnet" "public_subnet" {
  vpc_id            = aws_vpc.ExampleVPC.id
  cidr_block        = var.public_subnet_cidr
  availability_zone = "${var.region}a"
}

resource "aws_subnet" "private_subnet" {
  vpc_id            = aws_vpc.ExampleVPC.id
  cidr_block        = var.private_subnet_cidr
  availability_zone = "${var.region}b"
}
EC2 Configuration
## EC2 Instance configuration 

resource "aws_instance" "example" {
  ami           = var.ami_id
  instance_type = var.instance_type
  tags = {
    Name = var.instance_name
  }
}

Reusable Modules

Following Terraform best practices, I split my configuration into separate main.tfVPC module, and EC2 modules. This improves the organization and reusability of VPC across projects.

image

What’s Next?

In my next post I plan to cover:

  • Automated testing of modules
  • Deployment of load-balanced web applications

For readers interested in learning more about Terraform, I recommend the book Architecting AWS with TerraformIt provides practical, hands-on labs for mastering Terraform on AWS.

Hopefully this gives beginners an easier introduction into how variables and modules work! Check out Terraform’s documentation or reach out with any other questions!

1 thought on “Terraform: Evolving my Infrastructure as Code Practice with Terraform”

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top