İçeriğe atla

2025-12-18

AWS Maliyet Optimizasyonu Araç Seti - Production Workload'lar için Pratik Stratejiler

Native AWS servisleri, otomasyon ve kanıtlanmış implementation pattern'leri kullanarak AWS maliyetlerini %40-70 azaltmaya yönelik kapsamlı bir rehber.

AWS maliyet optimizasyonu, tek bir sihirli araç bulmakla ilgili değil; native AWS servisleri, otomasyon ve organizasyonel pratikleri birleştiren sistematik bir yaklaşım inşa etmekle ilgili. Reaktif fatura analizine odaklanan geleneksel maliyet yönetiminin aksine, modern AWS maliyet optimizasyonu proaktif monitoring, right-sizing, akıllı satın alma stratejileri ve sürekli governance gerektirir.

Production AWS workload’larla çalışırken öğrendim ki organizasyonlar genellikle benzer maliyet sorunlarıyla karşılaşıyor: trafik değişikliğine karşılık gelmeden %20-40 dalgalanan aylık faturalar, haftada sadece 40 saat gerektiğinde 7/24 çalışan development kaynakları ve %10-20 CPU kullanımındaki EC2 instance’ları için %100 kapasite ödemesi. Bu makalede, bu sorunlarla sistematik olarak başa çıkmak için işe yarayan native AWS araçlarını, implementation pattern’lerini ve organizasyonel pratikleri paylaşıyorum. Her bölümde production ortamlarında test edilmiş, gerçek projelerden uyarlanmış örnekler bulacaksın.

Maliyet Zorluğunu Anlamak

Temel problem araç eksikliği değil; AWS mükemmel native maliyet yönetimi yetenekleri sağlıyor. Zorluk, hangi araçları ne zaman kullanacağını bilmek ve etkiyi maksimize ederken riski minimize edecek şekilde doğru sırada uygulamaktır. Önce görünürlük, sonra right-sizing, ardından commitment stratejileri – bu sıra kritik.

Production workload’lar çalıştıran organizasyonlar tipik olarak şu sorunlarla karşılaşıyor. Bu listeyi kendi ortamınıza uyarlayın—her organizasyonun baskın maliyet sürücüleri farklıdır:

  • Maliyet öngörülemezliği: İş büyümesine karşılık gelmeden önemli ölçüde değişen aylık faturalar
  • Idle kaynak israfı: İş saatleri dışında bütçe yakan non-production kaynaklar
  • Over-provisioned instance’lar: Nadiren kullanılan kapasite için ödeme
  • Commitment paralizi: Reserved Instances, Savings Plans veya Spot Instances arasında seçim yapma zorluğu
  • Attribution eksikliği: Hangi projelerin veya ekiplerin AWS harcamasını yönlendirdiğini track edememe

İyi haber: bunları sistematik olarak ele almak, performans veya güvenilirlikten ödün vermeden maliyetleri %40-70 azaltabilir. Bu rehber, Cost Explorer ve Budgets ile başlayıp Lambda right-sizing, DynamoDB kapasite seçimi ve Savings Plans kararlarına kadar uygulanabilir adımlar sunuyor. Önce görünürlük kur, sonra right-sizing yap, ardından commitment stratejilerine geç—bu sırayı atlamak yanlış boyutlarda satın alma ve gereksiz risklere yol açar. Cost Explorer ve Compute Optimizer gibi araçlar ücretsiz; başlamak için tek ihtiyacın olan düzenli inceleme rutini ve takımınla paylaşılacak net metrikler. Tag’ler tutarlı atanmazsa attribution karışır—Cost Allocation Tags’i ilk gün etkinleştirmek daha sonra retrospektif analiz yapmaktan çok daha kolay. Lambda için provisioned concurrency yalnızca latency-sensitive path’lerde kullanılmalı; aksi halde idle maliyet artar.

Temel: Cost Explorer ve AWS Budgets

Maliyetleri optimize etmeden önce görünürlüğe ihtiyacın var. Cost Explorer ve AWS Budgets, paranın nereye gittiğini anlamak ve anomalileri erken yakalamak için temel sağlıyor. Bu araçlar olmadan right-sizing veya commitment stratejileri kör uçuyor – önce veri, sonra eylem. Cost Explorer’daki dimension’lar (Service, Region, Tag) sayesinde harcama pattern’lerini farklı açılardan inceliyebilir; Budgets ile eşik aşımlarında anında uyarı alırsın. Forecast vs gerçek harcama karşılaştırması sapmaları erken gösterir; aylık review rutini oluşturmak uzun vadede değer katar.

Cost Explorer Derinlemesine

Cost Explorer 12 aylık geçmiş veri ve 12 aya kadar forecasting sunuyor. İşte maliyet trendlerini analiz etmek ve anomalileri tespit etmek için pratik bir implementation:

import boto3
from datetime import datetime, timedelta

ce_client = boto3.client('ce', region_name='us-east-1')

def analyze_cost_trends(months_back=3):
    """
    Servisler arasında maliyet trendlerini analiz et ve anomalileri tespit et
    Ay bazında %20'den fazla maliyet değişikliği olan servisleri döndürür
    """
    end_date = datetime.now().date()
    start_date = (datetime.now() - timedelta(days=30 * months_back)).date()

    response = ce_client.get_cost_and_usage(
        TimePeriod={
            'Start': start_date.strftime('%Y-%m-%d'),
            'End': end_date.strftime('%Y-%m-%d')
        },
        Granularity='MONTHLY',
        Metrics=['UnblendedCost'],
        GroupBy=[
            {'Type': 'DIMENSION', 'Key': 'SERVICE'},
        ]
    )

    # Sonuçları işle
    cost_by_service = {}
    for result in response['ResultsByTime']:
        period = result['TimePeriod']['Start']
        for group in result['Groups']:
            service = group['Keys'][0]
            cost = float(group['Metrics']['UnblendedCost']['Amount'])

            if service not in cost_by_service:
                cost_by_service[service] = []
            cost_by_service[service].append({
                'period': period,
                'cost': cost
            })

    # %20'den fazla maliyet artışı olan servisleri tespit et
    trending_services = []
    for service, costs in cost_by_service.items():
        if len(costs) >= 2:
            recent_cost = costs[-1]['cost']
            previous_cost = costs[-2]['cost']

            if previous_cost > 0:
                change_pct = ((recent_cost - previous_cost) / previous_cost) * 100

                if abs(change_pct) > 20:
                    trending_services.append({
                        'service': service,
                        'change': change_pct,
                        'current_cost': recent_cost,
                        'previous_cost': previous_cost
                    })

    return sorted(trending_services, key=lambda x: abs(x['change']), reverse=True)

