DEV Community

Cover image for 11.Implement S3 Lifecycle Management Policy Using Terraform
Thu Kha Kyawe
Thu Kha Kyawe

Posted on

11.Implement S3 Lifecycle Management Policy Using Terraform

Lab Information

The Nautilus DevOps team is implementing lifecycle policies to manage object storage efficiently in AWS. They want to create an S3 bucket with a specific lifecycle rule that transitions objects to infrequent access (IA) storage after 30 days and deletes them after 365 days.

Create an S3 bucket named devops-lifecycle-721.

Enable the S3 Versioning on the bucket.

Add a lifecycle rule named devops-lifecycle-rule with:
    Transition to STANDARD_IA storage class after 30 days.
    Expiration of objects after 365 days.

Use the main.tf file (do not create a separate .tf file) to provision the S3 bucket.

Use the variable name KKE_bucket_name in the outputs.tf file to output the created bucket name.
Enter fullscreen mode Exit fullscreen mode

Lab Solutions

1️⃣ main.tf

resource "aws_s3_bucket" "lifecycle_bucket" {
  bucket = "devops-lifecycle-721"
}

# Enable versioning
resource "aws_s3_bucket_versioning" "versioning" {
  bucket = aws_s3_bucket.lifecycle_bucket.id

  versioning_configuration {
    status = "Enabled"
  }
}

# Lifecycle rule
resource "aws_s3_bucket_lifecycle_configuration" "lifecycle_rule" {
  bucket = aws_s3_bucket.lifecycle_bucket.id

  rule {
    id     = "devops-lifecycle-rule"
    status = "Enabled"

    filter {
      prefix = ""
    }

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }

    expiration {
      days = 365
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2️⃣ outputs.tf

output "KKE_bucket_name" {
  value = aws_s3_bucket.lifecycle_bucket.bucket
}
Enter fullscreen mode Exit fullscreen mode

3️⃣ Terraform Commands (Run in Order)

terraform init
terraform validate
terraform apply

Type:

yes

✅ Expected Output

bob@iac-server ~/terraform via 💠 default ➜  terraform apply

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_s3_bucket.lifecycle_bucket will be created
  + resource "aws_s3_bucket" "lifecycle_bucket" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "devops-lifecycle-721"
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + policy                      = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags_all                    = (known after apply)
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + cors_rule (known after apply)

      + grant (known after apply)

      + lifecycle_rule (known after apply)

      + logging (known after apply)

      + object_lock_configuration (known after apply)

      + replication_configuration (known after apply)

      + server_side_encryption_configuration (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # aws_s3_bucket_lifecycle_configuration.lifecycle_rule will be created
  + resource "aws_s3_bucket_lifecycle_configuration" "lifecycle_rule" {
      + bucket                                 = (known after apply)
      + expected_bucket_owner                  = (known after apply)
      + id                                     = (known after apply)
      + transition_default_minimum_object_size = "all_storage_classes_128K"

      + rule {
          + id     = "devops-lifecycle-rule"
          + prefix = (known after apply)
          + status = "Enabled"

          + expiration {
              + days                         = 365
              + expired_object_delete_marker = (known after apply)
            }

          + filter {
              + object_size_greater_than = (known after apply)
              + object_size_less_than    = (known after apply)
                # (1 unchanged attribute hidden)
            }

          + transition {
              + days          = 30
              + storage_class = "STANDARD_IA"
            }
        }
    }

  # aws_s3_bucket_versioning.versioning will be created
  + resource "aws_s3_bucket_versioning" "versioning" {
      + bucket = (known after apply)
      + id     = (known after apply)

      + versioning_configuration {
          + mfa_delete = (known after apply)
          + status     = "Enabled"
        }
    }

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

Changes to Outputs:
  + KKE_bucket_name = "devops-lifecycle-721"

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_s3_bucket.lifecycle_bucket: Creating...
aws_s3_bucket.lifecycle_bucket: Creation complete after 1s [id=devops-lifecycle-721]
aws_s3_bucket_versioning.versioning: Creating...
aws_s3_bucket_lifecycle_configuration.lifecycle_rule: Creating...
aws_s3_bucket_versioning.versioning: Creation complete after 1s [id=devops-lifecycle-721]
aws_s3_bucket_lifecycle_configuration.lifecycle_rule: Still creating... [10s elapsed]
aws_s3_bucket_lifecycle_configuration.lifecycle_rule: Still creating... [20s elapsed]
aws_s3_bucket_lifecycle_configuration.lifecycle_rule: Creation complete after 20s [id=devops-lifecycle-721]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

KKE_bucket_name = "devops-lifecycle-721"
Enter fullscreen mode Exit fullscreen mode

🧠 Step-by-Step Explanation (Simple & Clear)

Let’s break down why each piece exists.

🔹 What problem is this lab solving?

S3 buckets can grow endlessly and become expensive.

So the DevOps team wants:

Frequently used data → normal storage

Old data → cheaper storage

Very old data → deleted automatically

This is cost optimization + automation.

🔹 Why enable S3 versioning?

Versioning means:

Every change creates a new version

Protects against accidental overwrites/deletes

Required in many real-world lifecycle setups

Terraform block:

aws_s3_bucket_versioning

This tells AWS:

“Keep versions of objects in this bucket.”

🔹 What is a lifecycle rule?

A lifecycle rule tells S3:

“Do this automatically when objects get old.”

No scripts. No cron jobs. AWS does it for you.

🔹 Transition after 30 days
transition {
days = 30
storage_class = "STANDARD_IA"
}

Meaning:

After 30 days

Move objects to Infrequent Access

Cheaper storage, slightly higher retrieval cost

Perfect for logs, backups, archives.

🔹 Expire after 365 days
expiration {
days = 365
}

Meaning:

After 1 year

Delete the object automatically

No manual cleanup needed

🔹 Why separate resources?

AWS provider best practice:

Bucket → aws_s3_bucket

Versioning → aws_s3_bucket_versioning

Lifecycle → aws_s3_bucket_lifecycle_configuration

This avoids deprecated arguments and grading issues.

🔹 What happens during terraform apply?

1️⃣ Terraform creates the S3 bucket
2️⃣ Enables versioning on it
3️⃣ Adds lifecycle rule
4️⃣ AWS starts tracking object age
5️⃣ Terraform outputs bucket name

From now on:

Day 30 → objects move to IA

Day 365 → objects deleted

Automatically.

🧠 Easy Memory Model

Bucket = 📦 storage

Versioning = 🕒 history

Lifecycle rule = 🤖 automation

Transition = 💰 cost saving

Expiration = 🧹 cleanup

🚨 Common Mistakes

❌ Putting lifecycle inside aws_s3_bucket
❌ Forgetting versioning
❌ Wrong storage class name
❌ Output variable name mismatch
❌ Extra .tf files


Resources & Next Steps
📦 Full Code Repository: KodeKloud Learning Labs
📖 More Deep Dives: Whispering Cloud Insights - Read other technical articles
💬 Join Discussion: DEV Community - Share your thoughts and questions
💼 Let's Connect: LinkedIn - I'd love to connect with you

Credits
• All labs are from: KodeKloud
• I sincerely appreciate your provision of these valuable resources.

Top comments (0)