AWS Cost Explorer ile Bulut Maliyet Analizi ve Optimizasyonu

Bulut maliyetleri kontrolden çıktığında, faturanın sonunda “nasıl oldu bu?” diye şaşırıp kalmak çok yaygın bir durum. Özellikle ekipler büyüdükçe, kaynak sayısı arttıkça ve farklı departmanlar kendi hesaplarını yönetmeye başladıkça AWS faturaları beklenmedik rakamlar göstermeye başlar. İşte tam bu noktada AWS Cost Explorer devreye giriyor. Sadece grafik izlemek için değil, gerçek maliyet optimizasyonu için güçlü bir araç olan Cost Explorer’ı nasıl etkili kullanırsınız, bunu derinlemesine anlatacağım.

AWS Cost Explorer Nedir ve Neden Önemlidir

Cost Explorer, AWS’nin yerleşik maliyet analiz aracıdır. Tarihsel harcama verilerinizi görselleştirir, tahminler üretir ve granüler filtreler sayesinde tam olarak neye ne kadar para harcadığınızı görmenizi sağlar. Ücretsiz tier kapsamında temel özellikler kullanılabilir ancak API üzerinden sorgu yaptığınızda her istek için küçük bir ücret ödüyorsunuz.

Pek çok ekip Cost Explorer’ı açıp bakıyor, birkaç grafik görüyor ve kapatıyor. Oysa bu aracın asıl gücü, CLI ve API entegrasyonlarında gizli. Programatik olarak maliyet verilerini çekip kendi sistemlerinizle entegre etmek, otomatik raporlar oluşturmak ve anomali tespiti yapmak mümkün.

Başlamadan Önce: Gerekli IAM İzinleri

Cost Explorer’ı CLI üzerinden kullanmak için doğru IAM izinlerine ihtiyacınız var. Minimum gereksinim şunlar:

# IAM politikası oluştur
aws iam create-policy 
  --policy-name CostExplorerReadOnly 
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "ce:GetCostAndUsage",
          "ce:GetCostForecast",
          "ce:GetReservationUtilization",
          "ce:GetSavingsPlansCoverage",
          "ce:GetDimensionValues",
          "ce:GetTags",
          "ce:ListCostAllocationTags"
        ],
        "Resource": "*"
      }
    ]
  }'

Eğer organizasyon seviyesinde çalışıyorsanız ve birden fazla hesabın maliyetlerini görmek istiyorsanız, bu politikayı management account üzerinde tanımlamanız gerekiyor.

Temel Maliyet Sorguları

Aylık Toplam Harcamayı Çekmek

En temel kullanım senaryosu, belirli bir dönem için toplam maliyeti görmek. Bu komutu bir cron job’a bağladığınızda basit bir maliyet monitörü kurmuş oluyorsunuz:

# Son 3 ayın aylık maliyet özeti
aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-04-01 
  --granularity MONTHLY 
  --metrics "BlendedCost" "UnblendedCost" "UsageQuantity" 
  --query 'ResultsByTime[*].{Period:TimePeriod.Start,Cost:Total.BlendedCost.Amount,Unit:Total.BlendedCost.Unit}' 
  --output table

BlendedCost: Rezervasyon ve tasarruf planlarının dağıtılmış maliyetini gösterir, konsolidasyon hesaplarında anlamlı.

UnblendedCost: Her kaynağın gerçek ödediğiniz ücreti, tek hesap analizinde daha doğru sonuç verir.

AmortizedCost: Rezervasyon ve Savings Plans ön ödemelerini zaman içine yayan maliyet. Aylık karşılaştırma için en sağlıklı metrik bu.

Servise Göre Maliyeti Gruplamak

Hangi AWS servisi ne kadar yiyor sorusunun cevabı:

# Servise göre gruplandırılmış bu ayın maliyeti
aws ce get-cost-and-usage 
  --time-period Start=2024-03-01,End=2024-04-01 
  --granularity MONTHLY 
  --metrics "UnblendedCost" 
  --group-by Type=DIMENSION,Key=SERVICE 
  --query 'ResultsByTime[0].Groups[*].{Service:Keys[0],Cost:Metrics.UnblendedCost.Amount}' 
  --output json | 
  python3 -c "
import json, sys
data = json.load(sys.stdin)
sorted_data = sorted(data, key=lambda x: float(x['Cost']), reverse=True)
for item in sorted_data[:10]:
    print(f"${float(item['Cost']):>10.2f}  {item['Service']}")
"

Bu scripti çalıştırdığınızda en pahalı 10 servisi sıralı göreceksiniz. Çoğunlukla EC2, RDS ve veri transferi ilk üçe giriyor.

Tag Bazlı Maliyet Analizi

Gerçek dünyada en kritik özellik bu. Tag’ler olmadan maliyet analizi yapmak, karanlıkta el yordamıyla yürümek gibi. Önce Cost Allocation Tag’lerini aktif etmeniz gerekiyor:

# Aktif cost allocation tag'lerini listele
aws ce list-cost-allocation-tags 
  --status Active 
  --query 'CostAllocationTags[*].TagKey'

# Belirli bir tag key'i aktif et (management account gerektirir)
aws ce update-cost-allocation-tags-status 
  --cost-allocation-tags-status TagKey=Environment,Status=Active

Tag aktifleştirme işlemi 24 saate kadar sürebilir, sabırla bekleyin. Sonrasında environment bazlı maliyet analizi yapabilirsiniz:

# Environment tag'e göre maliyet dağılımı
aws ce get-cost-and-usage 
  --time-period Start=2024-03-01,End=2024-04-01 
  --granularity MONTHLY 
  --metrics "UnblendedCost" 
  --group-by Type=TAG,Key=Environment 
  --query 'ResultsByTime[0].Groups[*].{Tag:Keys[0],Cost:Metrics.UnblendedCost.Amount}' 
  --output json

Gerçek Dünya Senaryosu: Beklenmedik Maliyet Artışı Analizi

Bir gece saat 23:00’de Slack’e alarm düştü. Maliyet anomali dedektörü bir saatte $200’lık bir artış tespit etmişti. Sorun neydi? Data transfer maliyetleri aniden patlamıştı.

İşte böyle bir durumda günlük granülarite ile belirli bir servisi inceliyorsunuz:

#!/bin/bash
# cost_spike_analyzer.sh - Maliyet artışı analiz scripti

SERVICE="AWS Data Transfer"
START_DATE=$(date -d "7 days ago" +%Y-%m-%d)
END_DATE=$(date +%Y-%m-%d)

echo "=== Maliyet Artışı Analizi: $SERVICE ==="
echo "Dönem: $START_DATE - $END_DATE"
echo ""

aws ce get-cost-and-usage 
  --time-period Start=$START_DATE,End=$END_DATE 
  --granularity DAILY 
  --metrics "UnblendedCost" "UsageQuantity" 
  --filter '{
    "Dimensions": {
      "Key": "SERVICE",
      "Values": ["AWS Data Transfer"]
    }
  }' 
  --query 'ResultsByTime[*].{Date:TimePeriod.Start,Cost:Total.UnblendedCost.Amount,Usage:Total.UsageQuantity.Amount}' 
  --output json | 
  python3 -c "
import json, sys
data = json.load(sys.stdin)
print(f'{'Tarih':<12} {'Maliyet ($)':<15} {'Kullanim (GB)'}')
print('-' * 45)
for item in data:
    print(f"{item['Date']:<12} ${float(item['Cost']):<14.2f} {float(item['Usage']):.2f}")
"

Bu script bize günlük breakdown verdi ve 3 gün önceki ani artışı tespit ettik. Ardından EC2 instance bazında inceleme yaptık ve yanlış region’a yapılandırılmış bir backup job’u bulduk. İstanbul’daki birinin yanlış region seçmesi, her gece terabytes veri transfer etmesine neden oluyordu.

Maliyet Tahmini ve Bütçe Planlama

Cost Explorer’ın tahmin özelliği, önümüzdeki dönem için projeksiyon yapmanızı sağlıyor:

# Sonraki 3 ay için maliyet tahmini
aws ce get-cost-forecast 
  --time-period Start=2024-04-01,End=2024-07-01 
  --metric UNBLENDED_COST 
  --granularity MONTHLY 
  --prediction-interval-level 95 
  --query '{
    Total: Total.Amount,
    ForecastByTime: ForecastResultsByTime[*].{
      Period: TimePeriod.Start,
      MeanValue: MeanValue,
      LowerBound: PredictionIntervalLowerBound,
      UpperBound: PredictionIntervalUpperBound
    }
  }'

prediction-interval-level 95: %95 güven aralığı. Gerçek değerin bu aralık içinde kalma ihtimali %95. Bütçe planlaması için üst sınırı kullanın, sürpriz yaşamazsınız.

