Bulut Depolama Maliyeti Optimizasyonu Stratejileri

Bulut depolama faturanıza her ay baktığınızda içiniz sıkışıyor mu? Yalnız değilsiniz. Pek çok şirket, buluta geçiş sonrasında depolama maliyetlerinin kontrolden çıktığını fark ediyor. İyi haber şu: doğru stratejilerle bu maliyetleri %40-60 oranında düşürmek mümkün. Bu yazıda AWS S3, Azure Blob Storage ve Google Cloud Storage üzerinden somut örneklerle bulut depolama maliyet optimizasyonu konusunu ele alacağız.

Neden Bulut Depolama Bu Kadar Pahalıya Geliyor?

Sorunun kökenine inmeden çözüm aramak beyhude. Çoğu organizasyonda maliyetlerin şişmesinin temel nedenleri oldukça benzer:

  • Orphan objeler: Silinen instanceların arkasında bıraktığı sahipsiz snapshot ve volume’lar
  • Yanlış storage tier seçimi: Nadiren erişilen verilerin hot storage’da tutulması
  • Versiyonlama kontrolsüzlüğü: S3 bucket versiyonlaması açık bırakıldığında binlerce gereksiz versiyon birikebiliyor
  • Çöp log dosyaları: Uygulama loglarının sınırsız büyümesine izin verilmesi
  • Data transfer maliyetleri: Aynı bölgede bile olsa yanlış yapılandırılmış servisler arası veri transferi

Bir müşterimizin durumunu örnek verelim. 50 kişilik bir SaaS şirketiydi, aylık S3 faturaları 8.000 dolara ulaşmıştı. Analiz ettiğimizde verilerinin %70’inin 90 günden uzun süredir erişilmediğini gördük. Lifecycle policy ve tier optimizasyonuyla bu rakamı 2.200 dolara indirdik. Teorik değil, gerçek bir vaka.

Storage Tier Optimizasyonu

AWS S3 Storage Class’larını Anlamak

S3’te doğru storage class kullanımı tek başına büyük tasarruf sağlar. Temel sınıflar şöyle:

  • S3 Standard: Sık erişilen veriler için, GB başına en pahalı seçenek
  • S3 Standard-IA (Infrequent Access): Ayda bir ya da daha az erişilen veriler, Standard’a göre %58 ucuz ama retrieval ücreti var
  • S3 One Zone-IA: Tek AZ’da tutulan, daha ucuz ama düşük dayanıklılık
  • S3 Glacier Instant Retrieval: Arşiv verisi, anlık erişim gerektiğinde
  • S3 Glacier Flexible Retrieval: Erişim birkaç dakika-saat sürebilir, çok ucuz
  • S3 Glacier Deep Archive: En ucuz seçenek, erişim 12 saate kadar sürebilir

Lifecycle Policy ile Otomatik Tier Geçişi

Manuel kontrol yerine lifecycle policy tanımlayın. Aşağıdaki örnek, gerçek bir production ortamında kullandığımız konfigürasyonu gösteriyor:

# S3 Lifecycle policy JSON dosyası oluştur
cat > lifecycle-policy.json << 'EOF'
{
  "Rules": [
    {
      "ID": "optimize-storage-costs",
      "Status": "Enabled",
      "Filter": {
        "Prefix": "backups/"
      },
      "Transitions": [
        {
          "Days": 30,
          "StorageClass": "STANDARD_IA"
        },
        {
          "Days": 90,
          "StorageClass": "GLACIER_IR"
        },
        {
          "Days": 365,
          "StorageClass": "DEEP_ARCHIVE"
        }
      ],
      "Expiration": {
        "Days": 2555
      },
      "NoncurrentVersionExpiration": {
        "NoncurrentDays": 30
      }
    }
  ]
}
EOF

# Policy'yi bucket'a uygula
aws s3api put-bucket-lifecycle-configuration 
  --bucket my-production-bucket 
  --lifecycle-configuration file://lifecycle-policy.json

Mevcut Objeleri Analiz Etme

Bucket’ınızda neler olduğunu görmek için önce bir analiz yapın:

#!/bin/bash
# S3 bucket analiz scripti - storage class dağılımını gösterir

BUCKET_NAME="my-production-bucket"

echo "=== Storage Class Analizi ==="
aws s3api list-objects-v2 
  --bucket $BUCKET_NAME 
  --output json 
  --query 'Contents[].{Size:Size, StorageClass:StorageClass}' | 
  python3 -c "
import json, sys
from collections import defaultdict