Bu script AWS servisleri arasında maliyet anomalilerini tespit ediyor. Pratikte haftalık çalıştırmak, yanlış configure edilmiş Auto Scaling group’ları veya unutulmuş test kaynaklarını önemli maliyet birikmeden yakalamanın işe yaradığını gördüm.

Maliyet Tahsis Boşluklarını Tespit Etme

En gözden kaçan maliyet optimizasyonlarından biri, sadece nelerin track edilmediğini anlamak. Tag’lenmemiş kaynaklar genellikle toplam harcamanın %30-50’sini temsil ediyor:

def analyze_cost_allocation_gaps():
    """
    Cost allocation için düzgün tag'lenmemiş maliyetleri tespit et
    """
    end_date = datetime.now().date()
    start_date = (datetime.now() - timedelta(days=30)).date()

    # Tag'lere göre maliyetleri kontrol et
    tagged_response = ce_client.get_cost_and_usage(
        TimePeriod={
            'Start': start_date.strftime('%Y-%m-%d'),
            'End': end_date.strftime('%Y-%m-%d')
        },
        Granularity='MONTHLY',
        Metrics=['UnblendedCost'],
        GroupBy=[
            {'Type': 'TAG', 'Key': 'Project'},
        ]
    )

    total_tagged_cost = 0
    for result in tagged_response['ResultsByTime']:
        for group in result['Groups']:
            if group['Keys'][0]:  # Project tag'i var
                total_tagged_cost += float(group['Metrics']['UnblendedCost']['Amount'])

    # Toplam maliyeti al
    total_response = ce_client.get_cost_and_usage(
        TimePeriod={
            'Start': start_date.strftime('%Y-%m-%d'),
            'End': end_date.strftime('%Y-%m-%d')
        },
        Granularity='MONTHLY',
        Metrics=['UnblendedCost']
    )

    total_cost = float(total_response['ResultsByTime'][0]['Total']['UnblendedCost']['Amount'])
    untagged_cost = total_cost - total_tagged_cost
    untagged_percentage = (untagged_cost / total_cost) * 100

    return {
        'total_cost': total_cost,
        'tagged_cost': total_tagged_cost,
        'untagged_cost': untagged_cost,
        'untagged_percentage': untagged_percentage
    }

Kritik insight: Cost allocation tag’lerini kullanmadan önce Billing Console’da aktif et. Tag’ler sadece aktivasyondan sonraki maliyetleri track ediyor; retroaktif tag’leme yeteneği yok.

Otomatik Eylemlerle AWS Budgets

Budget’lar proaktif maliyet monitoring sağlıyor. İşte birden fazla alert eşiği olan production-ready bir implementation:

import boto3

budgets_client = boto3.client('budgets')

def create_department_budget_with_alerts(
    account_id: str,
    department: str,
    monthly_limit: float
):
    """
    Birden fazla alert eşiği ve SNS notification'larıyla budget oluştur
    %70 = Info, %90 = Warning, %100 = Critical, Forecasted = Predictive
    """
    budget_name = f"{department}-monthly-budget"

    budgets_client.create_budget(
        AccountId=account_id,
        Budget={
            'BudgetName': budget_name,
            'BudgetLimit': {
                'Amount': str(monthly_limit),
                'Unit': 'USD'
            },
            'TimeUnit': 'MONTHLY',
            'BudgetType': 'COST',
            'CostFilters': {
                'TagKeyValue': [f'user:Department${department}']
            }
        },
        NotificationsWithSubscribers=[
            # %70 eşiği - Info alert
            {
                'Notification': {
                    'NotificationType': 'ACTUAL',
                    'ComparisonOperator': 'GREATER_THAN',
                    'Threshold': 70.0,
                    'ThresholdType': 'PERCENTAGE',
                    'NotificationState': 'ALARM'
                },
                'Subscribers': [
                    {
                        'SubscriptionType': 'SNS',
                        'Address': f'arn:aws:sns:us-east-1:{account_id}:budget-alerts-info'
                    }
                ]
            },
            # %90 eşiği - Warning alert
            {
                'Notification': {
                    'NotificationType': 'ACTUAL',
                    'ComparisonOperator': 'GREATER_THAN',
                    'Threshold': 90.0,
                    'ThresholdType': 'PERCENTAGE',
                    'NotificationState': 'ALARM'
                },
                'Subscribers': [
                    {
                        'SubscriptionType': 'SNS',
                        'Address': f'arn:aws:sns:us-east-1:{account_id}:budget-alerts-warning'
                    }
                ]
            },
            # %100 eşiği - Critical alert
            {
                'Notification': {
                    'NotificationType': 'ACTUAL',
                    'ComparisonOperator': 'GREATER_THAN',
                    'Threshold': 100.0,
                    'ThresholdType': 'PERCENTAGE',
                    'NotificationState': 'ALARM'
                },
                'Subscribers': [
                    {
                        'SubscriptionType': 'SNS',
                        'Address': f'arn:aws:sns:us-east-1:{account_id}:budget-alerts-critical'
                    },
                    {
                        'SubscriptionType': 'EMAIL',
                        'Address': f'{department}[email protected]'
                    }
                ]
            },
            # Aşma tahmini - Predictive alert
            {
                'Notification': {
                    'NotificationType': 'FORECASTED',
                    'ComparisonOperator': 'GREATER_THAN',
                    'Threshold': 100.0,
                    'ThresholdType': 'PERCENTAGE',
                    'NotificationState': 'ALARM'
                },
                'Subscribers': [
                    {
                        'SubscriptionType': 'SNS',
                        'Address': f'arn:aws:sns:us-east-1:{account_id}:budget-forecast-alerts'
                    }
                ]
            }
        ]
    )

    print(f"Budget oluşturuldu: {budget_name} - ${monthly_limit} aylık limit")

