AskLearn
Loading...
← Back to Terraform Course
BeginnerGetting Started

Destroy Infrastructure

Clean up and resource management

Tutorial 5: Destroy Infrastructure

Learning Objectives

  • Understand how to safely destroy Terraform-managed infrastructure
  • Learn about partial destruction and resource targeting
  • Understand protection mechanisms for critical resources
  • Practice cleanup procedures and cost management

Prerequisites

  • Completed previous tutorials with running infrastructure
  • Understanding of Terraform state and resource dependencies
  • Awareness of potential data loss implications

Why Destroy Infrastructure?

Common Scenarios

  • Development/Testing: Clean up temporary environments
  • Cost Management: Remove unused resources to save money
  • Environment Refresh: Start with clean slate
  • Decommissioning: Permanently remove old infrastructure
  • Troubleshooting: Remove problematic resources

Important Considerations

  • Data Loss: Destroying resources may result in permanent data loss
  • Dependencies: Some resources must be destroyed in specific order
  • Cost Impact: Verify what you're destroying to avoid surprises
  • Backup: Ensure important data is backed up before destruction

The Destroy Command

Basic Syntax

terraform destroy

Common Options

# Auto-approve (use with caution)
terraform destroy -auto-approve

# Target specific resources
terraform destroy -target=aws_instance.web

# Use variable file
terraform destroy -var-file="production.tfvars"

# Set variables
terraform destroy -var="environment=dev"

Understanding Destruction Order

Dependency Resolution

Terraform destroys resources in reverse dependency order:

  1. Resources with no dependencies first
  2. Resources that depend on others last
  3. Automatic dependency resolution

Example Destruction Order

Given this infrastructure:

VPC → Subnet → Security Group → EC2 Instance → Load Balancer

Destruction order would be:

Load Balancer → EC2 Instance → Security Group → Subnet → VPC

Safe Destruction Practices

Step 1: Review Current State

# List all resources
terraform state list

# Review current configuration
terraform show

# Check outputs
terraform output

Step 2: Plan Destruction

terraform plan -destroy

This shows exactly what will be destroyed:

Terraform will perform the following actions:

  # aws_instance.web will be destroyed
  - resource "aws_instance" "web" {
      - ami                    = "ami-0c55b159cbfafe1d0" -> null
      - instance_type          = "t2.micro" -> null
      # ... all attributes will be destroyed
    }

  # aws_vpc.main will be destroyed
  - resource "aws_vpc" "main" {
      - cidr_block = "10.0.0.0/16" -> null
      # ... all attributes will be destroyed
    }

Plan: 0 to add, 0 to change, 6 to destroy.

Step 3: Backup Important Data

# Backup Terraform state
cp terraform.tfstate terraform.tfstate.backup

# Export important data (example)
terraform output > infrastructure-outputs.txt

# Backup any databases or persistent storage
# This varies by resource type and requirements

Step 4: Execute Destruction

terraform destroy

You'll be prompted for confirmation:

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

Partial Destruction (Targeting)

Destroy Specific Resources

# Destroy only the EC2 instance
terraform destroy -target=aws_instance.web

# Destroy multiple specific resources
terraform destroy -target=aws_instance.web -target=aws_lb.web

Destroy by Resource Type

# Remove all instances (if you have multiple)
terraform destroy -target=aws_instance

# This won't work directly, but you can target each individually

Target Module Resources

# Destroy all resources in a specific module
terraform destroy -target=module.web_servers

Protecting Critical Resources

Prevent Destroy Lifecycle Rule

resource "aws_db_instance" "production" {
  # ... database configuration
  
  lifecycle {
    prevent_destroy = true  # Prevents terraform destroy
  }
}

If you try to destroy this resource:

terraform destroy

You'll get an error:

