Step 1 — Create Project
Create a new project.
mkdir terraform-functions-lab
cd terraform-functions-lab
Create files:
main.tf
variables.tf
outputs.tf
terraform.tfvars
Step 2 — Terraform Settings Block
This tells Terraform which providers to use.
main.tf
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
local = {
source = "hashicorp/local"
version = "~> 2.4"
}
}
}
Explanation
Settings block defines:
- Terraform version
- required providers
- provider versions
This ensures consistent environments across teams.
Step 3 — Provider Configuration
Add AWS provider.
provider "aws" {
region = var.aws_region
}
Step 4 — Variables
variables.tf
variable "aws_region" {
default = "us-east-2"
}
variable "instance_types" {
type = map(string)
default = {
dev = "t2.micro"
prod = "t2.small"
}
}
variable "ports" {
type = list(number)
default = [22,80,443]
}
variable "servers" {
type = list(string)
default = [
"web",
"api",
"worker"
]
}
Step 5 — Terraform Functions
We will now use these functions:
lookup()
length()
element()
format()
timestamp()
Step 6 — Security Group with Dynamic Block
Dynamic blocks are useful when you want Terraform to generate multiple blocks automatically.
resource "aws_security_group" "web" {
name = "terraform-dynamic-sg"
dynamic "ingress" {
for_each = var.ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
What dynamic block does
Instead of writing:
ingress {22}
ingress {80}
ingress {443}
Terraform generates them automatically.
Step 7 — Using count
Create multiple EC2 instances.
resource "aws_instance" "count_servers" {
count = length(var.servers)
ami = "ami-0c55b159cbfafe1f0"
instance_type = lookup(var.instance_types,"dev")
tags = {
Name = format("count-server-%s", element(var.servers,count.index))
}
}
Functions used
length()
Counts number of elements.
length(var.servers)
If servers list has 3 elements, Terraform creates 3 instances.
element()
Returns element from list.
element(var.servers,count.index)
Example result:
web
api
worker
format()
Formats strings.
format("count-server-%s",name)
Output example:
count-server-web
count-server-api
count-server-worker
lookup()
Gets value from map.
lookup(var.instance_types,"dev")
Returns:
t2.micro
Step 8 — Using for_each
Create instances using for_each.
resource "aws_instance" "foreach_servers" {
for_each = toset(var.servers)
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "foreach-${each.value}"
}
}
Difference
count
server[0]
server[1]
server[2]
for_each
server["web"]
server["api"]
server["worker"]
Step 9 — Using timestamp()
Create file containing deployment time.
resource "local_file" "deployment_info" {
filename = "deployment.txt"
content = "Deployment time: ${timestamp()}"
}
Example output file:
Deployment time: 2026-03-16T14:20:33Z
Step 10 — Terraform Outputs
outputs.tf
output "server_count" {
value = length(var.servers)
}
output "deployment_time" {
value = timestamp()
}
Run:
terraform output
Step 11 — Initialize Terraform
Run:
terraform init -upgrade
What -upgrade does
It upgrades providers to the latest compatible version.
Example:
aws v5.40 -> v5.55
Step 12 — Terraform Plan with Output File
Run:
terraform plan -out=infra.plan
This saves execution plan.
Benefits:
- review plan
- share plan with team
- ensure no changes occur before apply
Apply saved plan:
terraform apply infra.plan
Step 13 — Target Specific Resource
Plan only one resource.
terraform plan -target=local_file.deployment_info
Apply only one resource.
terraform apply -target=local_file.deployment_info
Destroy specific resource.
terraform destroy -target=local_file.deployment_info
Step 14 — Target Security Group
Example:
terraform apply -target=aws_security_group.web
This creates only security group.
Step 15 — Terraform Taint
Taint forces resource recreation.
Example:
terraform taint aws_instance.count_servers[0]
Next apply:
terraform apply
Terraform destroys and recreates that instance.
Step 16 — Terraform Graph
Visualize Terraform infrastructure.
Run:
terraform graph
Example output:
aws_security_group.web
↓
aws_instance.count_servers
↓
outputs
You can convert graph to image:
terraform graph | dot -Tpng > graph.png
Step 17 — Terraform Output Command
View outputs:
terraform output
Example:
server_count = 3
deployment_time = 2026-03-16T14:20:33Z
Step 18 — Terraform at Scale (API Throttling)
When Terraform manages hundreds or thousands of resources, cloud providers may limit requests.
Example:
AWS allows limited API calls per second.
If Terraform sends too many requests:
API throttling
Rate exceeded
Solutions
1️⃣ Reduce parallelism
terraform apply -parallelism=5
Default is 10 parallel operations.
2️⃣ Use modules
Split infrastructure into smaller deployments.
3️⃣ Use workspaces
Separate environments:
dev
stage
prod
4️⃣ Use remote state
Store state in:
S3
Terraform Cloud
Azure Storage
Final Architecture Created
This lab creates:
Security Group
3 EC2 instances using count
3 EC2 instances using for_each
Local file with timestamp
Outputs
also practice:
terraform init -upgrade
terraform plan -out
terraform apply -target
terraform destroy -target
terraform graph
terraform taint
terraform output
Top comments (0)