AWS Cost Explorer ile Bulut Maliyet Analizi ve Optimizasyonu

AWS faturanıza baktığınızda gözleriniz karardıysa, ay sonu sürprizi yaşadıysanız ya da “bu ay neden bu kadar ödedik?” sorusuna cevap arayıp duruyorsanız, bu yazı tam size göre. AWS Cost Explorer, bulut maliyetlerinizi anlamlı hale getiren, hangi servisin ne kadar harcama yaptığını gösteren ve gelecek ay ne ödeyeceğinizi tahmin etmenize yardımcı olan güçlü bir araç. Bugün bu aracı hem konsol üzerinden hem de CLI ve API aracılığıyla nasıl kullanacağımızı, gerçek dünya senaryolarıyla birlikte ele alacağız.

AWS Cost Explorer Nedir ve Neden Önemlidir

AWS Cost Explorer, Amazon’un sunduğu yerleşik maliyet analizi aracıdır. Aylık, günlük hatta saatlik granülaritede harcamalarınızı görselleştirmenizi, filtrelemenizi ve tahmin almanızı sağlar. Ücretli mi diye soruyorsanız, API üzerinden her istek başına 0.01 dolar ödüyorsunuz, ancak konsol üzerindeki kullanım ücretsiz.

Bir sysadmin olarak neden bunu bilmeniz gerekiyor? Çünkü artık “biz sadece sunucuları yönetiriz, maliyet finans departmanının işi” dönemi bitti. FinOps kültürü giderek yaygınlaşıyor ve altyapı yöneticilerinden de maliyet optimizasyonu konusunda sorumluluk almaları bekleniyor. Üstelik Cost Explorer’ı iyi kullanmak, anomalileri önceden yakalamak ve gereksiz harcamaları engellemek anlamına geliyor ki bu da direkt olarak şirketin kasasına katkı sağlıyor.

Temel Kavramlar

Cost Explorer’a girmeden önce birkaç temel kavramı netleştirelim:

  • Unblended Cost: Her kaynağın kendi başına ne kadar maliyete neden olduğu, rezervasyon indirimleri dağıtılmadan.
  • Blended Cost: Reserved Instance veya Savings Plans indirimleri hesaba katılarak dağıtılmış maliyet.
  • Amortized Cost: Rezervasyon ön ödemelerinin aylara dağıtılmış hali. Özellikle RI ve Savings Plans kullananlar için daha gerçekçi bir görünüm sunar.
  • Net Cost: Marketplace kredileri ve AWS kredi promosyonları düşüldükten sonra kalan net maliyet.
  • Usage Type: Bir servisin nasıl kullanıldığını gösteren detaylı etiket, örneğin BoxUsage:t3.medium gibi.

Bu kavramları anlamak önemli çünkü farklı raporlama bağlamlarında farklı maliyet tiplerini kullanmanız gerekecek.

AWS CLI ile Cost Explorer Kullanımı

Konsol güzel ama asıl güç CLI ve otomasyonda. AWS CLI’ın ce (cost explorer) subcommand’ını kullanarak pek çok şeyi script’e dökülebilir hale getirirsiniz.

Önce temel bir sorgu ile başlayalım. Bu ay toplam ne harcadınız?

aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --metrics "BlendedCost" 
  --query 'ResultsByTime[*].Total.BlendedCost.Amount' 
  --output text

Servise göre kırılım almak istiyorsanız --group-by parametresini kullanın:

aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --metrics "BlendedCost" "UsageQuantity" 
  --group-by Type=DIMENSION,Key=SERVICE 
  --output json | jq -r '.ResultsByTime[0].Groups[] | "(.Keys[0]): (.Metrics.BlendedCost.Amount) USD"' | sort -t: -k2 -rn | head -10

Bu komut size en çok harcama yapan 10 servisi sıralı şekilde getirir. jq kullanıyorsanız çıktıyı parse etmek çok kolaylaşıyor.

Günlük granülaritede EC2 maliyetlerini görmek isterseniz:

aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity DAILY 
  --metrics "UnblendedCost" 
  --filter '{
    "Dimensions": {
      "Key": "SERVICE",
      "Values": ["Amazon Elastic Compute Cloud - Compute"]
    }
  }' 
  --query 'ResultsByTime[*].[TimePeriod.Start, Total.UnblendedCost.Amount]' 
  --output text

Tag Bazlı Maliyet Analizi

Bu kısım pratikte en değerli olanı. Eğer kaynaklarınızı düzgün tag’lemişseniz, maliyet raporlarınız çok daha anlamlı hale gelir. Örneğin Environment=production, Team=backend, Project=checkout-service gibi tag’ler kullanıyorsanız:

aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --metrics "BlendedCost" 
  --group-by Type=TAG,Key=Environment 
  --output json | jq -r '.ResultsByTime[0].Groups[] | "(.Keys[0]): (.Metrics.BlendedCost.Amount) USD"'

Burada dikkat edilmesi gereken bir nokta var. Bir tag’i Cost Explorer’da kullanabilmek için önce onu Cost Allocation Tag olarak aktif etmeniz gerekiyor. AWS Console üzerinden Billing > Cost Allocation Tags yolunu izleyerek bunu yapabilirsiniz. Tag’ler aktif edildikten sonra görünür olması 24 saate kadar sürebilir.

Belirli bir projeye ait maliyetleri izole etmek için filter ve group-by’ı birlikte kullanabilirsiniz:

aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --metrics "BlendedCost" 
  --filter '{
    "Tags": {
      "Key": "Project",
      "Values": ["checkout-service"]
    }
  }' 
  --group-by Type=DIMENSION,Key=SERVICE 
  --output json | jq -r '.ResultsByTime[0].Groups[] | select(.Metrics.BlendedCost.Amount | tonumber > 1) | "(.Keys[0]): $(.Metrics.BlendedCost.Amount | tonumber | . * 100 | round / 100)"'

Maliyet Anomali Tespiti

AWS Cost Anomaly Detection, machine learning kullanarak beklenmedik harcama artışlarını otomatik olarak tespit eder. Bu özelliği CLI üzerinden de yönetebilirsiniz:

# Anomali monitörü oluştur
aws ce create-anomaly-monitor 
  --anomaly-monitor '{
    "MonitorName": "EC2-Anomaly-Monitor",
    "MonitorType": "DIMENSIONAL",
    "MonitorDimension": "SERVICE"
  }'

# Anomali aboneliği oluştur - 100 dolar üzeri anomalilerde SNS'e bildir
aws ce create-anomaly-subscription 
  --anomaly-subscription '{
    "SubscriptionName": "High-Spend-Alert",
    "MonitorArnList": ["arn:aws:ce::123456789012:anomalymonitor/XXXXXXXX"],
    "Subscribers": [
      {
        "Address": "arn:aws:sns:us-east-1:123456789012:cost-alerts",
        "Type": "SNS"
      }
    ],
    "Threshold": 100,
    "Frequency": "DAILY"
  }'

Mevcut anomalileri sorgulamak için:

aws ce get-anomalies 
  --date-interval Start=2024-01-01,End=2024-01-31 
  --query 'Anomalies[*].{Service:RootCauses[0].Service,Impact:Impact.TotalImpact,Start:AnomalyStartDate}' 
  --output table

Savings Plans ve Reserved Instance Analizi

RI veya Savings Plans kullanıyorsanız, bunların ne kadar coverage sağladığını ve utilization oranlarını düzenli olarak kontrol etmeniz gerekir. Eksik coverage para kaybı, düşük utilization da ayrı bir para kaybı demek.

# Savings Plans utilization raporu
aws ce get-savings-plans-utilization 
  --time-period Start=2024-01-01,End=2024-01-31 
  --query 'Total.{Utilization:Utilization.UtilizationPercentage, Savings:Savings.TotalSavings, UnusedCommitment:Savings.OnDemandCostEquivalent}' 
  --output json

Coverage raporunu da çekebilirsiniz. Bu size on-demand harcamalarınızın yüzde kaçının Savings Plans veya RI tarafından karşılandığını gösterir:

