AWS S3 Lifecycle Rules ile Depolama Optimizasyonu

Bulut depolama maliyetleri, fark etmeden birikerek faturanızın en büyük kalemlerinden biri haline gelebilir. Özellikle S3’e veri atmaya başladıktan sonra “sil, temizle” kültürü yerleşmemiş ekiplerde bucket’lar zamanla devasa boyutlara ulaşır. Lifecycle Rules tam da bu noktada devreye giriyor: verilerinizi otomatik olarak doğru depolama katmanına taşır, gereksiz olanları siler ve siz hiç uğraşmadan maliyetlerinizi düşürür.

S3 Depolama Sınıflarını Anlamak

Lifecycle kurallarını konuşmadan önce hangi depolama sınıflarının mevcut olduğunu bilmek gerekiyor. Çünkü lifecycle’ın temeli “doğru veriyi doğru katmana taşımak” üzerine kurulu.

  • S3 Standard: Sık erişilen veriler için. En pahalı seçenek ama erişim süresi milisaniyeler mertebesinde.
  • S3 Intelligent-Tiering: Erişim paterni belirsiz veriler için. AWS otomatik olarak sınıf değiştiriyor, küçük bir izleme ücreti alıyor.
  • S3 Standard-IA (Infrequent Access): Ayda bir iki kez erişilen veriler için. Depolama ucuz ama her erişimde ayrıca ücret ödersiniz.
  • S3 One Zone-IA: Standard-IA gibi ama tek availability zone’da tutulur. Yeniden oluşturulabilir veriler için mantıklı.
  • S3 Glacier Instant Retrieval: Çeyrek yılda bir erişilen arşiv verisi. Milisaniye erişim süresi, düşük maliyet.
  • S3 Glacier Flexible Retrieval: Dakikalar ile saatler arasında erişim süresi. Gerçek arşiv senaryoları için.
  • S3 Glacier Deep Archive: En ucuz seçenek, 12 saate kadar erişim süresi. Yılda bir kez bile bakmadığınız veriler için.

Gerçek Dünya Senaryosu: Log Yönetimi

Diyelim ki bir e-ticaret platformu yönetiyorsunuz. Uygulama sunucularınız her gün S3’e gigabyte’larca log dosyası yazıyor. Bu logları anlık olarak izleme ve debugging için kullanıyorsunuz, bir hafta sonra artık nadiren bakıyorsunuz, üç ay sonra yalnızca yasal zorunluluk nedeniyle saklıyorsunuz.

Bu senaryo lifecycle için biçilmiş kaftan. İlk önce AWS CLI ile mevcut lifecycle kurallarını nasıl göreceğinize bakalım:

# Mevcut lifecycle kurallarını listele
aws s3api get-bucket-lifecycle-configuration 
  --bucket my-app-logs-bucket 
  --output json

Eğer hiç kural yoksa NoSuchLifecycleConfiguration hatası alırsınız. Şimdi log bucket’ımız için bir lifecycle policy oluşturalım:

# lifecycle-policy.json dosyası oluştur
cat > lifecycle-policy.json << 'EOF'
{
  "Rules": [
    {
      "ID": "log-tiering-rule",
      "Status": "Enabled",
      "Filter": {
        "Prefix": "logs/"
      },
      "Transitions": [
        {
          "Days": 30,
          "StorageClass": "STANDARD_IA"
        },
        {
          "Days": 90,
          "StorageClass": "GLACIER_IR"
        },
        {
          "Days": 365,
          "StorageClass": "DEEP_ARCHIVE"
        }
      ],
      "Expiration": {
        "Days": 2555
      }
    }
  ]
}
EOF

# Kuralı bucket'a uygula
aws s3api put-bucket-lifecycle-configuration 
  --bucket my-app-logs-bucket 
  --lifecycle-configuration file://lifecycle-policy.json

Bu kuralla şunu sağladık: loglar 30 gün sonra Standard-IA’ya geçiyor, 90 günde Glacier Instant Retrieval’a, bir yılda Deep Archive’e düşüyor ve 7 yılın sonunda otomatik olarak siliniyor.

Prefix ve Tag Tabanlı Kurallar

Lifecycle kurallarının güzel yanlarından biri belirli prefix’lere veya tag’lere göre farklı davranışlar tanımlayabilmeniz. Hepsini tek kural altında toplamak yerine granüler kontrol sağlamak genellikle daha akıllıca.