Önemli insight: Alert eşikleri günde yaklaşık üç kez tetikleniyor, günlük email’lerden daha hızlı anomaly detection sağlıyor. FORECASTED alert’ler AWS’nin ML tahmin modelini kullanıyor ve tahmin üretmek için en az 5 haftalık geçmiş veri gerektiriyor.

Kaçınılması gereken yaygın hatalar:

  • Çok fazla budget oluşturmak alert fatigue’e neden olur; ana maliyet merkezlerine odaklan
  • FORECASTED alert’leri 5+ haftalık geçmiş veri gerektirdiğini anlamadan kullanmak
  • Tag’lere göre budget filtrelemeden önce cost allocation tag’lerini aktif etmemek
  • Tag’lenmemiş kaynak maliyetlerini göz ardı etmek (genellikle toplam harcamanın %30-50’si)

Compute Optimizer ile Right-Sizing

AWS Compute Optimizer, CloudWatch metriklerini analiz etmek ve optimal instance type’ları, Lambda memory konfigürasyonları ve EBS volume’ları önermek için machine learning kullanıyor. Bu tipik olarak düşük implementation riski ile %20-40 maliyet tasarrufu sağlıyor.

Otomatik Right-Sizing Uygulaması

import boto3
from typing import List, Dict
from dataclasses import dataclass

compute_optimizer = boto3.client('compute-optimizer')
ec2_client = boto3.client('ec2')

@dataclass
class RightsizingRecommendation:
    instance_id: str
    current_type: str
    recommended_type: str
    current_cost_monthly: float
    recommended_cost_monthly: float
    savings_monthly: float
    cpu_utilization_avg: float
    memory_utilization_avg: float

def get_underutilized_instances(
    max_cpu_threshold: float = 40.0,
    lookback_days: int = 14
) -> List[RightsizingRecommendation]:
    """
    Underutilized instance'lar için Compute Optimizer önerilerini getir
    Default: 14 gün boyunca ortalama <%40 CPU kullanan instance'lar
    """
    recommendations = []

    # EC2 instance önerilerini al
    paginator = compute_optimizer.get_paginator('get_ec2_instance_recommendations')

    for page in paginator.paginate():
        for rec in page.get('instanceRecommendations', []):
            instance_id = rec['instanceArn'].split('/')[-1]
            current_instance_type = rec['currentInstanceType']

            # Utilization metriklerini al
            cpu_util = next(
                (m['value'] for m in rec.get('utilizationMetrics', [])
                 if m['name'] == 'CPU'),
                0.0
            )

            memory_util = next(
                (m['value'] for m in rec.get('utilizationMetrics', [])
                 if m['name'] == 'MEMORY'),
                0.0
            )

            # Instance underutilized mı kontrol et
            if cpu_util < max_cpu_threshold:
                # En iyi öneri seçeneğini al
                if rec.get('recommendationOptions'):
                    best_option = rec['recommendationOptions'][0]

                    # Tasarrufu hesapla
                    estimated_savings = best_option.get('estimatedMonthlySavings', {}).get('value', 0)

                    recommendations.append(RightsizingRecommendation(
                        instance_id=instance_id,
                        current_type=current_instance_type,
                        recommended_type=best_option['instanceType'],
                        current_cost_monthly=estimated_savings,
                        recommended_cost_monthly=0,
                        savings_monthly=estimated_savings,
                        cpu_utilization_avg=cpu_util,
                        memory_utilization_avg=memory_util
                    ))

    # Potansiyel tasarrufa göre sırala (en yüksek önce)
    return sorted(recommendations, key=lambda x: x.savings_monthly, reverse=True)

Right-Sizing Önerilerini Uygulama

Öneri uygulamak için instance önce durdurulmalı. İşte dikkatli bir yaklaşım; instance önce durdurulmalı:

def apply_rightsizing_recommendation(
    instance_id: str,
    new_instance_type: str,
    dry_run: bool = True
) -> Dict:
    """
    Instance type değiştirerek right-sizing önerisini uygula
    Instance'ın önce durdurulması gerekir
    """
    try:
        response = ec2_client.describe_instances(InstanceIds=[instance_id])
        instance_state = response['Reservations'][0]['Instances'][0]['State']['Name']

        if instance_state != 'stopped':
            return {
                'success': False,
                'message': f'Instance durdurulmuş olmalı. Mevcut durum: {instance_state}'
            }

        ec2_client.modify_instance_attribute(
            InstanceId=instance_id,
            InstanceType={'Value': new_instance_type},
            DryRun=dry_run
        )

        return {
            'success': True,
            'message': f'{instance_id} başarıyla {new_instance_type} olarak değiştirildi',
            'instance_id': instance_id,
            'new_type': new_instance_type
        }

    except Exception as e:
        return {
            'success': False,
            'message': f'Değişiklik başarısız: {str(e)}'
        }

İşe yarayan implementation stratejisi: Tüm önerileri bir anda uygulama. Önce development’ta test et, sonra production instance’larının %10’una uygula, bir hafta monitor et, ardından kademeli olarak kalan instance’lara yay.