aws ce get-savings-plans-coverage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --group-by Type=DIMENSION,Key=INSTANCE_TYPE_FAMILY 
  --query 'SavingsPlansCoverages[*].Groups[*].{InstanceFamily:Attributes.INSTANCE_TYPE_FAMILY, Coverage:Coverage.CoveragePercentage}' 
  --output json

Gerçek Dünya Senaryosu: Aylık Maliyet Raporu Otomasyonu

Şimdi pratikte çok işe yarayan bir senaryo kurguLayalım. Diyelim ki her ayın 1’inde önceki ayın maliyet raporunu Slack’e veya e-postaya otomatik olarak göndermeniz gerekiyor. Bunu Lambda + EventBridge ile yapabilirsiniz ama önce script’i hazırlayalım:

#!/bin/bash
# monthly-cost-report.sh
# Önceki ayın maliyet raporunu çeker ve formatlı şekilde yazdırır

set -euo pipefail

LAST_MONTH_START=$(date -d "last month" +%Y-%m-01)
LAST_MONTH_END=$(date +%Y-%m-01)
PROFILE=${AWS_PROFILE:-default}

echo "========================================"
echo "AWS Maliyet Raporu: $LAST_MONTH_START / $LAST_MONTH_END"
echo "========================================"

# Toplam maliyet
TOTAL=$(aws ce get-cost-and-usage 
  --profile "$PROFILE" 
  --time-period Start="$LAST_MONTH_START",End="$LAST_MONTH_END" 
  --granularity MONTHLY 
  --metrics "BlendedCost" 
  --query 'ResultsByTime[0].Total.BlendedCost.Amount' 
  --output text)

echo ""
echo "TOPLAM HARCAMA: $TOTAL USD"
echo ""
echo "--- Servise Göre Kırılım (Top 10) ---"

aws ce get-cost-and-usage 
  --profile "$PROFILE" 
  --time-period Start="$LAST_MONTH_START",End="$LAST_MONTH_END" 
  --granularity MONTHLY 
  --metrics "BlendedCost" 
  --group-by Type=DIMENSION,Key=SERVICE 
  --output json | 
  jq -r '.ResultsByTime[0].Groups[] |
    select((.Metrics.BlendedCost.Amount | tonumber) > 0.01) |
    "(.Metrics.BlendedCost.Amount | tonumber | . * 100 | round / 100) USD - (.Keys[0])"' | 
  sort -rn | 
  head -10 | 
  awk '{printf "%-12s %sn", $1, substr($0, index($0,$3))}'

echo ""
echo "--- Environment Bazlı Kırılım ---"

aws ce get-cost-and-usage 
  --profile "$PROFILE" 
  --time-period Start="$LAST_MONTH_START",End="$LAST_MONTH_END" 
  --granularity MONTHLY 
  --metrics "BlendedCost" 
  --group-by Type=TAG,Key=Environment 
  --output json | 
  jq -r '.ResultsByTime[0].Groups[] |
    "(.Keys[0]): (.Metrics.BlendedCost.Amount | tonumber | . * 100 | round / 100) USD"'

Bu script’i cron’a veya Systems Manager State Manager’a bağlayabilirsiniz. Lambda için Python veya Node.js versiyonunu da benzer mantıkla yazabilirsiniz.

Maliyet Tahmini Almak

Cost Explorer’ın tahmin özelliği de oldukça kullanışlı. Mevcut tüketim trendine göre ay sonunda ne ödeyeceğinizi hesaplar:

aws ce get-cost-forecast 
  --time-period Start=$(date +%Y-%m-%d),End=$(date -d "next month" +%Y-%m-01) 
  --metric BLENDED_COST 
  --granularity MONTHLY 
  --prediction-interval-level 95 
  --query '{
    Total: Total.Amount,
    LowerBound: ForecastResultsByTime[0].PredictionIntervalLowerBound,
    UpperBound: ForecastResultsByTime[0].PredictionIntervalUpperBound
  }' 
  --output json

Bu komut size hem tahmini tutarı hem de yüzde 95 güven aralığıyla alt ve üst sınırları verir. Bütçe planlaması için bu değerleri düzenli olarak takip etmek çok işe yarıyor.

Budget Alarm’larla Entegrasyon