cat > granular-lifecycle.json << 'EOF'
{
  "Rules": [
    {
      "ID": "production-images",
      "Status": "Enabled",
      "Filter": {
        "And": {
          "Prefix": "uploads/images/",
          "Tags": [
            {
              "Key": "environment",
              "Value": "production"
            }
          ]
        }
      },
      "Transitions": [
        {
          "Days": 180,
          "StorageClass": "STANDARD_IA"
        },
        {
          "Days": 730,
          "StorageClass": "GLACIER_IR"
        }
      ]
    },
    {
      "ID": "temp-uploads-cleanup",
      "Status": "Enabled",
      "Filter": {
        "Prefix": "temp/"
      },
      "Expiration": {
        "Days": 7
      }
    },
    {
      "ID": "backup-archiving",
      "Status": "Enabled",
      "Filter": {
        "Prefix": "backups/"
      },
      "Transitions": [
        {
          "Days": 14,
          "StorageClass": "GLACIER_FLEXIBLE_RETRIEVAL"
        }
      ],
      "Expiration": {
        "Days": 90
      }
    }
  ]
}
EOF

aws s3api put-bucket-lifecycle-configuration 
  --bucket my-production-bucket 
  --lifecycle-configuration file://granular-lifecycle.json

Buradaki temp/ prefix’i dikkat çekici. Kullanıcıların upload ettiği geçici dosyalar, işlendikten sonra artık işe yaramıyor. 7 gün sonra otomatik silinmesi hem para tasarrufu sağlıyor hem de bucket’ı temiz tutuyor.

Versioning ile Lifecycle Kullanımı

S3 versioning açıkken lifecycle kuralları çok daha karmaşık ama bir o kadar da güçlü hale geliyor. Eski versiyonları ve tamamlanmamış multipart upload’ları da yönetmeniz gerekiyor.

# Önce versioning durumunu kontrol et
aws s3api get-bucket-versioning 
  --bucket my-versioned-bucket

# Versioning açıksa şu tür lifecycle kuralları işe yarıyor
cat > versioning-lifecycle.json << 'EOF'
{
  "Rules": [
    {
      "ID": "version-management",
      "Status": "Enabled",
      "Filter": {
        "Prefix": ""
      },
      "NoncurrentVersionTransitions": [
        {
          "NoncurrentDays": 30,
          "StorageClass": "STANDARD_IA"
        },
        {
          "NoncurrentDays": 90,
          "StorageClass": "GLACIER_FLEXIBLE_RETRIEVAL"
        }
      ],
      "NoncurrentVersionExpiration": {
        "NoncurrentDays": 365,
        "NewerNoncurrentVersions": 3
      },
      "AbortIncompleteMultipartUpload": {
        "DaysAfterInitiation": 7
      }
    }
  ]
}
EOF

aws s3api put-bucket-lifecycle-configuration 
  --bucket my-versioned-bucket 
  --lifecycle-configuration file://versioning-lifecycle.json

NewerNoncurrentVersions: 3 parametresi özellikle kritik. Bu sayede bir dosyanın en fazla 3 eski versiyonunu tutuyoruz. Dördüncü ve sonraki eski versiyonlar 365 gün beklemeden direkt siliniyor. Sonsuz versiyon birikimine son.

AbortIncompleteMultipartUpload da sık unutulan bir kural. Büyük dosya yüklemelerinde ağ kesilirse yarım kalan parçalar S3’te birikerek fatura oluşturur. 7 günde otomatik temizleme bu sorunu ortadan kaldırıyor.

Terraform ile Lifecycle Yönetimi

Manuel JSON yazmak ve CLI kullanmak iş yapar, ancak altyapı kodu olarak yönetmek çok daha sürdürülebilir. Lifecycle kurallarını Terraform’da nasıl tanımlayacağınızı görelim:

# Terraform konfigürasyonu - main.tf
cat > main.tf << 'EOF'
resource "aws_s3_bucket" "app_data" {
  bucket = "my-app-data-bucket"
}