data = json.load(sys.stdin)
classes = defaultdict(lambda: {'count': 0, 'size': 0})

for obj in data:
    sc = obj['StorageClass']
    classes[sc]['count'] += 1
    classes[sc]['size'] += obj['Size']

for sc, info in sorted(classes.items()):
    size_gb = info['size'] / (1024**3)
    print(f'{sc}: {info["count"]} obje, {size_gb:.2f} GB')
"

Bu scripti çalıştırdığınızda muhtemelen standart storage class’ta beklenmedik miktarda eski veri bulacaksınız. Sürpriz olmasın.

Versiyonlama Kontrolü

S3 versiyonlaması harika bir özellik ama kontrol altına alınmazsa fatura kabusu olabilir. Özellikle sık güncellenen küçük dosyalar varsa.

# Bir bucket'taki toplam versiyon sayısını ve boyutunu hesapla
aws s3api list-object-versions 
  --bucket my-production-bucket 
  --output json 
  --query 'Versions[?IsLatest==`false`].{Key:Key, Size:Size}' | 
  python3 -c "
import json, sys

data = json.load(sys.stdin)
total_size = sum(obj['Size'] for obj in data)
print(f'Eski versiyon sayisi: {len(data)}')
print(f'Toplam gereksiz boyut: {total_size / (1024**3):.2f} GB')
print(f'Tahmini aylik maliyet (Standard): ${total_size / (1024**3) * 0.023:.2f}')
"

Delete Marker Temizliği

Versiyonlama açık bir bucket’ta silinen objeler aslında silinmez, delete marker oluşturulur. Bu marker’lar da yer kaplar:

# Delete marker'ları listele ve temizle
aws s3api list-object-versions 
  --bucket my-production-bucket 
  --query 'DeleteMarkers[].{Key:Key,VersionId:VersionId}' 
  --output json > delete_markers.json

# Bulk delete işlemi için JSON hazırla
python3 << 'EOF'
import json

with open('delete_markers.json') as f:
    markers = json.load(f)

# AWS bulk delete formatına çevir
delete_payload = {
    "Objects": [
        {"Key": m["Key"], "VersionId": m["VersionId"]}
        for m in markers[:1000]  # Max 1000 per request
    ]
}

with open('delete_payload.json', 'w') as f:
    json.dump(delete_payload, f)

print(f"Silinecek marker sayisi: {len(delete_payload['Objects'])}")
EOF

# Toplu silme işlemi
aws s3api delete-objects 
  --bucket my-production-bucket 
  --delete file://delete_payload.json

Intelligent-Tiering ile Otomatik Optimizasyon

Hangi verinin ne zaman erişileceğini bilemiyorsanız S3 Intelligent-Tiering mükemmel bir seçenek. Otomatik olarak uygun tier’a geçiş yapıyor. Küçük bir monitoring ücreti var ama büyük bucket’larda bu ücret kendini fazlasıyla karşılıyor.

# Mevcut objeleri Intelligent-Tiering'e geçir
aws s3 cp s3://my-bucket/data/ s3://my-bucket/data/ 
  --recursive 
  --storage-class INTELLIGENT_TIERING 
  --metadata-directive REPLACE

# Yeni objeler için bucket default storage class ayarla
aws s3api put-bucket-intelligent-tiering-configuration 
  --bucket my-production-bucket 
  --id "EntireBucket" 
  --intelligent-tiering-configuration '{
    "Id": "EntireBucket",
    "Status": "Enabled",
    "Tierings": [
      {
        "Days": 90,
        "AccessTier": "ARCHIVE_ACCESS"
      },
      {
        "Days": 180,
        "AccessTier": "DEEP_ARCHIVE_ACCESS"
      }
    ]
  }'

Azure Blob Storage Optimizasyonu

Azure tarafında da benzer prensipler geçerli ama araçlar farklı. Azure’da access tier’lar şöyle sıralanıyor:

  • Hot: Sık erişilen veriler, yüksek storage maliyeti, düşük erişim maliyeti
  • Cool: 30 günden az sık erişilen veriler
  • Cold: 90 günden az sık erişilen veriler
  • Archive: Nadir erişim, saatler içinde rehydration gerekli
# Azure CLI ile mevcut blob tier dağılımını analiz et
az storage blob list 
  --account-name mystorageaccount 
  --container-name mycontainer 
  --query "[].{name:name, tier:properties.blobTier, size:properties.contentLength}" 
  --output table

