⏱ Duration: 5 Hours
📚 Learning Objectives
- Understand Terraform providers and resources
- Work with variables and outputs
- Master terraform init, plan, apply workflow
- Learn Terraform file structure and syntax
📖 Core Concepts (2 Hours)
Terraform File Structure
my-terraform-project/
├── main.tf # Main configuration (resources)
├── variables.tf # Input variable declarations
├── outputs.tf # Output value declarations
├── terraform.tfvars # Variable values (don't commit secrets!)
├── providers.tf # Provider configurations
└── .terraform/ # Downloaded providers (gitignore this)Providers
Providers are plugins that Terraform uses to interact with cloud APIs.
# providers.tf
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# Configure the AWS Provider
provider "aws" {
region = "us-east-1"
# Optional: Use specific profile
# profile = "my-aws-profile"
default_tags {
tags = {
Environment = "Development"
ManagedBy = "Terraform"
}
}
}Resources
Resources are the infrastructure objects Terraform manages.
# Resource syntax:
# resource "TYPE" "NAME" {
# argument = value
# }
# Example: S3 Bucket
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-unique-bucket-name-12345"
tags = {
Name = "My Terraform Bucket"
}
}
# Reference other resources
resource "aws_s3_bucket_versioning" "my_bucket_versioning" {
bucket = aws_s3_bucket.my_bucket.id # Reference!
versioning_configuration {
status = "Enabled"
}
}Variables
# variables.tf - Declare variables
variable "region" {
description = "AWS region to deploy to"
type = string
default = "us-east-1"
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.micro"
}
variable "allowed_ports" {
description = "List of allowed ports"
type = list(number)
default = [22, 80, 443]
}
variable "tags" {
description = "Tags for resources"
type = map(string)
default = {
Environment = "dev"
Project = "demo"
}
}
# Use variables with var.name
provider "aws" {
region = var.region
}Variable Values
# terraform.tfvars - Set values
region = "us-west-2"
instance_type = "t3.micro"
allowed_ports = [22, 80, 443, 8080]
tags = {
Environment = "production"
Project = "webapp"
}
# Or pass via command line:
terraform apply -var="region=us-west-2"
# Or environment variables:
export TF_VAR_region="us-west-2"Outputs
# outputs.tf
output "bucket_name" {
description = "Name of the S3 bucket"
value = aws_s3_bucket.my_bucket.id
}
output "bucket_arn" {
description = "ARN of the S3 bucket"
value = aws_s3_bucket.my_bucket.arn
}
output "bucket_domain" {
description = "Domain name of the bucket"
value = aws_s3_bucket.my_bucket.bucket_domain_name
}
# After apply, view outputs:
# terraform output
# terraform output bucket_nameTerraform Workflow
┌─────────────────────────────────────────────┐
│ terraform init │
│ • Downloads provider plugins │
│ • Initializes backend │
│ • Creates .terraform directory │
└─────────────────┬───────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ terraform plan │
│ • Reads current state │
│ • Compares with configuration │
│ • Shows what will change │
│ • Does NOT make any changes │
└─────────────────┬───────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ terraform apply │
│ • Executes the plan │
│ • Creates/updates/deletes resources │
│ • Updates state file │
└─────────────────┬───────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ terraform destroy │
│ • Removes all managed resources │
│ • Use when done to avoid charges │
└─────────────────────────────────────────────┘🔬 Hands-on Lab (2.5 Hours)
Lab 1: Create S3 Bucket with Variables
# Create project structure
mkdir -p ~/terraform-labs/lab2-s3
cd ~/terraform-labs/lab2-s3
# providers.tf
cat > providers.tf << 'EOF'
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
EOF
# variables.tf
cat > variables.tf << 'EOF'
variable "region" {
description = "AWS region"
type = string
default = "us-east-1"
}
variable "bucket_prefix" {
description = "Prefix for bucket name"
type = string
default = "my-terraform"
}
variable "environment" {
description = "Environment name"
type = string
default = "dev"
}
EOF
# main.tf
cat > main.tf << 'EOF'
resource "aws_s3_bucket" "demo" {
bucket = "${var.bucket_prefix}-${var.environment}-${random_id.suffix.hex}"
tags = {
Name = "Demo Bucket"
Environment = var.environment
ManagedBy = "Terraform"
}
}
resource "random_id" "suffix" {
byte_length = 4
}
resource "aws_s3_bucket_versioning" "demo" {
bucket = aws_s3_bucket.demo.id
versioning_configuration {
status = "Enabled"
}
}
EOF
# outputs.tf
cat > outputs.tf << 'EOF'
output "bucket_name" {
value = aws_s3_bucket.demo.id
}
output "bucket_arn" {
value = aws_s3_bucket.demo.arn
}
output "bucket_region" {
value = aws_s3_bucket.demo.region
}
EOFLab 2: Run Terraform Commands
# Initialize - download providers
terraform init
# Validate configuration
terraform validate
# Format code (auto-fix formatting)
terraform fmt
# Plan - see what will be created
terraform plan
# Apply - create resources
terraform apply
# Type 'yes' when prompted
# View outputs
terraform output
terraform output bucket_name
# View state
terraform state list
terraform state show aws_s3_bucket.demo
# Destroy when done (save money!)
terraform destroyLab 3: Using tfvars Files
# Create different environments
cat > dev.tfvars << 'EOF'
region = "us-east-1"
environment = "dev"
bucket_prefix = "myapp"
EOF
cat > prod.tfvars << 'EOF'
region = "us-west-2"
environment = "prod"
bucket_prefix = "myapp"
EOF
# Apply with specific tfvars
terraform plan -var-file="dev.tfvars"
terraform apply -var-file="dev.tfvars"
# Or for production
terraform plan -var-file="prod.tfvars"✅ Day 2 Checklist
- Understand providers and how to configure them
- Can create and reference resources
- Know how to use variables and outputs
- Master init, plan, apply, destroy workflow
- Created S3 bucket with Terraform