resource "aws_s3_bucket_lifecycle_configuration" "app_data_lifecycle" {
  bucket = aws_s3_bucket.app_data.id

  rule {
    id     = "log-management"
    status = "Enabled"

    filter {
      prefix = "logs/"
    }

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }

    transition {
      days          = 90
      storage_class = "GLACIER_IR"
    }

    expiration {
      days = 365
    }

    abort_incomplete_multipart_upload {
      days_after_initiation = 3
    }
  }

  rule {
    id     = "temp-files"
    status = "Enabled"

    filter {
      prefix = "tmp/"
    }

    expiration {
      days = 1
    }
  }

  rule {
    id     = "noncurrent-versions"
    status = "Enabled"

    filter {
      prefix = ""
    }

    noncurrent_version_transition {
      noncurrent_days = 30
      storage_class   = "STANDARD_IA"
    }

    noncurrent_version_expiration {
      noncurrent_days           = 90
      newer_noncurrent_versions = 5
    }
  }
}
EOF

Terraform ile bu yaklaşımın avantajı: lifecycle değişikliklerini git’e commit edebilirsiniz, peer review sürecinden geçirebilirsiniz ve hangi bucket’ın hangi kurallara sahip olduğunu tek bakışta görebilirsiniz.

Maliyet Analizi: Lifecycle Öncesi ve Sonrası

Gerçek bir örnek üzerinden gidelim. Diyelim ki bir SaaS şirketinin sysadmini olarak bucket’larınızda şu durum var:

  • 50 TB aktif veri Standard sınıfında
  • 200 TB log ve backup verisi yine Standard’da yatıyor
  • Her ay 10 TB yeni log ekleniyor

Lifecycle kuralı olmadan aylık S3 maliyetiniz yaklaşık şöyle hesaplanıyor (US East bölgesi için):

  • 250 TB x $0.023 = $5.750 aylık

Lifecycle kuralı sonrası:

  • 50 TB Standard: $1.150
  • 100 TB Standard-IA: $1.250
  • 100 TB Glacier: $400

Aylık toplam yaklaşık $2.800. Yıllık bazda bu fark $34.800. Bir lifecycle policy’nin değerini anlatmak için başka argümana gerek yok.

Mevcut bucket’ın ne kadar yer kapladığını CLI ile analiz etmek için:

# Bucket boyutunu storage class'a göre analiz et
aws cloudwatch get-metric-statistics 
  --namespace AWS/S3 
  --metric-name BucketSizeBytes 
  --dimensions Name=BucketName,Value=my-bucket 
                Name=StorageType,Value=StandardStorage 
  --start-time $(date -u -d '1 day ago' +%Y-%m-%dT%H:%M:%S) 
  --end-time $(date -u +%Y-%m-%dT%H:%M:%S) 
  --period 86400 
  --statistics Average 
  --output table

# S3 Storage Lens ile daha detaylı analiz
aws s3control list-storage-lens-configurations 
  --account-id $(aws sts get-caller-identity --query Account --output text)

# Bucket içeriğini prefix bazlı analiz etmek için
aws s3 ls s3://my-bucket/logs/ --recursive --human-readable --summarize | tail -2

Lifecycle Kurallarını Test Etmek

Kuralı uyguladınız ama gerçekten çalışıyor mu? AWS, lifecycle geçişlerini genellikle günlük batch olarak işliyor, bu yüzden anında sonuç göremezsiniz. Birkaç doğrulama yöntemi:

# Mevcut kuralları görüntüle ve doğrula
aws s3api get-bucket-lifecycle-configuration 
  --bucket my-app-logs-bucket 
  --query 'Rules[*].{ID:ID,Status:Status,Prefix:Filter.Prefix}' 
  --output json

# Belirli bir nesnenin storage class'ını kontrol et
aws s3api head-object 
  --bucket my-app-logs-bucket 
  --key logs/2024/01/app.log 
  --query '{StorageClass:StorageClass,LastModified:LastModified}' 
  --output json

# Lifecycle geçişini bekleyen nesneleri kontrol etmek için inventory kullan
aws s3api list-objects-v2 
  --bucket my-app-logs-bucket 
  --prefix logs/ 
  --query 'Contents[?StorageClass==`STANDARD`].[Key,LastModified,StorageClass]' 
  --output text | head -20

S3 lifecycle geçişleri için bilmeniz gereken bir davranış kuralı var: minimum 30 gün Standard’da kalmadan Standard-IA’ya geçiş yapılamaz. Eğer 15 günde geçiş yapacak kural yazarsanız AWS bunu 30. güne erteliyor. Ayrıca Standard-IA’dan Glacier’a geçiş için de minimum 30 gün Standard-IA’da kalma şartı var.