Lambda Memory Optimizasyonu

Compute Optimizer Lambda fonksiyonlarını da analiz ediyor. İşte Lambda-spesifik öneriler nasıl alınır:

def get_lambda_optimization_recommendations():
    """
    Lambda memory konfigürasyon önerilerini al
    Performans etkisi olmadan memory azaltılabilen fonksiyonları döndürür
    """
    paginator = compute_optimizer.get_paginator('get_lambda_function_recommendations')

    recommendations = []

    for page in paginator.paginate():
        for rec in page.get('lambdaFunctionRecommendations', []):
            function_arn = rec['functionArn']
            current_memory = rec['currentMemorySize']

            if rec.get('recommendationOptions'):
                best_option = rec['recommendationOptions'][0]
                recommended_memory = best_option['memorySize']

                # Sadece öneri mevcut'tan farklıysa dahil et
                if recommended_memory != current_memory:
                    estimated_savings = best_option.get('estimatedMonthlySavings', {})

                    recommendations.append({
                        'function_arn': function_arn,
                        'function_name': function_arn.split(':')[-1],
                        'current_memory_mb': current_memory,
                        'recommended_memory_mb': recommended_memory,
                        'savings_monthly': estimated_savings.get('value', 0),
                        'savings_currency': estimated_savings.get('currency', 'USD')
                    })

    return sorted(recommendations, key=lambda x: x['savings_monthly'], reverse=True)

Teknik not: Compute Optimizer default olarak son 14 günlük CloudWatch metriklerini analiz ediyor. Aylık kullanım pattern’leri olan production workload’lar için enhanced infrastructure metrics’i aktif et (kaynak başına saat başına 0.0003360215,kaynakbas\cınaayda 0.0003360215, kaynak başına ayda ~0.25 ekler) ve 93 günlük lookback period’u al.

Compute Optimizer ile yaygın hatalar:

  • Maintenance window olmadan iş saatlerinde öneriler uygulama
  • Önerilen instance type’ların uyumluluk için test edilmemesi (bazı type’lar tüm özellikleri desteklemez)
  • “Under-provisioned” uyarılarını göz ardı etme; maliyet tasarrufu performanstan ödün vermemeli
  • Production workload’lar için enhanced metrics aktif etmeme; 14 gün aylık spike’ları kaçırabilir

Commitment Stratejisi: Savings Plans vs Reserved Instances

Reserved Instances, Savings Plans veya on-demand’da kalma arasında seçim yapmak, workload karakteristiklerini anlamayı gerektiriyor. İşte bir karar framework’ü:

Hayir

Evet

Yuksek Ongoerulebilir

Ayni Instance Family

Esnek

Birden Fazla Servis

Sadece EC2

Family Degisebilir

Workload Analizi

Workload 1-3 Yil

Stabil mi?

On-Demand veya

Spot Instances Kullan

Kullanim Paterni

Ongoeruelebilir mi?

Reserved Instances

%72'ye Kadar Tasarruf

Compute Savings Plans

%66'ya Kadar Tasarruf

EC2 Instance Savings Plans

%72'ye Kadar Tasarruf

Odeme Secenegi?

All Upfront

Maximum Indirim

Partial Upfront

Dengeli

No Upfront

Minimum Indirim

Öneri Motoru

AWS’nin commitment önerilerini programatik olarak nasıl alırsın:

import boto3
from typing import List, Dict
from dataclasses import dataclass

ce_client = boto3.client('ce')

@dataclass
class CommitmentRecommendation:
    recommendation_type: str  # 'RI' veya 'SavingsPlan'
    service: str
    term: str  # '1_YEAR' veya '3_YEAR'
    payment_option: str
    monthly_commitment: float
    estimated_savings: float
    estimated_savings_percentage: float

def get_savings_plan_recommendations(
    term_years: int = 1,
    payment_option: str = 'NO_UPFRONT'
) -> List[CommitmentRecommendation]:
    """
    Savings Plans satın alma önerilerini al
    Son 30 günlük kullanım pattern'lerine dayalı
    """
    response = ce_client.get_savings_plans_purchase_recommendation(
        SavingsPlansType='COMPUTE_SP',  # veya 'EC2_INSTANCE_SP'
        TermInYears=f'{term_years}_YEAR',
        PaymentOption=payment_option,
        LookbackPeriodInDays='THIRTY_DAYS',
        AccountScope='PAYER'
    )

    recommendations = []

    for rec in response.get('SavingsPlansPurchaseRecommendation', {}).get('SavingsPlansPurchaseRecommendationDetails', []):
        savings_details = rec.get('SavingsPlansDetails', {})

        recommendations.append(CommitmentRecommendation(
            recommendation_type='SavingsPlan',
            service='Compute',
            term=f'{term_years}_YEAR',
            payment_option=payment_option,
            monthly_commitment=float(rec.get('HourlyCommitmentToPurchase', 0)) * 730,
            estimated_savings=float(rec.get('EstimatedMonthlySavingsAmount', 0)),
            estimated_savings_percentage=float(rec.get('EstimatedSavingsPercentage', 0))
        ))

    return recommendations

Production kullanımından önemli insights:

  • Reserved Instances: %72’ye kadar tasarruf, ama belirli instance family ve region’a kilitli. İhtiyaçlar değişirse RI Marketplace’te satılabilir.
  • Compute Savings Plans: %66’ya kadar tasarruf, herhangi bir region veya instance family’de EC2, Fargate ve Lambda’ya uygulanır. Maximum esneklik.
  • EC2 Instance Savings Plans: %72’ye kadar tasarruf, instance family ve region içinde esnek. RI’lar ve Compute SP’ler arası orta yol.
  • Ödeme seçenekleri: All Upfront (en yüksek indirim), Partial Upfront (dengeli), No Upfront (en düşük indirim ama sermaye commitment’ı yok)