Rezervasyon ve Savings Plans Analizi

Reserved Instance veya Savings Plans satın aldıysanız bunların ne kadar verimli kullanıldığını takip etmek kritik:

# Reserved Instance kullanım oranı analizi
aws ce get-reservation-utilization 
  --time-period Start=2024-03-01,End=2024-04-01 
  --granularity MONTHLY 
  --group-by Type=DIMENSION,Key=INSTANCE_TYPE 
  --query 'UtilizationsByTime[0].Groups[*].{
    InstanceType:Attributes.instanceType,
    UtilizationPercentage:Utilization.UtilizationPercentage,
    PurchasedHours:Utilization.TotalReservedHours,
    UsedHours:Utilization.UsedHours
  }' 
  --output json | 
  python3 -c "
import json, sys
data = json.load(sys.stdin)
print('Dusuk kullanim oranlı RI'lar (<%80):')
print('-' * 60)
for item in data:
    util = float(item.get('UtilizationPercentage', 0))
    if util < 80:
        print(f"  {item['InstanceType']}: %{util:.1f} kullanım")
        print(f"    Satın alınan: {item['PurchasedHours']} saat")
        print(f"    Kullanılan: {item['UsedHours']} saat")
"

%80 altındaki kullanım oranı alarm vermeli. Bu rezervasyonları ya satabilirsiniz (AWS Marketplace’de RI satışı mümkün) ya da workload’larınızı bu instance type’lara yönlendirebilirsiniz.

Otomatik Maliyet Raporu Scripti

Pratik bir sysadmin olarak haftada bir email almak yerine Slack’e düzenli rapor atmayı tercih ediyorum. İşte bunun için kullandığım script:

#!/bin/bash
# weekly_cost_report.sh
# crontab: 0 9 * * 1 /opt/scripts/weekly_cost_report.sh

SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
CURRENT_MONTH_START=$(date +%Y-%m-01)
TODAY=$(date +%Y-%m-%d)
LAST_MONTH_START=$(date -d "last month" +%Y-%m-01)
LAST_MONTH_END=$CURRENT_MONTH_START

# Bu ayın maliyeti
CURRENT_COST=$(aws ce get-cost-and-usage 
  --time-period Start=$CURRENT_MONTH_START,End=$TODAY 
  --granularity MONTHLY 
  --metrics "UnblendedCost" 
  --query 'ResultsByTime[0].Total.UnblendedCost.Amount' 
  --output text)

# Geçen ayın maliyeti
LAST_MONTH_COST=$(aws ce get-cost-and-usage 
  --time-period Start=$LAST_MONTH_START,End=$LAST_MONTH_END 
  --granularity MONTHLY 
  --metrics "UnblendedCost" 
  --query 'ResultsByTime[0].Total.UnblendedCost.Amount' 
  --output text)

# Yüzde değişim hesapla
CHANGE=$(python3 -c "
current = float('$CURRENT_COST')
last = float('$LAST_MONTH_COST')
change = ((current - last) / last) * 100
symbol = '+' if change > 0 else ''
print(f'{symbol}{change:.1f}%')
")

# En pahalı 5 servis
TOP_SERVICES=$(aws ce get-cost-and-usage 
  --time-period Start=$CURRENT_MONTH_START,End=$TODAY 
  --granularity MONTHLY 
  --metrics "UnblendedCost" 
  --group-by Type=DIMENSION,Key=SERVICE 
  --query 'ResultsByTime[0].Groups[*].{Service:Keys[0],Cost:Metrics.UnblendedCost.Amount}' 
  --output json | 
  python3 -c "
import json, sys
data = json.load(sys.stdin)
sorted_data = sorted(data, key=lambda x: float(x['Cost']), reverse=True)
lines = []
for item in sorted_data[:5]:
    lines.append(f"• {item['Service']}: ${float(item['Cost']):.2f}")
print('n'.join(lines))
")

# Slack mesajı gönder
PAYLOAD=$(cat <<EOF
{
  "text": "*Haftalık AWS Maliyet Raporu*",
  "attachments": [
    {
      "color": "good",
      "fields": [
        {
          "title": "Bu Ay (MTD)",
          "value": "$$CURRENT_COST",
          "short": true
        },
        {
          "title": "Geçen Aya Göre",
          "value": "$CHANGE",
          "short": true
        },
        {
          "title": "En Pahalı 5 Servis",
          "value": "$TOP_SERVICES",
          "short": false
        }
      ]
    }
  ]
}
EOF
)

curl -s -X POST 
  -H 'Content-type: application/json' 
  --data "$PAYLOAD" 
  $SLACK_WEBHOOK

echo "Rapor gönderildi: $(date)"

Cost Anomaly Detection Kurulumu

Manuel takip yetmez, anomali tespiti de kurmanız şart. Bu özellik makine öğrenmesi kullanarak beklenmedik maliyet artışlarını tespit ediyor:

# Anomaly monitor oluştur - tüm AWS servisleri için
aws ce create-anomaly-monitor 
  --anomaly-monitor '{
    "MonitorName": "AllServicesMonitor",
    "MonitorType": "DIMENSIONAL",
    "MonitorDimension": "SERVICE"
  }'

# Monitor ARN'ını al
MONITOR_ARN=$(aws ce get-anomaly-monitors 
  --query 'AnomalyMonitors[0].MonitorArn' 
  --output text)

# Alert aboneliği oluştur - $50 üzeri anomalilerde email gönder
aws ce create-anomaly-subscription 
  --anomaly-subscription "{
    "SubscriptionName": "DailyAnomalyAlert",
    "MonitorArnList": ["$MONITOR_ARN"],
    "Subscribers": [
      {
        "Address": "[email protected]",
        "Type": "EMAIL"
      }
    ],
    "Threshold": 50,
    "Frequency": "DAILY"
  }"

Anomali tespiti aktif olduktan sonra, Cost Explorer’ın ML modeli 10-14 günlük learning period’undan sonra baseline oluşturuyor ve bu baseline’dan sapmaları size bildiriyor.

Filtre Kombinasyonları ile İleri Seviye Sorgular

Bazen tek filtre yetmez, birden fazla koşulu kombine etmeniz gerekir:

# Production ortamındaki EC2 maliyetleri (tag + servis filtresi)
aws ce get-cost-and-usage 
  --time-period Start=2024-03-01,End=2024-04-01 
  --granularity DAILY 
  --metrics "UnblendedCost" 
  --filter '{
    "And": [
      {
        "Dimensions": {
          "Key": "SERVICE",
          "Values": ["Amazon Elastic Compute Cloud - Compute"]
        }
      },
      {
        "Tags": {
          "Key": "Environment",
          "Values": ["production"]
        }
      },
      {
        "Not": {
          "Dimensions": {
            "Key": "USAGE_TYPE",
            "Values": ["DataTransfer-Out-Bytes"]
          }
        }
      }
    ]
  }' 
  --group-by Type=DIMENSION,Key=INSTANCE_TYPE 
  --output json

