DEV Community

Aisalkyn Aidarova
Aisalkyn Aidarova

Posted on

LAB: Terraform Lifecycle (FULL HANDS-ON)

✅ What is lifecycle (quick recap)

lifecycle block controls how Terraform handles resource changes:

lifecycle {
  create_before_destroy = true
  prevent_destroy       = true
  ignore_changes        = [...]
}
Enter fullscreen mode Exit fullscreen mode

🚀

🎯 Goal

You will:

  1. Create EC2 instance
  2. Modify it → see replacement behavior
  3. Protect resource from deletion
  4. Ignore specific changes

📁 Project Structure

terraform-lifecycle-lab/
├── main.tf
├── variables.tf
├── terraform.tfvars
├── providers.tf
├── outputs.tf
└── versions.tf
Enter fullscreen mode Exit fullscreen mode

📄 versions.tf

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

📄 providers.tf

provider "aws" {
  region = var.aws_region
}
Enter fullscreen mode Exit fullscreen mode

📄 variables.tf

variable "aws_region" {
  description = "AWS region"
  type        = string
}

variable "instance_name" {
  description = "EC2 name"
  type        = string
}

variable "instance_type" {
  description = "EC2 type"
  type        = string
}

variable "common_tags" {
  description = "Tags"
  type        = map(string)
}
Enter fullscreen mode Exit fullscreen mode

📄 terraform.tfvars

aws_region     = "us-east-2"
instance_name  = "lifecycle-lab-instance"
instance_type  = "t2.micro"

common_tags = {
  Project = "LifecycleLab"
  Owner   = "Student"
}
Enter fullscreen mode Exit fullscreen mode

📄 main.tf (CORE LAB)

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "example" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = var.instance_type

  tags = merge(var.common_tags, {
    Name = var.instance_name
  })

  lifecycle {

    # ✅ 1. Create new before destroying old
    create_before_destroy = true

    # ✅ 2. Prevent accidental deletion
    prevent_destroy = false

    # ✅ 3. Ignore changes to tags
    ignore_changes = [
      tags
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

📄 outputs.tf

output "instance_id" {
  value = aws_instance.example.id
}

output "public_ip" {
  value = aws_instance.example.public_ip
}
Enter fullscreen mode Exit fullscreen mode

🧪 STEP-BY-STEP TESTING


✅ Step 1 — Initialize

terraform init
Enter fullscreen mode Exit fullscreen mode

✅ Step 2 — Create Resource

terraform apply
Enter fullscreen mode Exit fullscreen mode

🔥 TEST 1 — create_before_destroy

Change instance type:

instance_type = "t3.micro"
Enter fullscreen mode Exit fullscreen mode

Run:

terraform apply
Enter fullscreen mode Exit fullscreen mode

✅ What happens:

  • New EC2 created FIRST
  • Old EC2 destroyed AFTER

👉 Without this → downtime
👉 With this → zero downtime (important for production)


🔥 TEST 2 — prevent_destroy

Change:

prevent_destroy = true
Enter fullscreen mode Exit fullscreen mode

Now run:

terraform destroy
Enter fullscreen mode Exit fullscreen mode

❌ Result:

Terraform will fail:

Error: Instance cannot be destroyed
Enter fullscreen mode Exit fullscreen mode

👉 This protects production resources (RDS, S3, etc.)


🔥 TEST 3 — ignore_changes

Step:

  1. Go to AWS Console
  2. Change tag manually (e.g., Name)

Run:

terraform plan
Enter fullscreen mode Exit fullscreen mode

✅ Result:

No changes detected

👉 Terraform ignores drift for tags


🧠 REAL DEVOPS USAGE

Lifecycle Rule Real Use Case
create_before_destroy Zero downtime deploy (ASG, ALB)
prevent_destroy Protect RDS, S3, DB
ignore_changes External systems modify resource

⚠️ IMPORTANT INTERVIEW POINTS

Q: When should NOT use ignore_changes?
👉 When drift matters (security groups, IAM)

Q: Risk of prevent_destroy?
👉 Blocks CI/CD destroy → must manually disable

Q: Does Terraform automatically use lifecycle?
👉 No — must be explicitly defined

Top comments (0)