Error: Instance cannot be destroyed

  on main.tf line 45:
  45: resource "aws_db_instance" "production" {

Resource aws_db_instance.production has lifecycle.prevent_destroy 
set, but the plan calls for this resource to be destroyed.

Override Protection (Use with Extreme Caution)

# Remove the prevent_destroy rule first, then destroy
# OR use -refresh=false and edit state (not recommended)

Handling Destruction Issues

Dependency Errors

Sometimes resources can't be destroyed due to dependencies:

Error: Error deleting VPC: DependencyViolation: The vpc 'vpc-12345' has dependencies and cannot be deleted.

Solutions:

  1. Check for manually created resources
  2. Use AWS Console to identify dependencies
  3. Remove dependencies manually
  4. Use terraform refresh to update state

Resource Not Found Errors

Error: Error deleting instance: InvalidInstanceID.NotFound

Solutions:

  1. The resource was already deleted outside Terraform
  2. Remove from state: terraform state rm aws_instance.web
  3. Or run terraform refresh first

Stuck Resources

Some resources may fail to destroy due to:

  • Protection policies
  • Resource dependencies
  • Service limits
  • Network connectivity issues

Debug approach:

# Enable detailed logging
export TF_LOG=DEBUG
terraform destroy

# Check AWS CloudTrail for API errors
# Review resource-specific documentation

Force Removal from State

When to Use State Removal

  • Resource was deleted outside Terraform
  • Resource is stuck and can't be destroyed
  • Need to stop managing a resource with Terraform

Remove from State (Without Destroying)

# Remove specific resource from state
terraform state rm aws_instance.web

# Remove multiple resources
terraform state rm aws_instance.web aws_instance.app

# Remove entire module
terraform state rm module.web_servers

Warning: This removes the resource from Terraform's knowledge but doesn't destroy the actual resource.

Cost-Effective Destruction Strategies

Stop vs. Destroy

For some resources, stopping is cheaper than destroying and recreating:

# Stop instance instead of destroying
resource "aws_instance" "web" {
  # ... configuration
  
  # Use count to effectively "stop" managing the resource
  count = var.instance_enabled ? 1 : 0
}

Graduated Destruction

For complex environments, destroy in phases:

  1. Phase 1: Destroy compute resources (EC2, containers)
  2. Phase 2: Destroy networking (load balancers, NAT gateways)
  3. Phase 3: Destroy storage and databases (if safe)
  4. Phase 4: Destroy core networking (VPCs, subnets)
# Phase 1
terraform destroy -target=aws_instance.web -target=aws_autoscaling_group.web

# Phase 2
terraform destroy -target=aws_lb.web -target=aws_nat_gateway.main

# Phase 3 (be very careful with data!)
terraform destroy -target=aws_db_instance.main -target=aws_s3_bucket.data

# Phase 4
terraform destroy -target=aws_vpc.main

Data Backup Before Destruction

Database Backup Example

# Create RDS snapshot before destroying
aws rds create-db-snapshot \
  --db-instance-identifier mydb \
  --db-snapshot-identifier mydb-final-snapshot-$(date +%Y%m%d)

# Then destroy with final snapshot

For Terraform-managed snapshots:

resource "aws_db_instance" "main" {
  # ... configuration
  
  # Ensure final snapshot is created
  final_snapshot_identifier = "mydb-final-snapshot"
  skip_final_snapshot      = false
  
  # Backup retention
  backup_retention_period = 7
}

S3 Bucket Backup

# Sync bucket contents before destroying
aws s3 sync s3://my-terraform-bucket ./backup-folder/

# Or enable versioning and lifecycle policies in Terraform

Automation and Scripts

Pre-Destruction Checklist Script

#!/bin/bash
# pre-destroy-checklist.sh

echo "Pre-Destruction Checklist"
echo "========================"

# Check current resources
echo "Current resources:"
terraform state list

# Show destruction plan
echo -e "\nDestruction plan:"
terraform plan -destroy -out=destroy.plan

# Prompt for confirmation
echo -e "\nPlease review the destruction plan above."
read -p "Are you sure you want to proceed? (yes/no): " confirm

if [ "$confirm" = "yes" ]; then
    echo "Proceeding with destruction..."
    terraform apply destroy.plan
else
    echo "Destruction cancelled."
    rm -f destroy.plan
fi

Post-Destruction Verification

#!/bin/bash
# post-destroy-verify.sh

echo "Post-Destruction Verification"
echo "============================"

# Check if any resources remain
resource_count=$(terraform state list | wc -l)

if [ $resource_count -eq 0 ]; then
    echo "✓ All resources successfully destroyed"
else
    echo "⚠ Warning: $resource_count resources remain in state"
    terraform state list
fi

# Check for orphaned AWS resources (example)
echo -e "\nChecking for potential orphaned resources..."
aws ec2 describe-instances --query 'Reservations[].Instances[?Tags[?Key==`CreatedBy` && Value==`Terraform`]]'

Environment-Specific Destruction

Development Environment

# Quick destruction for dev environments
terraform destroy -auto-approve

Staging Environment

# More cautious approach for staging
terraform plan -destroy
# Review plan
terraform destroy

Production Environment

# Very careful approach for production
# 1. Full backup
# 2. Team approval
# 3. Maintenance window
# 4. Gradual destruction

# Create destruction plan
terraform plan -destroy -out=prod-destroy.plan

# Have team review the plan file
# Apply during maintenance window
terraform apply prod-destroy.plan

Monitoring Destruction

Logging

# Enable detailed logging
export TF_LOG=INFO
export TF_LOG_PATH=./terraform-destroy.log

terraform destroy

# Review logs
cat terraform-destroy.log

Cost Tracking

  • Monitor AWS billing during destruction
  • Verify resources are actually removed
  • Check for any ongoing charges

Recovery Procedures

Accidental Destruction Recovery

From State Backup

# Restore state from backup
cp terraform.tfstate.backup terraform.tfstate

# Recreate infrastructure
terraform plan
terraform apply

From Version Control

# Restore configuration from git
git checkout HEAD~1 main.tf

# Recreate infrastructure
terraform init
terraform plan
terraform apply

Partial Recovery

# Import existing resources that weren't destroyed
terraform import aws_instance.web i-1234567890abcdef0

# Recreate only what was lost
terraform plan
terraform apply

Best Practices Checklist

Before Destroying

  • Review terraform plan -destroy output
  • Backup critical data and configurations
  • Verify backup integrity
  • Check for any prevent_destroy lifecycle rules
  • Notify team members (for shared environments)
  • Document the reason for destruction

During Destruction

  • Monitor the destruction process
  • Watch for any errors or stuck resources
  • Be prepared to handle dependency issues
  • Keep logs of the destruction process

After Destruction

  • Verify all resources are destroyed
  • Check cloud provider billing/console
  • Clean up any orphaned resources
  • Update documentation
  • Remove any DNS entries or external references

Common Mistakes to Avoid

  1. Not checking dependencies: Always review the destruction plan
  2. Forgetting data backup: Backup before destroying data resources
  3. Ignoring costs: Some resources continue billing even after "destruction"
  4. Not using targeting: Destroying everything when you only need to remove specific resources
  5. Force removal without cleanup: Using terraform state rm without cleaning up actual resources

Key Takeaways

  • Always run terraform plan -destroy before actual destruction
  • Terraform destroys resources in reverse dependency order
  • Use lifecycle rules to protect critical resources
  • Backup important data before destruction
  • Use targeting for partial destruction when appropriate
  • Monitor costs and verify complete removal
  • Have recovery procedures in place for accidental destruction

Next Steps

  1. Complete Tutorial 6: Variables and Configuration
  2. Learn about remote state management
  3. Explore workspace management for multiple environments
  4. Practice with modules and advanced configurations

Additional Resources