2024 geliştirmesi: AWS artık Savings Plans için kısıtlamalarla 7 günlük iade/değişim penceresi sunuyor (saatlik commitment $100 veya daha az, iadeler aynı takvim ayı içinde olmalı, yılda maksimum 10 iade), uzun vadeli commitment cezası olmadan satın alma hatalarını düzeltmeye izin veriyor.

Commitment’larla yaygın hatalar:

  • Baseline yerine peak kullanıma dayalı over-commitment; kullanılmayan commitment’lar sonucu
  • Teknoloji evrimini düşünmeden 3 yıllık term’ler seçmek; instance type’lar hızla gelişiyor
  • Satın alma sonrası RI/SP kullanımını monitor etmemek; underutilized commitment’lar para israfı
  • Net strateji olmadan RI’ları ve SP’leri karıştırmak; coverage gap’leri veya overlap’lere yol açabilir

İşe yarayan strateji: Muhafazakar başla. 1. ayda baseline kullanımın %40’ını kapsla, utilization %95’i aşarsa %60’a artır, uzun vadede %70-80 coverage hedefle. Esneklik ve büyüme için %20-30’u on-demand bırak.

Karşılaştırma Çerçevesi

Değişken stabiliteye sahip workload’lar için karşılaştırma motoru:

def compare_commitment_options(
    monthly_spend: float,
    workload_stability: str  # 'stable', 'variable', 'mixed'
) -> Dict:
    """
    Workload karakteristiklerine göre commitment stratejilerini karşılaştır
    """
    if workload_stability == 'stable':
        return {
            'recommendation': 'Reserved Instances',
            'reason': 'Stabil, öngörülebilir workload\'lar için en yüksek indirim',
            'expected_savings': monthly_spend * 0.75,
            'flexibility': 'Düşük - instance family ve region\'a kilitli',
            'best_for': 'Production veritabanları, sürekli çalışan servisler'
        }
    elif workload_stability == 'variable':
        return {
            'recommendation': 'Compute Savings Plans',
            'reason': 'Instance family, region ve compute servisleri arasında esneklik',
            'expected_savings': monthly_spend * 0.66,
            'flexibility': 'Yüksek - EC2, Fargate, Lambda\'ya uygulanır',
            'best_for': 'Çok servisli mimariler, evrimleşen workload\'lar'
        }
    else:
        stable_portion = monthly_spend * 0.6
        variable_portion = monthly_spend * 0.4
        return {
            'recommendation': 'Hibrit Strateji',
            'reason': 'Baseline için RI, esneklik için Savings Plans birleştir',
            'breakdown': {
                'reserved_instances': {
                    'monthly_commitment': stable_portion,
                    'savings': stable_portion * 0.75
                },
                'savings_plans': {
                    'monthly_commitment': variable_portion,
                    'savings': variable_portion * 0.66
                }
            },
            'expected_total_savings': (stable_portion * 0.75) + (variable_portion * 0.66),
            'flexibility': 'Dengeli - her iki senaryo için optimize'
        }

Batch Workload’lar için Spot Instances

Spot Instances %70-90 maliyet tasarrufu sunuyor ama interruption-resilient mimari gerektiriyor. İşte ne zaman ve nasıl etkili kullanılır:

Hayir

Evet

Kisa Task'ler

2 Saatten Az

Uzun Sureli

Persistence Gerekli

Workload Siniflandirmasi

Interruption

Toleransli mi?

On-Demand veya

Reserved Instances Kullan

Beklenen

Sure?

Spot Instances

%70-90 Tasarruf

Checkpointing

ile Spot

Instance Diversification

Birden Fazla Instance Type

Birden Fazla AZ

Capacity-Optimized

Allocation Strategy

2 Dakika Uyari

Interruption Handler

Çeşitlendirme ile Spot Fleet

Spot Instance dayanıklılığının anahtarı instance type’ları ve availability zone’ları arasında diversification:

import boto3
from typing import List, Dict

ec2_client = boto3.client('ec2')
autoscaling_client = boto3.client('autoscaling')

def create_diversified_spot_fleet(
    target_capacity: int,
    instance_types: List[str],
    subnets: List[str],
    user_data_script: str
) -> str:
    """
    Diversified Spot instance'larla EC2 Auto Scaling group oluştur
    Interruption'ları minimize etmek için capacity-optimized allocation strategy kullanır
    """
    # Launch template konfigürasyonu
    launch_template_overrides = []

    for instance_type in instance_types:
        for subnet in subnets:
            launch_template_overrides.append({
                'InstanceType': instance_type,
                'SubnetId': subnet,
                'WeightedCapacity': 1.0
            })

    # Mixed instances policy ile Auto Scaling group oluştur
    asg_config = {
        'AutoScalingGroupName': 'spot-optimized-asg',
        'MinSize': target_capacity,
        'MaxSize': target_capacity * 2,
        'DesiredCapacity': target_capacity,
        'VPCZoneIdentifier': ','.join(subnets),
        'MixedInstancesPolicy': {
            'InstancesDistribution': {
                'OnDemandBaseCapacity': 0,  # Tüm Spot instance'lar
                'OnDemandPercentageAboveBaseCapacity': 0,
                'SpotAllocationStrategy': 'capacity-optimized',
                'SpotInstancePools': len(instance_types) * len(subnets)
            },
            'LaunchTemplate': {
                'LaunchTemplateSpecification': {
                    'LaunchTemplateName': 'spot-fleet-template',
                    'Version': '$Latest'
                },
                'Overrides': launch_template_overrides
            }
        },
        'Tags': [
            {
                'Key': 'CostOptimization',
                'Value': 'SpotInstances',
                'PropagateAtLaunch': True
            }
        ]
    }

    response = autoscaling_client.create_auto_scaling_group(**asg_config)

    return asg_config['AutoScalingGroupName']

