Crisp answer: A resource block declares a piece of infrastructure to create and manage. Every resource has a type (from the provider), a local name (for referencing within the config), and arguments that configure it.
Anatomy:
resource "<PROVIDER>_<TYPE>" "<LOCAL_NAME>" {
# arguments
}
resource "aws_instance" "web" { # type: aws_instance, name: web
ami = "ami-0abc123"
instance_type = "t3.micro"
}
resource "aws_security_group" "app" { # type: aws_security_group, name: app
name = "app-sg"
vpc_id = aws_vpc.main.id # references another resource
}
Referencing a resource:
# Pattern: <TYPE>.<LOCAL_NAME>.<ATTRIBUTE>
aws_vpc.main.id
aws_instance.web.private_ip
aws_security_group.app.arn
aws_s3_bucket.logs.bucket
Meta-arguments that work on any resource:
resource "aws_instance" "web" {
ami = "ami-0abc123"
instance_type = "t3.micro"
# count — create multiple identical resources
count = 3
# Reference: aws_instance.web[0], aws_instance.web[1], aws_instance.web[2]
tags = { Name = "web-${count.index}" }
# for_each — create one resource per map entry or set element
# (cannot use both count and for_each)
}
resource "aws_iam_user" "team" {
for_each = toset(["alice", "bob", "carol"])
name = each.key
# Reference: aws_iam_user.team["alice"], aws_iam_user.team["bob"]
}
resource "aws_subnet" "private" {
for_each = var.subnet_map # map(string)
vpc_id = aws_vpc.main.id
cidr_block = each.value # map value
availability_zone = each.key # map key
}
depends_on:
resource "aws_eks_node_group" "workers" {
cluster_name = aws_eks_cluster.main.name
node_role_arn = aws_iam_role.node.arn
depends_on = [
aws_iam_role_policy_attachment.worker_node,
aws_iam_role_policy_attachment.cni,
]
}
lifecycle:
resource "aws_rds_cluster" "main" {
cluster_identifier = "prod-db"
lifecycle {
create_before_destroy = true # New resource before old is destroyed
prevent_destroy = true # Block accidental destruction
ignore_changes = [tags] # Ignore tag changes managed elsewhere
}
}
What to say in the interview:
"A resource block is the fundamental unit in Terraform. Type plus local name is the address used to reference it everywhere else. The meta-arguments that work on any resource are count and for_each for creating multiple instances, depends_on for explicit ordering, and lifecycle for controlling create, update, and destroy behaviour. count gives you indexed instances, for_each gives you named instances keyed by map key or set element — prefer for_each because it's more robust to index shifting when items are removed."