๐ฏ Lab Goal
You will build a modular Terraform project that:
- Creates IAM users + EC2
- Uses
for_each,count,zipmap - Demonstrates lifecycle rules
- Shows dependency handling
- Simulates scale practices
- Uses targeting & refresh control
๐งฑ STEP 1 โ Project Structure (Scaling Best Practice)
terraform-scale-lab/
โ
โโโ iam/
โ โโโ main.tf
โ
โโโ ec2/
โ โโโ main.tf
โ
โโโ shared/
โ โโโ variables.tf
โ
โโโ root/
โโโ main.tf
โ This simulates:
- Large infra split into modules
- Reduces API calls
- Used in real companies
๐งฉ STEP 2 โ Shared Variables (Object + Map + Set)
๐ shared/variables.tf
variable "users" {
type = set(string)
default = ["alice", "bob", "john"]
}
variable "amis" {
type = map(string)
default = {
dev = "ami-123456"
prod = "ami-654321"
}
}
variable "instance_config" {
type = object({
instance_type = string
count = number
})
default = {
instance_type = "t2.micro"
count = 2
}
}
โ Covers:
- set
- map
- object
๐ค STEP 3 โ IAM Module (for_each + zipmap)
๐ iam/main.tf
# Create IAM users using for_each
resource "aws_iam_user" "users" {
for_each = var.users
name = each.value
}
# Output names
output "user_names" {
value = [for u in aws_iam_user.users : u.name]
}
# Output ARNs
output "user_arns" {
value = [for u in aws_iam_user.users : u.arn]
}
# โ
zipmap usage (IMPORTANT FOR EXAM)
output "user_map" {
value = zipmap(
[for u in aws_iam_user.users : u.name],
[for u in aws_iam_user.users : u.arn]
)
}
โ You just implemented:
- for_each
- splat alternative (for loop)
- zipmap()
๐ฅ๏ธ STEP 4 โ EC2 Module (count + lifecycle + depends_on)
๐ ec2/main.tf
# Security group
resource "aws_security_group" "web" {
name = "web-sg"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
# EC2 instances using count
resource "aws_instance" "web" {
count = var.instance_config.count
ami = var.amis["dev"]
instance_type = var.instance_config.instance_type
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "web-${count.index}"
}
# โ
lifecycle rules
lifecycle {
create_before_destroy = true
ignore_changes = [tags]
}
}
โ You covered:
- count
- lifecycle
- implicit dependency (SG โ EC2)
๐ STEP 5 โ ROOT MODULE (Connect Everything)
๐ root/main.tf
provider "aws" {
region = "us-east-1"
}
# Import shared variables
module "iam" {
source = "../iam"
users = var.users
}
module "ec2" {
source = "../ec2"
amis = var.amis
instance_config = var.instance_config
# Explicit dependency example
depends_on = [module.iam]
}
๐งช STEP 6 โ Initialize & Run
cd root
terraform init
terraform plan
terraform apply
๐จ STEP 7 โ API THROTTLING SIMULATION
Now simulate large infra behavior:
terraform plan
๐ Terraform will:
- Refresh ALL resources
- Call AWS APIs multiple times
โก STEP 8 โ SOLUTION 1: TARGETING
terraform apply -target=module.ec2
โ
Only EC2 runs
โ
Less API calls
โก STEP 9 โ SOLUTION 2: DISABLE REFRESH
terraform plan -refresh=false
โ
Skips API calls
โ ๏ธ Use only when state is trusted
โก STEP 10 โ TEST LIFECYCLE (IMPORTANT)
Change tag manually in AWS Console:
Add:
Env = production
Now run:
terraform apply
๐ Terraform will NOT remove it
โ
Because:
ignore_changes = [tags]
โก STEP 11 โ TEST create_before_destroy
Change AMI:
ami = "new-ami-id"
Run:
terraform apply
๐ Terraform:
- Creates new instance
- Then destroys old
โ No downtime
โก STEP 12 โ TEST DEPENDENCY
Remove depends_on and observe order.
Then add back:
depends_on = [module.iam]
๐ Forces IAM creation first
โก STEP 13 โ COMMENTS PRACTICE
Add all types:
# Single line comment
// Another comment
/*
Multi-line comment
for disabling resources
*/
๐ง STEP 14 โ count vs for_each TEST
Change IAM to count (bad practice test)
count = 3
name = "user-${count.index}"
๐ Then reorder list โ resources recreated
โ This is WHY for_each is better
๐ฏ FINAL
You just practiced:
Scaling & API
- Terraform refresh causes API throttling
- Split projects
- Use -target
- Use -refresh=false carefully
Data Handling
- zipmap()
- map, set, object
Resource Behavior
-
lifecycle:
- ignore_changes
- create_before_destroy
- prevent_destroy (concept)
Dependencies
- implicit vs explicit
Iteration
- count (risky)
- for_each (production-safe)
Q: Why does Terraform cause API throttling?
Answer:
Because every plan performs a state refresh, calling cloud APIs for every resource, which can exceed provider rate limits in large infrastructures.
Top comments (0)