Terraform enables you to define cloud infrastructure as code, ensuring consistency and repeatability across environments.
Basic AWS Infrastructure
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
}
}
provider "aws" {
region = var.aws_region
}
# Variables
variable "aws_region" {
default = "us-east-1"
}
variable "environment" {
default = "production"
}
# VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}-vpc"
Environment = var.environment
}
}
# Subnets
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 1}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public-${count.index + 1}"
}
}
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 10}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${var.environment}-private-${count.index + 1}"
}
}
EC2 with Auto Scaling
# ec2.tf
resource "aws_launch_template" "app" {
name_prefix = "${var.environment}-app"
image_id = data.aws_ami.amazon_linux.id
instance_type = "t3.medium"
vpc_security_group_ids = [aws_security_group.app.id]
user_data = base64encode(<<-EOF
#!/bin/bash
yum update -y
yum install -y docker
systemctl start docker
docker run -d -p 80:8080 my-app:latest
EOF
)
iam_instance_profile {
name = aws_iam_instance_profile.app.name
}
tags = {
Environment = var.environment
}
}
resource "aws_autoscaling_group" "app" {
name = "${var.environment}-app-asg"
vpc_zone_identifier = aws_subnet.private[*].id
desired_capacity = 2
min_size = 1
max_size = 10
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
target_group_arns = [aws_lb_target_group.app.arn]
tag {
key = "Name"
value = "${var.environment}-app"
propagate_at_launch = true
}
}
# Auto Scaling Policy
resource "aws_autoscaling_policy" "scale_up" {
name = "scale-up"
autoscaling_group_name = aws_autoscaling_group.app.name
adjustment_type = "ChangeInCapacity"
scaling_adjustment = 1
cooldown = 300
}
RDS Database
# rds.tf
resource "aws_db_instance" "main" {
identifier = "${var.environment}-db"
engine = "postgres"
engine_version = "15.4"
instance_class = "db.t3.medium"
allocated_storage = 20
max_allocated_storage = 100
db_name = "myapp"
username = var.db_username
password = var.db_password
vpc_security_group_ids = [aws_security_group.db.id]
db_subnet_group_name = aws_db_subnet_group.main.name
backup_retention_period = 7
backup_window = "03:00-04:00"
maintenance_window = "Mon:04:00-Mon:05:00"
multi_az = true
deletion_protection = true
skip_final_snapshot = false
tags = {
Environment = var.environment
}
}
Modules for Reusability
# modules/vpc/main.tf
variable "cidr_block" {}
variable "environment" {}
resource "aws_vpc" "this" {
cidr_block = var.cidr_block
tags = { Name = "${var.environment}-vpc" }
}
output "vpc_id" {
value = aws_vpc.this.id
}
# Usage in main.tf
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
environment = "production"
}
Terraform Commands
# Initialize
terraform init
# Plan changes
terraform plan -out=tfplan
# Apply changes
terraform apply tfplan
# Destroy infrastructure
terraform destroy
# Format code
terraform fmt -recursive
# Validate configuration
terraform validate
# Import existing resources
terraform import aws_instance.example i-1234567890abcdef0
Terraform makes infrastructure reproducible and version-controlled. Start with modules for maintainability!