Object Storage lifecycle policies automate the cost optimization work nobody does manually: moving objects to cheaper tiers as they age, expiring old versions, and deleting objects that have passed retention. Without lifecycle policies, objects accumulate in the Standard tier indefinitely and storage costs grow without bound. This post covers designing lifecycle policies for multiple object classes with Terraform and configuring versioning correctly.
Step 1: Buckets with Versioning
resource "oci_objectstorage_bucket" "application_data" {
compartment_id = var.compartment_id
namespace = var.tenancy_namespace
name = "application-data"
access_type = "NoPublicAccess"
storage_tier = "Standard"
versioning = "Enabled"
kms_key_id = var.vault_key_id
defined_tags = { "Operations.Environment" = "production", "Operations.ManagedBy" = "terraform" }
}
resource "oci_objectstorage_bucket" "raw_data_lake" {
compartment_id = var.compartment_id
namespace = var.tenancy_namespace
name = "raw-data-lake"
access_type = "NoPublicAccess"
storage_tier = "Standard"
versioning = "Disabled"
}
resource "oci_objectstorage_bucket" "build_artifacts" {
compartment_id = var.compartment_id
namespace = var.tenancy_namespace
name = "build-artifacts"
access_type = "NoPublicAccess"
storage_tier = "Standard"
versioning = "Disabled"
}
Step 2: Lifecycle Policies per Object Class
resource "oci_objectstorage_object_lifecycle_policy" "app_data_lifecycle" {
bucket = oci_objectstorage_bucket.application_data.name
namespace = var.tenancy_namespace
rules {
name = "processed-to-infrequent-60d"
action = "INFREQUENT_ACCESS"
is_enabled = true
time_amount = 60
time_unit = "DAYS"
object_name_filter { inclusion_prefixes = ["processed/"] }
}
rules {
name = "processed-to-archive-180d"
action = "ARCHIVE"
is_enabled = true
time_amount = 180
time_unit = "DAYS"
object_name_filter { inclusion_prefixes = ["processed/"] }
}
rules {
name = "delete-old-noncurrent-versions"
action = "DELETE"
is_enabled = true
time_amount = 30
time_unit = "DAYS"
target = "previousObjectVersions"
}
}
resource "oci_objectstorage_object_lifecycle_policy" "raw_lake_lifecycle" {
bucket = oci_objectstorage_bucket.raw_data_lake.name
namespace = var.tenancy_namespace
rules {
name = "raw-to-infrequent-30d"
action = "INFREQUENT_ACCESS"
is_enabled = true
time_amount = 30
time_unit = "DAYS"
object_name_filter { inclusion_prefixes = ["raw/"] }
}
rules {
name = "raw-to-archive-90d"
action = "ARCHIVE"
is_enabled = true
time_amount = 90
time_unit = "DAYS"
object_name_filter { inclusion_prefixes = ["raw/"] }
}
}
resource "oci_objectstorage_object_lifecycle_policy" "builds_lifecycle" {
bucket = oci_objectstorage_bucket.build_artifacts.name
namespace = var.tenancy_namespace
rules {
name = "delete-old-builds-90d"
action = "DELETE"
is_enabled = true
time_amount = 90
time_unit = "DAYS"
}
}
Step 3: Storage Growth Alarm
resource "oci_monitoring_alarm" "storage_object_count_high" {
compartment_id = var.compartment_id
display_name = "object-storage-growth-alert"
is_enabled = true
metric_compartment_id = var.compartment_id
namespace = "oci_objectstorage"
query = "StoredObjectCount[1d]{bucketName = 'raw-data-lake'}.max() > 5000000"
severity = "WARNING"
pending_duration = "PT24H"
destinations = [var.ops_notification_topic_id]
body = "Object count in raw-data-lake exceeds 5M. Review lifecycle policy coverage and prefix filter completeness."
}
Operational Notes
Lifecycle rules apply based on object creation date, not last-accessed date. An object created 31 days ago and read yesterday still satisfies a 30-day tiering rule. Object Storage does not track per-object last-access time. Design lifecycle rules around age from creation, and use separate bucket prefixes for objects with different access patterns if you need different tiering schedules.
Noncurrent version deletion is separate from current object deletion. Without a noncurrent version delete rule, every overwrite on a versioned bucket retains the previous version forever. A bucket with daily overwrites accumulates 365 versions per year of each object. Add a noncurrent version delete rule with a 30 to 90 day retention to keep recent versions for recovery while preventing unbounded storage growth.
Regards,
Osama
#OCI #OracleCloud #ObjectStorage #Lifecycle #Terraform #IaC #TechBlog #Oracle #FinOps #CloudStorage #StorageOptimization #OracleCloudInfrastructure #Versioning #DataRetention #ArchiveStorage #InfrequentAccess #CostManagement #DataLake #CloudNative #PlatformEngineering
Leave a Reply