Kritik insight: Capacity-optimized allocation strategy kullan ve 10+ instance type ile 3+ availability zone arasında diversify et. Bu, single-type Spot fleet’lere kıyasla interruption rate’lerini %90’a kadar azaltıyor.

Kesinti Yönetimi

Spot instance’lar sonlandırmadan önce EventBridge üzerinden 2 dakika uyarı verir. Graceful shutdown için Lambda fonksiyonu:

# Spot kesintisi için Lambda fonksiyonu
def lambda_handler(event, context):
    '''
    EC2 Spot Instance kesinti uyarılarını işle (2 dakika bildirim)
    Strateji: Task'ları boşalt ve işi kuyruğa geri gönder
    '''
    detail = event.get('detail', {})
    instance_id = detail.get('instance-id')
    instance_action = detail.get('instance-action')

    if not instance_id:
        return {'statusCode': 400, 'body': 'Olayda instance ID yok'}

    # Instance detaylarını ve tag'lerini al
    response = ec2_client.describe_instances(InstanceIds=[instance_id])
    instance = response['Reservations'][0]['Instances'][0]
    task_queue_url = get_tag_value(instance.get('Tags', []), 'TaskQueueUrl')

    if task_queue_url:
        sqs_client.send_message(
            QueueUrl=task_queue_url,
            MessageBody=json.dumps({
                'action': 'drain_instance',
                'instance_id': instance_id,
                'interruption_time': detail.get('time')
            })
        )

    return {'statusCode': 200, 'body': f'{instance_id} kesintisi işlendi'}

Uzun Süren İşler için Checkpoint

2 saatten uzun job’lar için checkpoint ile kesinti sonrası kaldığı yerden devam et:

def save_checkpoint(state, bucket, prefix='checkpoints'):
    """Job checkpoint'ini S3'e kaydet - Spot kesintisi sonrası kurtarma için"""
    checkpoint_key = f"{prefix}/{state.job_id}/checkpoint-{state.current_step}.pkl"
    s3_client.put_object(
        Bucket=bucket,
        Key=checkpoint_key,
        Body=pickle.dumps(state),
        ServerSideEncryption='AES256'
    )

def restore_checkpoint(job_id, bucket, prefix='checkpoints'):
    """Kesintiye uğrayan job için son checkpoint'i geri yükle"""
    response = s3_client.list_objects_v2(Bucket=bucket, Prefix=f"{prefix}/{job_id}/")
    latest = sorted(response['Contents'], key=lambda x: x['LastModified'], reverse=True)[0]
    obj = s3_client.get_object(Bucket=bucket, Key=latest['Key'])
    return pickle.loads(obj['Body'].read())

Production’dan en iyi pratikler: 30 dakikadan uzun job’lar için 5-10 dakikada bir checkpoint al.

S3 Depolama Optimizasyonu

S3 depolama maliyetleri Intelligent-Tiering ve lifecycle policy’leri ile %40-95 azaltılabilir. Etkili implementation:

def create_intelligent_lifecycle_policy(
    bucket_name: str,
    prefix: str = '',
    enable_deep_archive_tier: bool = True
) -> Dict:
    """
    Intelligent-Tiering'e geçiş ve opsiyonel deep archive tier ile
    S3 lifecycle policy oluştur
    """
    lifecycle_rules = [
        {
            'ID': 'transition-to-intelligent-tiering',
            'Filter': {'Prefix': prefix},
            'Status': 'Enabled',
            'Transitions': [{'Days': 0, 'StorageClass': 'INTELLIGENT_TIERING'}]
        },
        {
            'ID': 'cleanup-incomplete-multipart-uploads',
            'Filter': {'Prefix': prefix},
            'Status': 'Enabled',
            'AbortIncompleteMultipartUpload': {'DaysAfterInitiation': 7}
        },
        {
            'ID': 'expire-old-versions',
            'Filter': {'Prefix': prefix},
            'Status': 'Enabled',
            'NoncurrentVersionExpiration': {'NoncurrentDays': 90}
        }
    ]

    s3_client.put_bucket_lifecycle_configuration(
        Bucket=bucket_name,
        LifecycleConfiguration={'Rules': lifecycle_rules}
    )

    if enable_deep_archive_tier:
        s3_client.put_bucket_intelligent_tiering_configuration(
            Bucket=bucket_name,
            Id='deep-archive-config',
            IntelligentTieringConfiguration={
                'Id': 'deep-archive-config',
                'Status': 'Enabled',
                'Tierings': [
                    {'Days': 90, 'AccessTier': 'ARCHIVE_ACCESS'},
                    {'Days': 180, 'AccessTier': 'DEEP_ARCHIVE_ACCESS'}
                ]
            }
        )

    return {'bucket': bucket_name, 'rules_applied': len(lifecycle_rules)}

S3 Intelligent-Tiering detayları: Dört otomatik erişim katmanı. Archive Instant Access ile %68’e kadar, Deep Archive ile %95’e kadar tasarruf. 128KB’dan küçük objeler monitoring ücreti nedeniyle uygun değil.

Lambda Maliyet Optimizasyonu

Lambda maliyeti üç bileşenden oluşur: request, duration (GB-saniye) ve opsiyonel provisioned concurrency. Her birini nasıl optimize edeceğin:

Power Tuning ile Memory Optimizasyonu

AWS Lambda Power Tuning (açık kaynak) veri odaklı memory optimizasyonu sağlıyor:

