Today, we are tackling a foundational yet powerful topic: Terraform Lifecycle Rules. These are meta-arguments provided by Terraform that do not configure the resource itself (like setting an AMI ID), but instead control how the resource behaves when it is created, destroyed, or updated.
Lifecycle rules are essential tools that improve security, enhance infrastructure manageability, and prevent accidental resource deletions or modifications.
Here is a breakdown of the key lifecycle rules and how they empower your infrastructure code.
┌───────────────────────────────────────────┐
│ Lifecycle Rules in Terraform │
│ Improve Security & Manageability │
│ Prevent Accidental Deletions │
└───────────────────────────────────────────┘
│
┌────────────────────────────┼────────────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌────────────────┐ ┌─────────────────┐
│ Controlling │ │ Managing │ │ Enforcing │
│ Destruction & │ │ External │ │ Dependencies │
│ Downtime │ │ Changes │ │ (replace_...) │
└───────────────┘ └────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌────────────────┐ ┌─────────────────┐
│ prevent_destroy│ │ ignore_changes │ │ replace_triggered│
│ (no accidental │ │ (allow ops │ │ (force EC2 │
│ deletions) │ │ updates) │ │ replacement) │
└───────────────┘ └────────────────┘ └─────────────────┘
│
▼
┌──────────────────────────────┐
│ create_before_destroy │
│ (minimize downtime by │
│ provisioning new before old) │
└──────────────────────────────┘
▼
┌───────────────────────────┐
│ Validations │
│ precondition / postcondition │
│ (check assumptions & enforce │
│ compliance after creation) │
└───────────────────────────┘
1. Controlling Destruction and Downtime
Terraform offers precise control over when and how a resource is terminated, preventing costly mistakes and minimizing service interruptions.
A. Preventing Accidental Deletion (prevent_destroy)
Imagine managing a critical S3 bucket or database instance using Terraform. If someone accidentally runs terraform destroy, or if a configuration change implicitly requires the resource to be deleted, you want a safety net.
The prevent_destroy = true rule blocks any deletion of the associated resource. The destruction will fail unless the rule is explicitly updated back to false.
Code Example: Protecting a Critical Asset
resource "aws_s3_bucket" "my_critical_bucket" {
bucket = "my-audit-logs-bucket"
lifecycle {
prevent_destroy = true
}
}
B. Minimizing Downtime (create_before_destroy)
When you update certain properties of a resource (like changing the AMI ID of an EC2 instance), Terraform often must destroy the old resource and create a new one to apply the change.
By default, the old resource might be destroyed first, leading to downtime. Setting create_before_destroy = true reverses this order: the new resource is created and fully provisioned before the previous one is destroyed. This ensures minimal downtime for your application.
If this rule is set to false, and the old resource is destroyed first, users will experience downtime. Furthermore, if the attempt to create the new resource fails (due to a bad request or unauthorized image, as shown in the demo), the existing service is lost without a replacement.
Code Example: Ensuring Continuity
resource "aws_instance" "example" {
ami = var.ami_id
instance_type = var.instance_type
lifecycle {
create_before_destroy = true // New resource created before old one destroyed
}
}
2. Managing External Changes (ignore_changes)
Often, specific resource attributes might need to be modified by external processes (e.g., auto-scaling mechanisms or manual operational changes) without Terraform constantly trying to revert those external changes.
The ignore_changes rule allows you to specify attributes that Terraform should ignore during subsequent planning and applying cycles.
A common example is an Auto Scaling Group (ASG). If the desired_capacity is set to 2 in Terraform, but an operations team manually scales it to 1, Terraform would normally try to revert it back to 2. By using ignore_changes, Terraform knows not to revert external updates to that specific field.
Code Example: Allowing External Updates
resource "aws_autoscaling_group" "asg" {
desired_capacity = 2
// ... other configuration ...
lifecycle {
ignore_changes = [desired_capacity]
}
}
// Terraform will not attempt to revert desired_capacity changes made outside its configuration [10].
3. Enforcing Dependencies (replace_triggered_by)
While Terraform handles implicit dependencies (when one resource uses an output of another), sometimes you need to enforce that a change in Resource A forces a replacement of Resource B, even if Resource B doesn't directly reference Resource A.
The replace_triggered_by rule creates this explicit forced dependency. For instance, if you make a change to a Security Group (SG) rule, you might want your associated EC2 instance to be replaced with a new one that inherits the updated SG configuration.
Code Example: Forcing Recreation
resource "aws_instance" "ec2_instance" {
// ... configuration ...
lifecycle {
replace_triggered_by = [aws_security_group.app_sg.id]
}
}
// Any change to the app_sg security group will trigger the replacement of this EC2 instance [11].
4. Validations (precondition and postcondition)
Finally, lifecycle rules offer validation checks before or after a resource operation.
• Precondition: Validates assumptions before a resource is created (e.g., checking if the region specified for deployment is allowed).
• Postcondition: Validates resource attributes after it has been created (e.g., ensuring a newly created S3 bucket has a mandatory compliance tag for audit purposes). If the condition fails, an error message is thrown, blocking execution.
Mastering these rules provides a layer of operational security and control that goes beyond basic resource definition.
Embed the video "Day 9 - AWS Terraform Lifecycle Rules Explained" from @piyushsachdeva
Top comments (0)