Cost Explorer’ı Budgets servisiyle birlikte kullanmak maliyet yönetiminin temel taşı. Belirli bir eşiği geçtiğinde alarm üretmek için:

aws budgets create-budget 
  --account-id "$(aws sts get-caller-identity --query Account --output text)" 
  --budget '{
    "BudgetName": "Monthly-EC2-Budget",
    "BudgetLimit": {
      "Amount": "500",
      "Unit": "USD"
    },
    "TimeUnit": "MONTHLY",
    "BudgetType": "COST",
    "CostFilters": {
      "Service": ["Amazon Elastic Compute Cloud - Compute"]
    }
  }' 
  --notifications-with-subscribers '[
    {
      "Notification": {
        "NotificationType": "ACTUAL",
        "ComparisonOperator": "GREATER_THAN",
        "Threshold": 80,
        "ThresholdType": "PERCENTAGE"
      },
      "Subscribers": [
        {
          "SubscriptionType": "EMAIL",
          "Address": "[email protected]"
        }
      ]
    }
  ]'

Bu komut EC2 için aylık 500 dolar bütçe kurar ve yüzde 80’ine ulaşıldığında e-posta gönderir. Farklı eşikler için birden fazla notification tanımlayabilirsiniz, mesela yüzde 80, yüzde 100 ve yüzde 110 için ayrı ayrı bildirim ayarlamak mantıklı.

Gerçek Dünya Senaryosu: Kullanılmayan Kaynakları Tespit Etme

Bir gün bir müşterinin hesabına baktım ve 3 aydır hiç trafik almayan ama çalışmaya devam eden bir ELB buldum. Aylık 20 dolar gibi görünse de bu yüzlerce kaynakta birikim yapınca ciddi bir rakama ulaşıyor. Cost Explorer bu tür kaynakları doğrudan göstermese de kullanım miktarına bakarak tespit edebilirsiniz:

# UsageQuantity 0'a yakın olan servis kullanımlarını bul
aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --metrics "BlendedCost" "UsageQuantity" 
  --group-by Type=DIMENSION,Key=USAGE_TYPE 
  --filter '{
    "Dimensions": {
      "Key": "SERVICE",
      "Values": ["AWS Elastic Load Balancing"]
    }
  }' 
  --output json | 
  jq -r '.ResultsByTime[0].Groups[] |
    select((.Metrics.BlendedCost.Amount | tonumber) > 0) |
    "Cost: (.Metrics.BlendedCost.Amount) | Usage: (.Metrics.UsageQuantity.Amount) | Type: (.Keys[0])"'

Bu tür analizleri AWS Trusted Advisor veya Compute Optimizer ile birlikte kullanmak daha güçlü sonuçlar veriyor. Cost Explorer maliyeti gösterir, Compute Optimizer neyin fazla provizyon edildiğini söyler.

Multi-Account Organizasyonlarda Maliyet Yönetimi

AWS Organizations kullanıyorsanız, maliyet raporlarınızı yönetim hesabı (management account) üzerinden çekebilirsiniz. Bu sayede tüm linked account’ların maliyetlerini tek yerden görebilirsiniz:

# Hesap bazlı kırılım
aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --metrics "BlendedCost" 
  --group-by Type=DIMENSION,Key=LINKED_ACCOUNT 
  --output json | 
  jq -r '.ResultsByTime[0].Groups[] |
    "(.Keys[0]): (.Metrics.BlendedCost.Amount | tonumber | . * 100 | round / 100) USD"' | 
  sort -t: -k2 -rn

Hesap ID’si yerine hesap adını görmek istiyorsanız AWS Organizations API ile join yapmanız gerekiyor. Bunu şöyle yapabilirsiniz:

#!/bin/bash
# Hesap ID'lerini isimleriyle eşleştir

declare -A ACCOUNT_NAMES

while IFS=$'t' read -r id name; do
  ACCOUNT_NAMES[$id]=$name
done < <(aws organizations list-accounts 
  --query 'Accounts[*].[Id, Name]' 
  --output text)