Bu sorgu size sadece production’daki EC2 compute maliyetlerini, data transfer hariç tutarak instance type bazında gösteriyor. İnce ayar yapmanın önemi burada ortaya çıkıyor.

Python ile Cost Explorer Entegrasyonu

CLI harika ama Python ile daha güçlü analizler yapabilirsiniz. Boto3 kullanarak basit bir maliyet dashboard scripti:

#!/usr/bin/env python3
# cost_dashboard.py

import boto3
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta

def get_monthly_costs(months_back=6):
    client = boto3.client('ce', region_name='us-east-1')
    
    end_date = datetime.today().replace(day=1)
    start_date = end_date - relativedelta(months=months_back)
    
    response = 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'}
        ]
    )
    
    monthly_data = {}
    for period in response['ResultsByTime']:
        month = period['TimePeriod']['Start'][:7]
        monthly_data[month] = {}
        for group in period['Groups']:
            service = group['Keys'][0]
            cost = float(group['Metrics']['UnblendedCost']['Amount'])
            if cost > 0.01:
                monthly_data[month][service] = round(cost, 2)
    
    return monthly_data

def find_cost_increases(monthly_data):
    months = sorted(monthly_data.keys())
    if len(months) < 2:
        return []
    
    current = monthly_data[months[-1]]
    previous = monthly_data[months[-2]]
    
    increases = []
    for service, cost in current.items():
        prev_cost = previous.get(service, 0)
        if prev_cost > 0:
            change_pct = ((cost - prev_cost) / prev_cost) * 100
            if change_pct > 20:
                increases.append({
                    'service': service,
                    'current': cost,
                    'previous': prev_cost,
                    'change_pct': round(change_pct, 1)
                })
    
    return sorted(increases, key=lambda x: x['change_pct'], reverse=True)

