#Lab: Terraform Modules
Create reusable, maintainable infrastructure with Terraform modules.
#๐ฏ Objectives
- Create custom Terraform modules
- Use module inputs and outputs
- Publish and consume modules
- Implement module best practices
#๐ Prerequisites
- Terraform installed
- AWS credentials configured
#โฑ๏ธ Duration: 45 minutes
#Task 1: Project Structure (5 min)
bash
1mkdir -p ~/terraform-modules-lab
2cd ~/terraform-modules-lab
3
4# Create structure
5mkdir -p modules/vpc modules/ec2 environments/{dev,prod}#Task 2: Create VPC Module (15 min)
#modules/vpc/main.tf
hcl
1variable "vpc_cidr" {
2 description = "CIDR block for VPC"
3 type = string
4 default = "10.0.0.0/16"
5}
6
7variable "environment" {
8 description = "Environment name"
9 type = string
10}
11
12variable "public_subnets" {
13 description = "List of public subnet CIDRs"
14 type = list(string)
15 default = ["10.0.1.0/24", "10.0.2.0/24"]
16}
17
18data "aws_availability_zones" "available" {
19 state = "available"
20}
21
22resource "aws_vpc" "main" {
23 cidr_block = var.vpc_cidr
24 enable_dns_hostnames = true
25 enable_dns_support = true
26
27 tags = {
28 Name = "${var.environment}-vpc"
29 Environment = var.environment
30 }
31}
32
33resource "aws_internet_gateway" "main" {
34 vpc_id = aws_vpc.main.id
35
36 tags = {
37 Name = "${var.environment}-igw"
38 }
39}
40
41resource "aws_subnet" "public" {
42 count = length(var.public_subnets)
43 vpc_id = aws_vpc.main.id
44 cidr_block = var.public_subnets[count.index]
45 availability_zone = data.aws_availability_zones.available.names[count.index]
46 map_public_ip_on_launch = true
47
48 tags = {
49 Name = "${var.environment}-public-${count.index + 1}"
50 }
51}
52
53resource "aws_route_table" "public" {
54 vpc_id = aws_vpc.main.id
55
56 route {
57 cidr_block = "0.0.0.0/0"
58 gateway_id = aws_internet_gateway.main.id
59 }
60
61 tags = {
62 Name = "${var.environment}-public-rt"
63 }
64}
65
66resource "aws_route_table_association" "public" {
67 count = length(aws_subnet.public)
68 subnet_id = aws_subnet.public[count.index].id
69 route_table_id = aws_route_table.public.id
70}#modules/vpc/outputs.tf
hcl
1output "vpc_id" {
2 description = "VPC ID"
3 value = aws_vpc.main.id
4}
5
6output "public_subnet_ids" {
7 description = "Public subnet IDs"
8 value = aws_subnet.public[*].id
9}
10
11output "vpc_cidr" {
12 description = "VPC CIDR block"
13 value = aws_vpc.main.cidr_block
14}#Task 3: Create EC2 Module (10 min)
#modules/ec2/main.tf
hcl
1variable "instance_type" {
2 type = string
3 default = "t3.micro"
4}
5
6variable "subnet_id" {
7 type = string
8}
9
10variable "vpc_id" {
11 type = string
12}
13
14variable "environment" {
15 type = string
16}
17
18data "aws_ami" "amazon_linux" {
19 most_recent = true
20 owners = ["amazon"]
21
22 filter {
23 name = "name"
24 values = ["amzn2-ami-hvm-*-x86_64-gp2"]
25 }
26}
27
28resource "aws_security_group" "web" {
29 name = "${var.environment}-web-sg"
30 vpc_id = var.vpc_id
31
32 ingress {
33 from_port = 80
34 to_port = 80
35 protocol = "tcp"
36 cidr_blocks = ["0.0.0.0/0"]
37 }
38
39 ingress {
40 from_port = 22
41 to_port = 22
42 protocol = "tcp"
43 cidr_blocks = ["0.0.0.0/0"]
44 }
45
46 egress {
47 from_port = 0
48 to_port = 0
49 protocol = "-1"
50 cidr_blocks = ["0.0.0.0/0"]
51 }
52}
53
54resource "aws_instance" "web" {
55 ami = data.aws_ami.amazon_linux.id
56 instance_type = var.instance_type
57 subnet_id = var.subnet_id
58
59 vpc_security_group_ids = [aws_security_group.web.id]
60
61 tags = {
62 Name = "${var.environment}-web"
63 Environment = var.environment
64 }
65}
66
67output "instance_id" {
68 value = aws_instance.web.id
69}
70
71output "public_ip" {
72 value = aws_instance.web.public_ip
73}#Task 4: Use Modules (10 min)
#environments/dev/main.tf
hcl
1terraform {
2 required_providers {
3 aws = {
4 source = "hashicorp/aws"
5 version = "~> 5.0"
6 }
7 }
8}
9
10provider "aws" {
11 region = "us-east-1"
12}
13
14module "vpc" {
15 source = "../../modules/vpc"
16
17 environment = "dev"
18 vpc_cidr = "10.0.0.0/16"
19 public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
20}
21
22module "web_server" {
23 source = "../../modules/ec2"
24
25 environment = "dev"
26 vpc_id = module.vpc.vpc_id
27 subnet_id = module.vpc.public_subnet_ids[0]
28 instance_type = "t3.micro"
29}
30
31output "vpc_id" {
32 value = module.vpc.vpc_id
33}
34
35output "web_server_ip" {
36 value = module.web_server.public_ip
37}#Task 5: Apply Configuration (5 min)
bash
1cd environments/dev
2
3# Initialize
4terraform init
5
6# Plan
7terraform plan
8
9# Apply (if you have AWS credentials)
10# terraform apply
11
12# Destroy when done
13# terraform destroy#โ Success Criteria
- VPC module created with inputs/outputs
- EC2 module created
- Modules consumed in environment
- terraform plan shows correct resources
#๐งน Cleanup
bash
cd environments/dev
terraform destroy -auto-approve 2>/dev/null
cd ~ && rm -rf terraform-modules-lab