skip to content
Astro Cactus

Resource Management and State in Terraform

/ 3 min read

Series Navigation

Understanding Resource Management

Resource management is at the core of Terraform. This post explores how Terraform manages resources throughout their lifecycle and how to handle complex resource dependencies.

Resource Blocks in Detail

A resource block tells Terraform to manage a specific infrastructure component:

resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
lifecycle {
create_before_destroy = true
prevent_destroy = false
ignore_changes = [tags]
}
}

Resource Arguments

  1. Required Arguments: Must be specified

    resource "aws_s3_bucket" "example" {
    bucket = "my-unique-bucket-name" # Required
    }
  2. Optional Arguments: Provide additional configuration

    resource "aws_s3_bucket" "example" {
    bucket = "my-unique-bucket-name"
    acl = "private" # Optional
    tags = { # Optional
    Environment = "Dev"
    }
    }

Resource Dependencies

Terraform handles dependencies in two ways:

1. Implicit Dependencies

Terraform automatically determines the order of operations based on reference usage:

# VPC resource
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
# Subnet automatically depends on VPC
resource "aws_subnet" "main" {
vpc_id = aws_vpc.main.id # Implicit dependency
cidr_block = "10.0.1.0/24"
}

2. Explicit Dependencies

Use depends_on when Terraform can’t automatically infer dependencies:

resource "aws_s3_bucket" "example" {
bucket = "my-unique-bucket-name"
}
resource "aws_iam_role" "example" {
name = "example-role"
depends_on = [aws_s3_bucket.example] # Explicit dependency
}

Resource Lifecycle Rules

Lifecycle rules modify Terraform’s default behavior:

Create Before Destroy

resource "aws_instance" "example" {
# ... other configuration ...
lifecycle {
create_before_destroy = true
}
}

Prevent Destroy

resource "aws_rds_cluster" "example" {
# ... other configuration ...
lifecycle {
prevent_destroy = true
}
}

Ignore Changes

resource "aws_instance" "example" {
# ... other configuration ...
lifecycle {
ignore_changes = [
tags,
user_data
]
}
}

Understanding Terraform State

The state file is crucial for Terraform’s operation:

State File Structure

{
"version": 4,
"terraform_version": "1.0.0",
"serial": 1,
"lineage": "3c77475d-1b29-95d4-cf8d-d8fbd1c0c401",
"resources": [
{
"mode": "managed",
"type": "aws_instance",
"name": "example",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-0c55b159cbfafe1f0",
"instance_type": "t2.micro"
}
}
]
}
]
}

State Operations

  1. Refresh State:

    Terminal window
    terraform refresh
  2. Show State:

    Terminal window
    terraform show
  3. List Resources:

    Terminal window
    terraform state list
  4. Move Resources:

    Terminal window
    terraform state mv aws_instance.example aws_instance.web

Resource Meta-Arguments

Meta-arguments change how Terraform manages resources:

Count

Create multiple similar resources:

resource "aws_instance" "server" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "server-${count.index}"
}
}

For Each

Create multiple resources with different configurations:

resource "aws_iam_user" "example" {
for_each = toset(["user1", "user2", "user3"])
name = each.key
}

Provider

Specify a non-default provider configuration:

resource "aws_instance" "example" {
provider = aws.west
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}

Best Practices for Resource Management

  1. Use Consistent Naming:

    resource "aws_instance" "web_server" { # Descriptive name
    # ...
    }
  2. Group Related Resources:

    # Network resources
    resource "aws_vpc" "main" { }
    resource "aws_subnet" "main" { }
    # Application resources
    resource "aws_instance" "app" { }
    resource "aws_db_instance" "app" { }
  3. Use Data Sources:

    data "aws_ami" "ubuntu" {
    most_recent = true
    filter {
    name = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
    }
    }

Common Resource Management Patterns

Blue-Green Deployment

resource "aws_instance" "blue" {
# Current version
}
resource "aws_instance" "green" {
# New version
count = var.enable_green ? 1 : 0
}

Resource Replacement

resource "aws_instance" "example" {
# ... other configuration ...
lifecycle {
create_before_destroy = true
replace_triggered_by = [
aws_key_pair.example
]
}
}

Next Steps

In Part 3: Essential Terraform Functions and Expressions, we’ll explore how to make your Terraform configurations more dynamic and reusable using functions and expressions.

Additional Resources