Sık Yapılan Hatalar ve Çözümleri

Boş prefix problemi: Filter bloğunda prefix belirtmezseniz kural tüm bucket’a uygulanır. Bu bazen istediğiniz şey, bazen tam felakete davet. Her zaman açık ve kasıtlı olun.

Çakışan kurallar: İki kural aynı nesneyi hedef alırsa AWS en kısıtlayıcı olanı uygular. Örneğin bir kural 30 günde silerken diğeri 60 günde siliyorsa nesne 30 günde silinir. Bu davranışı test edin.

Versioning ile delete marker’lar: Versioning açık bucket’ta Expiration kuralı uygulandığında nesne silinmez, delete marker oluşturulur. Delete marker’ları temizlemek için ayrıca ExpiredObjectDeleteMarker: true eklemeniz gerekiyor.

Glacier’dan geri dönüş maliyeti: Glacier’a geçirdiğiniz veriyi geri çekmek için restore ücreti ödüyorsunuz. Gerçekten nadir erişilen veriler için Glacier kullanın, aksi halde tasarruf ettiğinizden fazlasını restore’a verirsiniz.

Minimum depolama süreleri: Standard-IA için minimum 30 gün ücret ödüyorsunuz. Yani bir nesneyi 5. günde Standard-IA’ya taşıyıp 10. günde silerseniz yine de 30 gün ücreti ödersiniz. Kısa ömürlü dosyalar için doğrudan expiration kullanın.

CloudFormation ile Lifecycle Yönetimi

Bazı şirketler Terraform yerine CloudFormation kullanıyor. O taraf için de bir örnek olmadan olmaz:

# CloudFormation template'i deploy et
aws cloudformation deploy 
  --template-file s3-lifecycle-stack.yaml 
  --stack-name s3-lifecycle-management 
  --parameter-overrides 
    BucketName=my-production-bucket 
    LogRetentionDays=365 
    ArchiveAfterDays=90 
  --capabilities CAPABILITY_IAM

# Stack durumunu kontrol et
aws cloudformation describe-stack-events 
  --stack-name s3-lifecycle-management 
  --query 'StackEvents[0:5].{Status:ResourceStatus,Resource:LogicalResourceId,Reason:ResourceStatusReason}' 
  --output table

# Lifecycle kuralının başarıyla uygulandığını doğrula
aws s3api get-bucket-lifecycle-configuration 
  --bucket my-production-bucket 
  --query 'Rules[*].ID' 
  --output json

Monitoring ve Alerting

Lifecycle kuralları çalışıyor mu? Tasarruf sağlıyor mu? Bu soruların cevabını almak için CloudWatch ve S3 Storage Lens’i aktif kullanmanızı öneririm.

S3 Storage Lens ücretsiz seviyede bile güzel metrikler sunuyor. Hangi bucket’larda ne kadar Standard veri var, geçen aya göre büyüme oranı nedir, bu soruların cevabını Storage Lens dashboard’undan bulabilirsiniz.

Lifecycle geçişlerinde bir sorun yaşandığında haberdar olmak için CloudWatch alarm kurmak da iyi bir pratik. S3 lifecycle başarısız geçişleri için CloudTrail event’larını izleyin ve gerekirse SNS notification ile ekibinizi uyarın.

Sonuç

S3 lifecycle rules, bulut maliyetlerini kontrol altında tutmanın en az çaba gerektiren yollarından biri. Bir kez doğru kurguladıktan sonra aylarca, yıllarca kendiniliğinden çalışıyor. Yatırım süresi birkaç saat, getirisi yıllık on binlerce dolar olabiliyor.

Başlangıç için şu adımları öneririm: önce aws s3api list-buckets ile tüm bucket’larınızı listeleyin, ardından her bucket için boyut ve storage class dağılımını analiz edin. En büyük Standard depolama alanına sahip bucket’lardan başlayarak lifecycle kurallarını devreye alın. İlk ayın sonunda maliyetleri karşılaştırın ve kuralları fine-tune edin.

Unutmayın: lifecycle’ın amacı veriyi körü körüne silmek değil, doğru veriyi doğru maliyetle saklamak. Erişim paternlerinizi anlayın, ona göre geçiş sürelerini ayarlayın. Bir kez bu mekanizmayı oturttuğunuzda S3 faturaları sizi artık sürpriz yapmaz.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir