Terraform Tutorial — Resources Practice Exercises
Practice creating, configuring, and managing Terraform resources.
Exercise 1: Read a Resource Block
Task: Given this resource block, identify: the resource type, the local name, two required arguments, and how you would reference the instance’s public IP elsewhere.
resource "aws_instance" "app_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.small"
key_name = "my-key"
tags = {
Name = "app-server"
}
}
Answer
- Resource type:
aws_instance - Local name:
app_server - Required arguments:
amiandinstance_type - Reference public IP:
aws_instance.app_server.public_ip
Exercise 2: Dependencies
Task: Write a VPC and a subnet where the subnet depends on the VPC. Use an implicit dependency (reference).
Answer
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "main-vpc"
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
tags = {
Name = "public-subnet"
}
}
The reference aws_vpc.main.id creates an implicit dependency — Terraform creates the VPC before the subnet.
Exercise 3: Lifecycle
Task: Write a resource for an RDS database that cannot be accidentally destroyed and creates a new instance before destroying the old one during updates.
Answer
resource "aws_db_instance" "main" {
allocated_storage = 20
engine = "postgres"
engine_version = "15.4"
instance_class = "db.t3.micro"
db_name = "mydb"
username = "admin"
password = var.db_password
lifecycle {
prevent_destroy = true
create_before_destroy = true
}
}
Exercise 4: count vs for_each
Task: Create three S3 buckets using for_each with the names “logs”, “assets”, and “backups”. Each bucket should be named myproject-<name>.
Answer
resource "aws_s3_bucket" "buckets" {
for_each = toset(["logs", "assets", "backups"])
bucket = "myproject-${each.value}"
tags = {
Name = each.value
ManagedBy = "terraform"
}
}
Exercise 5: Full Resource Configuration
Task: Write a complete Terraform configuration that creates an EC2 instance with a security group allowing HTTP (port 80) inbound traffic. The security group should reference a VPC.
Answer
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Allow HTTP inbound traffic"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "web-server"
}
}
Chapter Summary
In this chapter, you learned:
- The resource block anatomy: type, local name, arguments, and computed attributes
- How to create an S3 bucket step-by-step with init, plan, apply, and destroy
- Implicit dependencies through references and explicit dependencies with
depends_on - The lifecycle block:
create_before_destroy,prevent_destroy,ignore_changes - Meta-arguments:
count,for_each,depends_on,provider,lifecycle
Next up: Variables — making your configuration reusable.