if __name__ == '__main__':
    print("Maliyet analizi başlatılıyor...")
    data = get_monthly_costs(months_back=3)
    
    print("n=== Aylık Maliyet Özeti ===")
    for month, services in sorted(data.items()):
        total = sum(services.values())
        print(f"n{month}: Toplam ${total:.2f}")
        top_5 = sorted(services.items(), key=lambda x: x[1], reverse=True)[:5]
        for svc, cost in top_5:
            print(f"  {svc}: ${cost:.2f}")
    
    print("n=== Dikkat Gerektiren Artışlar (>%20) ===")
    increases = find_cost_increases(data)
    for item in increases:
        print(f"  {item['service']}")
        print(f"    Önceki ay: ${item['previous']:.2f}")
        print(f"    Bu ay: ${item['current']:.2f}")
        print(f"    Artış: %{item['change_pct']}")

Bu scripti çalıştırıp çıktısını bir cron job ile düzenli kayıt altına aldığınızda, zaman içinde güçlü bir maliyet tarih arşivi oluşturuyorsunuz.

Tag Stratejisi Olmadan Maliyet Analizi Anlamsız

Cost Explorer’ı ne kadar iyi kullanırsanız kullanın, kaynaklarınız düzgün tag’lenmemişse analiz yüzeysel kalır. Minimum tag standardı şöyle olmalı:

  • Environment: production, staging, development, testing
  • Project: hangi projeye ait olduğu
  • Team: sorumlu ekip
  • CostCenter: muhasebe için maliyet merkezi
  • Owner: kaynağı oluşturan kişinin email’i

AWS Config ile tag compliance rule’u kurarak tag’siz kaynak oluşturulmasını tespit edebilirsiniz. Daha katı bir yaklaşım için Service Control Policy (SCP) ile belirli tag’ler olmadan kaynak oluşturmayı tamamen engelleyebilirsiniz.

Maliyet Optimizasyonu İçin Eylem Planı

Cost Explorer analizinden sonra ne yapacaksınız? Verileri toplayıp bakmak yetmez, aksiyon almanız lazım:

  • Kullanılmayan kaynakları tespit edin: $0 kullanım ama maliyet var mı? Büyük ihtimalle silebilirsiniz.
  • Sağ boyutlandırma: EC2 CPU kullanımı sürekli %5 altındaysa bir küçük instance type’a geçin.
  • Spot instance fırsatları: Batch workload’lar için Spot Instance kullanımını değerlendirin, %70’e kadar tasarruf.
  • Veri transferini optimize edin: Cross-region veri transferi pahalı, aynı region’da tutun.
  • S3 lifecycle policy: Eski nesneleri otomatik olarak daha ucuz storage class’lara taşıyın.
  • NAT Gateway maliyeti: Genellikle beklenmedik şekilde yükseliyor, VPC endpoint alternatifleri değerlendirin.
  • Idle RDS: Kullanılmayan veritabanlarını snapshot alıp durdurun veya silin.

Sonuç

AWS Cost Explorer’ı sadece “fatura ne kadar geldi” sorusunu yanıtlamak için kullananlar bu aracın gerçek potansiyelini kaçırıyor. Doğru kullanıldığında, anomali tespiti, servis bazlı granüler analiz, tag tabanlı departman maliyetleri ve otomatik raporlama ile bulut bütçenizin gerçek anlamda sahibi olabiliyorsunuz.

Başlangıç için pratik adımlar şunlar: Önce Cost Allocation Tag’lerini aktif edin ve ekibinize tag standardı oturtun. Sonra basit bir haftalık rapor scripti kurun, Slack’e veya email’e atsın. Anomali detection’ı mutlaka aktif edin, bir kez kuruyorsunuz ve sürekli arka planda çalışıyor. Son olarak ayda bir rezervasyon kullanım oranlarınıza bakın ve düşük performanslı RI’ları değerlendirin.

Maliyet yönetimi tek seferlik bir proje değil, süregelen bir disiplin. Cost Explorer’ı rutin operasyonlarınızın parçası haline getirdiğinizde, sürpriz faturalarla karşılaşma ihtimaliniz dramatik şekilde düşüyor. Ve dürüst olmak gerekirse, “bu ay $3000 fazla harcadık neden?” sorusuna cevap verememenin verdiği o rahatsızlık hissinden kurtulmak paha biçilemez.

Bir yanıt yazın

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