Terraform: How to prevent accidental deletion of resources

Updated: February 3, 2024 By: Guest Contributor Post a comment

Introduction

Terraform, a widely used Infrastructure as Code (IaC) tool, offers great flexibility and control over infrastructure provisioning and management. However, this power also brings potential risks; among them is the accidental deletion of critical infrastructure components. This article aims to guide you through various strategies to prevent such mishaps, enhancing your Terraform scripts with safeguards.

To start with, Terraform’s lifecycle management capabilities are fundamental in preventing unintentional modifications or deletions. The lifecycle block within resource definitions is crucial. Let’s explore this feature through examples, progressing from basic usage to more advanced practices.

Understanding Lifecycle Block

The lifecycle block within a Terraform resource definition allows you to customize how changes to the resource are applied. The most relevant attributes for preventing accidental deletion are prevent_destroy, create_before_destroy, and ignore_changes.

resource "aws_instance" "example" {
  ami           = "ami-123456"
  instance_type = "t2.micro"

  lifecycle {
    prevent_destroy = true
  }
}

By setting prevent_destroy = true, Terraform will refuse to delete this resource, even if a terraform destroy command is issued. This safeguards your key infrastructure components against accidental deletion but requires manual adjustment to remove this protection when you intend to delete the resource.

Granular Control with Conditional Expressions

As your Terraform projects grow, you might find the need for more granular control over infrastructure changes. Conditional expressions in conjunction with lifecycle block attributes offer a sophisticated way to manage this. Suppose you want to protect production resources but allow clearing test environments:

variable "environment" {
  description = "The deployment environment"
  type        = "string"
}

resource "aws_instance" "example" {
  ami           = "ami-123456"
  instance_type = "t2.micro"

  lifecycle {
    prevent_destroy = var.environment == "production" ? true : false
  }
}

This configuration ensures that resources in a production environment are safeguarded against accidental deletion, while deployment and testing in other environments remain flexible.

Utilizing Terraform State Locking

Terraform state locking is another essential feature to prevent accidental infrastructure changes. When Terraform modifies your infrastructure, it locks the state file. This mechanism prevents concurrent executions that could lead to conflicts or accidental deletions. Most Terraform backends support state locking. To enable it, specify a backend that supports locking in your Terraform configuration:

terraform {
  backend "s3" {
    bucket         = "your-terraform-state-bucket"
    key            = "path/to/your/terraform/state/file"
    region         = "us-east-1"
    dynamodb_table = "your-terraform-state-lock"
    encrypt        = true
  }
}

This configuration stores the Terraform state in an S3 bucket and uses a DynamoDB table for state locking, providing an additional layer of protection.

Backup Strategies

Besides preventing accidental deletion, having a solid backup strategy for your Terraform state files ensures that you can recover from unintended changes. Regular backups, possibly automated through CI/CD pipelines, can provide peace of mind. Consider using cloud storage services for automated, scheduled backups of your Terraform state files.

Advance Practices

As you become more comfortable with these safety mechanisms, exploring advanced practices becomes essential. Delving into custom provider development or employing external tools for monitoring and enforcing policy as code could offer further protection against accidental deletions or changes.

For instance, employing open-source tools like Terraform Cloud or Enterprise versions, which feature policy as code (via Sentinel) and enhanced state management, could introduce increased guardrails for your infrastructure provisioning processes.

Conclusion

Preventing accidental deletion of resources in Terraform is crucial for managing robust and resilient infrastructure. By strategically utilizing the lifecycle block, employing state locking, maintaining diligent backups, and exploring advanced practices, you can significantly mitigate the risks of unintended changes. Protecting your infrastructure begins with thoughtful Terraform script enhancements and extends into comprehensive infrastructure management strategies.