def run_lambda_power_tuning(
    function_name: str,
    power_values: List[int] = [128, 256, 512, 1024, 1536, 2048, 3008],
    num_invocations: int = 10,
    strategy: str = 'balanced'  # 'cost', 'speed' veya 'balanced'
) -> Dict:
    """
    Optimal memory konfigürasyonunu bulmak için AWS Lambda Power Tuning çalıştır
    GitHub: alexcasalboni/aws-lambda-power-tuning
    """
    input_payload = {
        'lambdaARN': f'arn:aws:lambda:us-east-1:123456789012:function:{function_name}',
        'powerValues': power_values,
        'num': num_invocations,
        'payload': {},
        'parallelInvocation': True,
        'strategy': strategy
    }
    response = stepfunctions_client.start_execution(
        stateMachineArn='arn:aws:states:us-east-1:123456789012:stateMachine:lambda-power-tuner',
        input=json.dumps(input_payload)
    )
    # Sonuçları bekle ve döndür
    return {'recommended_memory': output.get('power'), 'optimization_summary': output}

Provisioned Concurrency Maliyet Analizi

Provisioned concurrency cold start’ı ortadan kaldırıyor ama her GB için ~$13/ay always-warm kapasite maliyeti var. Ne zaman mantıklı:

def calculate_lambda_costs(config: LambdaCostBreakdown) -> Dict:
    """
    Provisioned concurrency ile ve olmadan Lambda maliyetlerini hesapla
    Provisioned concurrency'nin maliyet-etkin olup olmadığını belirlemeye yardımcı olur
    """
    price_per_request = 0.20 / 1_000_000
    price_per_gb_second = 0.0000166667
    provisioned_price_per_gb_hour = 0.0000041667

    memory_gb = config.memory_mb / 1024
    duration_seconds = config.avg_duration_ms / 1000

    request_cost = config.invocations_monthly * price_per_request
    compute_cost = config.invocations_monthly * duration_seconds * memory_gb * price_per_gb_second
    total_on_demand = request_cost + compute_cost

    provisioned_cost = 0
    if config.provisioned_concurrency:
        provisioned_cost = (config.provisioned_concurrency * memory_gb * 730 *
                           provisioned_price_per_gb_hour)

    total_with_provisioned = request_cost + compute_cost + provisioned_cost
    return {
        'on_demand_cost_monthly': round(total_on_demand, 2),
        'provisioned_cost_monthly': round(total_with_provisioned, 2),
        'recommendation': 'Provisioned concurrency kullan' if total_with_provisioned < total_on_demand * 1.5 else 'On-demand\'da kal'
    }

Lambda optimizasyon notları: Memory allocation CPU ve network’ü de belirliyor. Sık kullanılan tatlı nokta 1024-1536MB. Provisioned concurrency sadece kesin latency gereksinimli user-facing API’lerde kullan.

Maliyet Tahsisi ve Etiketleme

Kapsamlı tagging ekipler, projeler ve environment’lar arasında maliyet attribution sağlar. Production-ready yaklaşım:

def create_tagging_compliance_rule():
    """
    Tag'lenmemiş kaynakları tespit eden AWS Config kuralı oluştur
    Environment, Project, CostCenter tag'lerini zorunlu kılar
    """
    config_client.put_config_rule(ConfigRule={
        'ConfigRuleName': 'required-tags-compliance',
        'Description': 'Kaynakların gerekli cost allocation tag\'lerine sahip olduğunu kontrol et',
        'Source': {'Owner': 'AWS', 'SourceIdentifier': 'REQUIRED_TAGS'},
        'InputParameters': '{"tag1Key":"Environment","tag2Key":"Project","tag3Key":"CostCenter"}',
        'Scope': {
            'ComplianceResourceTypes': [
                'AWS::EC2::Instance', 'AWS::RDS::DBInstance', 'AWS::S3::Bucket',
                'AWS::Lambda::Function', 'AWS::DynamoDB::Table'
            ]
        }
    })
    return {'rule_name': 'required-tags-compliance'}

Maliyet Tahsis Raporlaması

Tag’lere göre gruplanmış aylık maliyet raporları chargeback/showback için:

def generate_cost_allocation_report(
    month: str,
    group_by_tags: List[str] = ['Project', 'Environment', 'CostCenter']
) -> Dict:
    """
    Tag'lere göre gruplanmış maliyet tahsis raporu oluştur
    Dikkat gerektiren tag'lenmemiş maliyetleri tespit eder
    """
    start_date = datetime.strptime(f'{month}-01', '%Y-%m-%d')
    if start_date.month == 12:
        end_date = start_date.replace(year=start_date.year + 1, month=1, day=1)
    else:
        end_date = start_date.replace(month=start_date.month + 1, day=1)
    end_date = end_date - timedelta(days=1)

    cost_by_tags = {}
    for tag_key in group_by_tags:
        response = ce_client.get_cost_and_usage(
            TimePeriod={'Start': start_date.strftime('%Y-%m-%d'), 'End': end_date.strftime('%Y-%m-%d')},
            Granularity='MONTHLY',
            Metrics=['UnblendedCost'],
            GroupBy=[{'Type': 'TAG', 'Key': tag_key}]
        )
        tag_costs = {}
        for result in response['ResultsByTime']:
            for group in result['Groups']:
                tag_value = group['Keys'][0].split('$')[1] if '$' in group['Keys'][0] else 'Untagged'
                cost_by_tags[tag_key] = tag_costs

    total_response = ce_client.get_cost_and_usage(
        TimePeriod={'Start': start_date.strftime('%Y-%m-%d'), 'End': end_date.strftime('%Y-%m-%d')},
        Granularity='MONTHLY', Metrics=['UnblendedCost'])
    total_cost = float(total_response['ResultsByTime'][0]['Total']['UnblendedCost']['Amount'])
    return {'month': month, 'total_cost': round(total_cost, 2), 'breakdown_by_tags': cost_by_tags}

Tagging en iyi pratikleri: Gerekli tag’ler: Environment, Project, CostCenter, Owner. Cost allocation tag’lerini Billing Console’da kullanmadan önce aktif et. Hedef: <%10 tag’lenmemiş maliyet.

Optimizasyon Teknikleri Karşılaştırması