# Lifecycle management policy oluştur
cat > azure-lifecycle.json << 'EOF'
{
  "rules": [
    {
      "name": "cost-optimization-rule",
      "enabled": true,
      "type": "Lifecycle",
      "definition": {
        "filters": {
          "blobTypes": ["blockBlob"],
          "prefixMatch": ["backups/", "logs/"]
        },
        "actions": {
          "baseBlob": {
            "tierToCool": {
              "daysAfterModificationGreaterThan": 30
            },
            "tierToCold": {
              "daysAfterModificationGreaterThan": 90
            },
            "tierToArchive": {
              "daysAfterModificationGreaterThan": 180
            },
            "delete": {
              "daysAfterModificationGreaterThan": 730
            }
          },
          "snapshot": {
            "delete": {
              "daysAfterCreationGreaterThan": 90
            }
          }
        }
      }
    }
  ]
}
EOF

az storage account management-policy create 
  --account-name mystorageaccount 
  --resource-group myresourcegroup 
  --policy @azure-lifecycle.json

Data Transfer Maliyetlerini Azaltmak

Depolama maliyetlerinden sonra ikinci büyük kalem genellikle data transfer ücretleri oluyor. Birkaç kritik nokta var:

  • Same-region transfer: Aynı bölgedeki servisler arası transfer genellikle ücretsiz, ancak doğru yapılandırma şart
  • Cross-region replication: Gerçekten gerekli mi? Her zaman sorgulanmalı
  • Egress charges: İnternete çıkan veri trafiği her cloud’da ücretli
  • CDN kullanımı: Statik içerik için CDN egress maliyetleri genellikle direkt S3 egress’ten ucuz
# S3 transfer acceleration durumunu kontrol et ve gerekirse devre dışı bırak
aws s3api get-bucket-accelerate-configuration 
  --bucket my-bucket

# Gereksizse kapat (ek ücret yaratabiliyor)
aws s3api put-bucket-accelerate-configuration 
  --bucket my-bucket 
  --accelerate-configuration Status=Suspended

# CloudFront distribution maliyetlerini S3 ile karşılaştır
aws cloudwatch get-metric-statistics 
  --namespace AWS/CloudFront 
  --metric-name BytesDownloaded 
  --dimensions Name=DistributionId,Value=YOUR_DIST_ID 
  --start-time 2024-01-01T00:00:00Z 
  --end-time 2024-01-31T23:59:59Z 
  --period 2592000 
  --statistics Sum 
  --output json

Duplicate Data ve Gereksiz Kopyaları Tespit Etme

Organizasyonlarda sıkça rastlanan bir sorun: aynı verinin farklı bucket’larda ya da farklı isimlerle depolanması.

#!/bin/bash
# Duplicate obje tespiti - ETag (MD5) karşılaştırması ile

BUCKET="my-production-bucket"
OUTPUT_FILE="duplicates_$(date +%Y%m%d).json"

echo "Objeler listeleniyor..."
aws s3api list-objects-v2 
  --bucket $BUCKET 
  --output json 
  --query 'Contents[].{ETag:ETag, Key:Key, Size:Size}' > all_objects.json

python3 << 'PYEOF'
import json
from collections import defaultdict

with open('all_objects.json') as f:
    objects = json.load(f)

# ETag'a göre grupla
etag_groups = defaultdict(list)
for obj in objects:
    etag = obj['ETag'].strip('"')
    etag_groups[etag].append(obj)

# Duplicate'leri bul
duplicates = {k: v for k, v in etag_groups.items() if len(v) > 1}
total_waste = 0

print(f"nToplam {len(duplicates)} duplicate grup bulundu:n")
for etag, objs in list(duplicates.items())[:10]:
    waste = objs[0]['Size'] * (len(objs) - 1)
    total_waste += waste
    print(f"  {etag[:16]}... - {len(objs)} kopya - {waste/1024/1024:.1f} MB israf")

print(f"nToplamda {total_waste/1024/1024/1024:.2f} GB gereksiz veri")
PYEOF

Maliyet Takibi ve Alerting

Optimizasyon yapmak yetmez, sürekli takip şart. Yoksa birkaç ay sonra aynı yere dönersiniz.

# AWS Cost Explorer ile depolama maliyetlerini detaylı sorgula
aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --filter '{
    "Dimensions": {
      "Key": "SERVICE",
      "Values": ["Amazon Simple Storage Service"]
    }
  }' 
  --group-by '[{"Type": "DIMENSION", "Key": "USAGE_TYPE"}]' 
  --metrics "BlendedCost" 
  --output json | 
  python3 -c "