aws ce get-cost-and-usage 
  --time-period Start=2024-01-01,End=2024-01-31 
  --granularity MONTHLY 
  --metrics "BlendedCost" 
  --group-by Type=DIMENSION,Key=LINKED_ACCOUNT 
  --output json | 
  jq -r '.ResultsByTime[0].Groups[] | "(.Keys[0]) (.Metrics.BlendedCost.Amount | tonumber | . * 100 | round / 100)"' | 
  while read -r account_id cost; do
    account_name=${ACCOUNT_NAMES[$account_id]:-"Bilinmeyen"}
    echo "$account_name ($account_id): $cost USD"
  done | sort -t: -k2 -rn

Cost Explorer API Kullanım Limitleri ve İyi Pratikler

API’yi kullanırken dikkat etmeniz gereken bazı noktalar var:

  • Her API isteği 0.01 USD tutar. Script’leri sık çalıştırıyorsanız bu maliyet birikebilir. Sonuçları cache’leyin.
  • Veri gecikmesi: Maliyet verileri 24 saate kadar gecikebilir. “Bugün” için gerçek zamanlı veri beklemeyin.
  • Throttling: API rate limiti hesap başına oldukça makul ama yoğun sorgu yapıyorsanız exponential backoff implementasyonu ekleyin.
  • Tarih aralıkları: End tarihi bugünün tarihi veya öncesi olmalı. Gelecek tarihler için tahmin API’sini kullanın.
  • Tag aktivasyonu: Yeni oluşturulan tag’ler Cost Explorer’da görünür hale gelmesi 24 saat sürebilir. Tag stratejinizi en baştan planlayın.
  • Granülarite sınırları: Saatlik granülarite sadece son 14 gün için kullanılabilir.

Maliyet Görünürlüğü için Dashboard Kurulumu

Birçok ekip Cost Explorer verilerini Grafana veya benzeri araçlara taşımak istiyor. Bunun için en temiz yol Cost and Usage Report (CUR) dosyalarını S3’e atmak ve Athena üzerinden sorgulamaktır. Ama hızlı bir görünürlük için CloudWatch Custom Metrics ile basit bir çözüm de yapılabilir:

#!/bin/bash
# cost-to-cloudwatch.sh
# Günlük maliyeti CloudWatch'a custom metric olarak yaz

YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
TODAY=$(date +%Y-%m-%d)

DAILY_COST=$(aws ce get-cost-and-usage 
  --time-period Start="$YESTERDAY",End="$TODAY" 
  --granularity DAILY 
  --metrics "UnblendedCost" 
  --query 'ResultsByTime[0].Total.UnblendedCost.Amount' 
  --output text)

aws cloudwatch put-metric-data 
  --namespace "Custom/AWSCosts" 
  --metric-name "DailyTotalCost" 
  --value "$DAILY_COST" 
  --unit "None" 
  --dimensions Name=Account,Value="$(aws sts get-caller-identity --query Account --output text)"

echo "Maliyet metrigi CloudWatch'a yazildi: $DAILY_COST USD"

Bu script’i Systems Manager ile günlük çalıştırıp CloudWatch dashboard’unda maliyet trendini takip edebilirsiniz. Alarm da kurarsanız anormal artışlarda anında haberdar olursunuz.

Sonuç

AWS Cost Explorer, başlangıçta sadece fatura kontrolü için kullanılan bir araç gibi görünse de doğru kullanıldığında proaktif maliyet yönetiminin temel taşına dönüşüyor. Tag stratejisi olmadan bu araçtan alacağınız değer sınırlı kalır, bu yüzden önce kaynak etiketleme standardınızı oturtun. Sonrasında CLI ve API entegrasyonlarıyla maliyet raporlarını otomatize edin, Anomaly Detection’ı aktive edin ve Budget Alarm’larınızı kurun.

Unutmayın, bulutta maliyet optimizasyonu tek seferlik bir proje değil, sürekli bir pratik. Her ay maliyet trendlerinize bakma alışkanlığı edinin, büyük harcama kalemlerini sorgulayın ve kullanılmayan kaynakları düzenli olarak temizleyin. Bu alışkanlıkları otomasyonla desteklediğinizde, ay sonu fatura sürprizleri tarih olacak.

Bir yanıt yazın

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