π― 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)