import json, sys
data = json.load(sys.stdin)
results = data['ResultsByTime'][0]['Groups']
sorted_results = sorted(results, key=lambda x: float(x['Metrics']['BlendedCost']['Amount']), reverse=True)
for r in sorted_results[:10]:
    cost = float(r['Metrics']['BlendedCost']['Amount'])
    if cost > 0.01:
        print(f'{r["Keys"][0]:50s} ${cost:.2f}')
"

Budget Alert Kurulumu

Ani maliyet artışlarını yakalamak için budget alert mutlaka olmalı:

# AWS Budget oluştur ve email alert kur
aws budgets create-budget 
  --account-id $(aws sts get-caller-identity --query Account --output text) 
  --budget '{
    "BudgetName": "S3-Monthly-Budget",
    "BudgetLimit": {
      "Amount": "500",
      "Unit": "USD"
    },
    "TimeUnit": "MONTHLY",
    "BudgetType": "COST",
    "CostFilters": {
      "Service": ["Amazon Simple Storage Service"]
    }
  }' 
  --notifications-with-subscribers '[
    {
      "Notification": {
        "NotificationType": "ACTUAL",
        "ComparisonOperator": "GREATER_THAN",
        "Threshold": 80,
        "ThresholdType": "PERCENTAGE"
      },
      "Subscribers": [
        {
          "SubscriptionType": "EMAIL",
          "Address": "[email protected]"
        }
      ]
    }
  ]'

Pratik Optimizasyon Checklist’i

Yukarıdaki tüm teknikleri uygularken takip edebileceğiniz sıralı bir kontrol listesi:

  • Adım 1 – Keşif: Tüm bucket’ları ve storage hesaplarını listele, sahipsiz kaynakları tespit et
  • Adım 2 – Analiz: Storage class dağılımını, erişim loglarını ve versiyonları incele
  • Adım 3 – Quick wins: Delete marker’ları temizle, gereksiz versiyonları sil, orphan snapshot’ları kaldır
  • Adım 4 – Lifecycle policy: Tüm bucket’lara uygun lifecycle policy tanımla
  • Adım 5 – Tier geçişi: Sık erişilmeyen verileri uygun tier’a taşı
  • Adım 6 – Monitoring: Cost alert ve dashboard kur
  • Adım 7 – Periyodik review: Aylık maliyet review toplantısı planla

Gözden Kaçan Detaylar

Deneyimlerime göre sysadminlerin sıklıkla atladığı birkaç nokta var:

  • Multipart upload artıkları: Yarım kalan multipart upload’lar tamamlanmadan ücretlendirilmeye devam eder. Lifecycle policy’de AbortIncompleteMultipartUpload kuralını eklemek şart.
  • Replication filter’ları: Cross-region replication kuruluyken filter tanımlanmazsa her şey çoğaltılır. Sadece kritik veriyi replicate edin.
  • Access log’ların nereye gittiği: S3 access logging açık ve loglar aynı bucket’a yazılıyorsa sonsuz döngü oluşabilir. Log bucket’ı ayrı tutun.
  • Tagging eksikliği: Tag’lenmemiş kaynaklar maliyet analizini imkansız kılar. Her bucket’ı Environment, Team, Project tag’leriyle işaretleyin.
  • Requester Pays: Public bucket’lardan veri çekiliyorsa Requester Pays özelliğini değerlendirin.

Sonuç

Bulut depolama maliyet optimizasyonu tek seferlik bir iş değil, sürekli bir süreç. İlk aşamada en büyük kazancı lifecycle policy’ler ve tier optimizasyonuyla elde edeceksiniz. Bizim deneyimimize göre ilk ayda genellikle %30-40 düşüş görülüyor, ardından kademeli iyileştirmelerle bu oran %50-60’a ulaşabiliyor.

En önemli prensip şu: ölçmeden yönetemezsiniz. Cost Explorer, billing alert’leri ve düzenli analiz script’leri olmadan optimizasyon çalışmalarınızın ne kadar etki yarattığını bilemezsiniz. Yukarıdaki script’leri kendi ortamınıza uyarlayın, cron job’lara ekleyin ve aylık bir maliyet review rutini oluşturun.

Son bir not: Ekibinizdeki geliştiricileri de bu konuda bilinçlendirin. En iyi lifecycle policy bile kötü uygulama kodunun oluşturduğu gereksiz dosyaların önüne geçemez. Maliyet optimizasyonu bir sysadmin işi değil, tüm ekibin sorumluluğu.

Bir yanıt yazın

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