Objective
Build reusable Terraform modules and deploy infrastructure using them.
You will:
- Create a VPC module
- Create an EC2 module
- Reuse modules
- Understand module inputs, outputs, and structure
Part 1 – Project Structure (Real-world layout)
terraform-modules-lab/
│
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ │
│ └── ec2/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
├── env/
│ └── dev/
│ ├── main.tf
│ ├── variables.tf
│ └── terraform.tfvars
Part 2 – Create VPC Module
modules/vpc/main.tf
resource "aws_vpc" "main" {
cidr_block = var.cidr_block
tags = {
Name = var.name
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = var.subnet_cidr
availability_zone = var.az
tags = {
Name = "${var.name}-subnet"
}
}
modules/vpc/variables.tf
variable "cidr_block" {}
variable "subnet_cidr" {}
variable "az" {}
variable "name" {}
modules/vpc/outputs.tf
output "vpc_id" {
value = aws_vpc.main.id
}
output "subnet_id" {
value = aws_subnet.public.id
}
Part 3 – Create EC2 Module
modules/ec2/main.tf
resource "aws_instance" "web" {
ami = var.ami
instance_type = var.instance_type
subnet_id = var.subnet_id
tags = {
Name = var.name
}
}
modules/ec2/variables.tf
variable "ami" {}
variable "instance_type" {}
variable "subnet_id" {}
variable "name" {}
modules/ec2/outputs.tf
output "instance_id" {
value = aws_instance.web.id
}
Part 4 – Use Modules (Dev Environment)
env/dev/main.tf
provider "aws" {
region = "us-east-1"
}
module "vpc" {
source = "../../modules/vpc"
cidr_block = "10.0.0.0/16"
subnet_cidr = "10.0.1.0/24"
az = "us-east-1a"
name = "dev-vpc"
}
module "ec2" {
source = "../../modules/ec2"
ami = "ami-0c55b159cbfafe1f0" # update for your region
instance_type = "t2.micro"
subnet_id = module.vpc.subnet_id
name = "dev-server"
}
env/dev/terraform.tfvars
# optional for extension later
Part 5 – Run the Lab
cd env/dev
terraform init
terraform plan
terraform apply
Expected Result
You should get:
- 1 VPC
- 1 Subnet
- 1 EC2 instance inside that subnet
Part 6 – Important Concepts (Interview + Real-world)
1. What is a module?
A module is:
A reusable Terraform configuration block
2. Module Flow
Root Module (env/dev)
↓
Calls Module (vpc, ec2)
↓
Creates Resources
3. How data flows
- Input → variables
- Output → used by other modules
Example:
subnet_id = module.vpc.subnet_id
Part 7 – Advanced Tasks
Task 1 – Add Security Group Module
Create:
modules/security-group
- Allow port 22
- Allow port 80
- Attach to EC2
Task 2 – Multiple EC2 Instances
Update EC2 module:
count = var.instance_count
Task 3 – Multi-environment
Create:
env/
dev/
stage/
prod/
Each with different:
- instance size
- CIDR block
Task 4 – Remote Module (REAL DevOps)
Push module to GitHub:
source = "git::https://github.com/your-repo/vpc-module.git"
Part 8 – Production Best Practices
DO:
- Use modules for reusable components
- Separate env (dev/stage/prod)
- Use outputs between modules
- Keep modules small and focused
DON'T:
- Hardcode values
- Mix everything in one file
- Create giant modules
Part 9 – Real Interview Questions
- What is the difference between root module and child module?
- How do modules communicate?
- Can modules call other modules?
- How do you version modules in production?
- What is the difference between local module and remote module?
Part 10 – Real Production Insight (Very Important)
In real companies:
You will see:
-
terraform-modulesrepo (reusable) -
terraform-liverepo (env-specific)
Example:
infra-modules/
infra-live/
Top comments (0)