TeknikTasarrufUygulama ÇabasıRiskEn İyi Kullanım
Right-Sizing (Compute Optimizer)%20-40DüşükDüşükOver-provisioned instance’lar
Savings Plans%66’ya kadarDüşükOrtaÖngörülebilir baseline
Reserved Instances%72’ye kadarDüşükOrtaStabil workload’lar
Spot Instances%70-90OrtaOrtaFault-tolerant workload’lar
Lambda memory optimizasyonu%20-50DüşükDüşükLambda-ağır mimariler
S3 Intelligent-Tiering%40-95DüşükDüşükBüyük depolama, karışık erişim
Aurora Serverless v2%30-70OrtaDüşükDeğişken veritabanı workload’ları
Instance scheduling%70OrtaDüşükNon-production environment’lar

Önemli Çıkarımlar

Engineering Ekipleri için:

  1. Maliyet optimizasyonu sürekli, tek seferlik değil: Compute Optimizer önerilerini aylık gözden geçir, utilization’a göre Savings Plans’i üç ayda bir ayarla, kullanılmayan kaynakları haftalık temizle.

  2. Right-sizing en hızlı ROI sağlar: Compute Optimizer düşük implementation riski ile %20-40 tasarruf fırsatları tespit ediyor. Güven oluşturmak için non-production environment’larla başla.

  3. Tag’leme maliyet sorumluluğunu sağlar: Tag’leri kaynak oluşturma sırasında zorla (retroaktif olarak değil). Gerekli tag’ler: Environment, Project, CostCenter, Owner. <%10 tag’lenmemiş maliyet hedefle.

Platform/FinOps Ekipleri için:

  1. Önce maliyet görünürlüğü oluştur: Geçmiş analiz için Cost Explorer, proaktif alerting için Budgets, olağandışı harcama pattern’leri için Cost Anomaly Detection.

  2. Governance’ı erken implement et: AWS Organizations üzerinden tag policy’leri, compliance monitoring için AWS Config, harcama limitleri için Service Control Policy’ler.

  3. Commitment’ları ve esnekliği dengele: Baseline’ın %60-70’ini Savings Plans/RI’larla kapsla, büyüme için %30-40’ı on-demand bırak. 1 yıllık term’lerle başla (3 yıllıktan daha az risk).

Teknik Karar Vericiler için:

  1. Hızlı kazanımlar vs uzun vadeli strateji: 1. ay %20-30 tasarruf (idle kaynaklar, S3 lifecycle, budget’lar), 2-3. aylar %20-30 ekler (rightsizing, commitment’lar), 4+ ay %5-10 sürekli ekler (continuous improvement).

  2. Maliyet optimizasyon ROI’si: Aylık 100,000AWSharcamasıic\cin,100,000 AWS harcaması için, %40 optimizasyon = yıllık 480,000 tasarruf. Platform engineer zaman yatırımı: ayda ~40 saat. ROI: yatırılan zamana 60x+ dönüş.

  3. Kültürel değişim kritik: Maliyeti performans ve güvenilirlikle birlikte bir KPI yap. Mimari incelemelerinde maliyet etkisini dahil et. Ekiplerle optimizasyon kazanımlarını kutla.

Burada kapsanan araçlar ve teknikler AWS maliyet optimizasyonuna sistematik bir yaklaşım sağlıyor. Hızlı kazanımlarla başla, görünürlük oluştur, ardından kademeli olarak stratejik optimizasyonlar implement et. Anahtar, maliyet optimizasyonunu tek seferlik bir proje değil, sürekli bir engineering pratiği olarak ele almak. Ekibinin kültürüne maliyet bilincini dahil etmek—mimari kararlarda maliyet boyutunu sorgulama alışkanlığı—uzun vadede tek tek optimizasyonlardan daha fazla etki yaratır.

Uygulama sırası: İlk ay idle kaynakları kapat, S3 lifecycle policy’leri aktif et, budget alarmları kur. İkinci üç ayda Compute Optimizer önerilerini uygula, Savings Plans’e başla. Sonraki aylarda sürekli iyileştirme: aylık cost review, yeni workload’lar için right-sizing checklist.

Kaynaklar

İlgili yazılar

AWS ile Edge Computing: CloudFront Functions vs Lambda@Edge

Global uygulamalar için AWS edge computing çözümlerini seçme ve uygulama üzerine pratik örnekler ve maliyet optimizasyonu stratejileri içeren kapsamlı teknik rehber.

awscloudfrontlambda+6
Amazon Cognito Derinlemesine: Temel Authentication'ın Ötesinde

Amazon Cognito'nun gelişmiş özellikleri üzerine kapsamlı teknik kılavuz: özel authentication akışları, federation pattern'leri, multi-tenancy mimarileri, migration stratejileri ve production-grade güvenlik implementasyonu.

awscognitoauthentication+7
AWS Secrets Manager & Parameter Store: Güvenlik Best Practices

AWS Secrets Manager ve Systems Manager Parameter Store'u karşılaştıran kapsamlı teknik rehber - hangi servisi ne zaman kullanmalı ve gerçek dünya implementation pattern'leri.

awssecrets-managerparameter-store+8
AI Workload'ları için FinOps: Production'da LLM Maliyet Yönetimi

Token-based pricing, production LLM uygulamaları için benzersiz maliyet zorlukları yaratır. Prompt caching, model routing ve token budget'ları ile kaliteden ödün vermeden maliyetleri %60-80 azaltmak için sistematik optimizasyon stratejilerini öğren.

awsfinopsllm+5
Amazon Aurora: AWS'nin Cloud-Native Veritabanını Anlamak

Aurora mimarisi, maliyet analizi ve RDS'e göre ne zaman seçilmesi gerektiğine dair kapsamlı rehber. Migration stratejileri, performans özellikleri ve gerçek dünya karar çerçeveleri içerir.

awsaurorards+6