AWS EC2 Spot Instance Kullanımı: Maliyet Optimizasyonu İçin Kapsamlı Rehber
Bulut maliyetleri her zaman sysadmin’lerin kafasını karıştıran konulardan biri olmuştur. EC2 On-Demand fiyatlarına bakınca insanın içi sıkışıyor, Reserved Instance almak için yöneticiye gitmek gerekiyor, ama ortada Spot Instance diye bir şey var ki doğru kullanılınca maliyeti yüzde seksene kadar düşürebiliyorsun. Bu yazıda Spot Instance’ın ne olduğunu, nasıl çalıştığını ve gerçek dünya senaryolarında nasıl kullanabileceğini anlatacağım.
Spot Instance Nedir, Neden Bu Kadar Ucuz?
AWS’nin veri merkezlerinde her an boşta duran kapasiteler var. Bu kapasite kullanılmadığında AWS için saf maliyet. İşte Spot Instance tam da bu atıl kapasiteyi piyasaya sürmek için tasarlanmış bir mekanizma. AWS, bu kapasiteyi anlık fiyatlarla satıyor ve sen teklif veriyorsun. Eğer spot fiyatı senin belirlediğin maksimum fiyatın altındaysa instance çalışıyor, üstüne çıkarsa AWS sana 2 dakika uyarı vererek instance’ını kapatıyor.
Bu “kapatılabilir” özellik kulağa ürkütücü geliyor, değil mi? Ama işin özü şu: doğru iş yükleri için Spot Instance neredeyse mükemmel bir çözüm. Yanlış iş yükleri için ise gerçek bir felaket tarifi.
Spot fiyatları instance tipine, region’a ve availability zone’a göre değişiyor. Örneğin m5.xlarge için us-east-1a’da spot fiyatı on-demand’ın yüzde yirmisi olabilirken, aynı anda eu-west-1b’de yüzde kırkına çıkabiliyor. Bu dinamik yapıyı anlamak, Spot Instance kullanımının temel taşı.
Hangi İş Yükleri İçin Uygun?
Spot Instance’ı her yerde kullanamazsın. Önce uygun iş yüklerini tanımlamak lazım.
Uygun iş yükleri:
- Batch processing işleri (veri dönüşümleri, ETL pipeline’ları)
- CI/CD pipeline worker’ları
- Makine öğrenimi model eğitimi
- Video transcoding, render işleri
- Büyük veri analizi (Spark, Hadoop kümeleri)
- Stateless web uygulamaları (load balancer arkasında)
- Test ve geliştirme ortamları
Uygun olmayan iş yükleri:
- Tek instance üzerinde çalışan veritabanları
- State tutması gereken uygulamalar
- Uzun süreli session yöneten sistemler
- Production’da tek nokta olan kritik servisler
Temel kural şu: Bir instance aniden kapansa işin kırılmayacaksa Spot kullan, kırılacaksa kullanma veya çok dikkatli kullan.
AWS CLI ile Spot Instance Başlatmak
Hadi pratik kısma geçelim. Önce basit bir Spot Instance ayağa kaldıralım:
# Mevcut spot fiyatlarını öğren
aws ec2 describe-spot-price-history
--instance-types m5.xlarge
--product-descriptions "Linux/UNIX"
--start-time $(date -u +%Y-%m-%dT%H:%M:%S)
--region us-east-1
--query 'SpotPriceHistory[*].[AvailabilityZone,SpotPrice]'
--output table
# Spot Instance request oluştur
aws ec2 request-spot-instances
--instance-count 1
--type "one-time"
--launch-specification '{
"ImageId": "ami-0c55b159cbfafe1f0",
"InstanceType": "m5.xlarge",
"KeyName": "my-key-pair",
"SecurityGroupIds": ["sg-0a1b2c3d4e5f6789"],
"SubnetId": "subnet-0abc123def456789",
"IamInstanceProfile": {
"Name": "my-instance-profile"
}
}'
--spot-price "0.08"
--region us-east-1
Burada --spot-price parametresi maksimum ödemeye razı olduğun saatlik fiyat. Günümüzde AWS bu değeri belirlemeyi zorunlu tutmuyor, belirlemezsen on-demand fiyatı otomatik olarak maksimum kabul ediliyor. Ama yine de mantıklı bir üst sınır koymak bütçe koruması açısından iyi bir alışkanlık.
Spot Fleet: Gerçek Güç Burada
Tek Spot Instance kullanmak işe yarasa da asıl güç Spot Fleet’te. Spot Fleet, birden fazla instance tipi ve availability zone kombinasyonunu aynı anda hedefleyerek kapasite bulunamama riskini büyük ölçüde azaltıyor.
# Spot Fleet konfigürasyon dosyası oluştur
cat > spot-fleet-config.json << 'EOF'
{
"IamFleetRole": "arn:aws:iam::123456789012:role/aws-ec2-spot-fleet-tagging-role",
"AllocationStrategy": "diversified",
"TargetCapacity": 10,
"SpotPrice": "0.15",
"LaunchSpecifications": [
{
"ImageId": "ami-0c55b159cbfafe1f0",
"InstanceType": "m5.xlarge",
"SubnetId": "subnet-0abc123def456789",
"WeightedCapacity": 1
},
{
"ImageId": "ami-0c55b159cbfafe1f0",
"InstanceType": "m5a.xlarge",
"SubnetId": "subnet-0abc123def456789",
"WeightedCapacity": 1
},
{
"ImageId": "ami-0c55b159cbfafe1f0",
"InstanceType": "m4.xlarge",
"SubnetId": "subnet-0bcd234ef567890",
"WeightedCapacity": 1
},
{
"ImageId": "ami-0c55b159cbfafe1f0",
"InstanceType": "r5.large",
"SubnetId": "subnet-0cde345fg678901",
"WeightedCapacity": 1
}
],
"Type": "maintain"
}
EOF
# Fleet'i başlat
aws ec2 request-spot-fleet
--spot-fleet-request-config file://spot-fleet-config.json
--region us-east-1
AllocationStrategy için üç seçenek var:
- lowestPrice: En ucuz instance’ları hedefler, interrupt riski yüksek
- diversified: Kapasiteyi pool’lar arasında dağıtır, daha stabil
- capacityOptimized: En fazla kapasitesi olan pool’ları tercih eder, interrupt riski düşük
Production sistemlerde genellikle capacityOptimized veya diversified kullanmak daha mantıklı. Birkaç kuruş daha fazla ödesen bile interrupt edilme ihtimalin dramatik biçimde düşüyor.
Interrupt Bildirimine Hazırlanmak
Spot Instance’ın en kritik konusu interrupt yönetimi. AWS seni 2 dakika önceden uyarıyor, bu süre içinde graceful shutdown yapman gerekiyor. Instance metadata service üzerinden bu sinyali yakalayabilirsin.
#!/bin/bash
# /usr/local/bin/spot-interrupt-handler.sh
# Bu script instance üzerinde çalışır, metadata endpoint'ini dinler
METADATA_URL="http://169.254.169.254/latest/meta-data/spot/termination-time"
LOG_FILE="/var/log/spot-interrupt.log"
SHUTDOWN_SCRIPT="/usr/local/bin/graceful-shutdown.sh"
echo "$(date): Spot interrupt handler başlatıldı" >> $LOG_FILE
while true; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}"
--connect-timeout 2
$METADATA_URL)
if [ "$HTTP_CODE" -eq 200 ]; then
TERMINATION_TIME=$(curl -s $METADATA_URL)
echo "$(date): UYARI! Instance sonlandırılacak: $TERMINATION_TIME" >> $LOG_FILE
# Devam eden işleri durdur, checkpoint al
if [ -f "$SHUTDOWN_SCRIPT" ]; then
echo "$(date): Graceful shutdown başlatılıyor..." >> $LOG_FILE
bash $SHUTDOWN_SCRIPT
fi
# SQS kuyruğuna mesaj gönder (opsiyonel)
aws sqs send-message
--queue-url "https://sqs.us-east-1.amazonaws.com/123456789012/spot-interrupts"
--message-body "{"instance_id": "$(curl -s http://169.254.169.254/latest/meta-data/instance-id)", "time": "$TERMINATION_TIME"}"
--region us-east-1
break
fi
# Her 5 saniyede bir kontrol et
sleep 5
done
Bu script’i systemd service olarak çalıştırmak en temiz yöntem:
# /etc/systemd/system/spot-interrupt-handler.service
cat > /etc/systemd/system/spot-interrupt-handler.service << 'EOF'
[Unit]
Description=Spot Instance Interrupt Handler
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/spot-interrupt-handler.sh
Restart=always
RestartSec=10
StandardOutput=append:/var/log/spot-interrupt.log
StandardError=append:/var/log/spot-interrupt.log
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable spot-interrupt-handler
systemctl start spot-interrupt-handler
EC2 Auto Scaling ile Spot Entegrasyonu
Gerçek dünya senaryolarında Spot Instance’ları genellikle Auto Scaling Group ile kullanırsın. AWS’nin Mixed Instances Policy özelliği burada işini çok kolaylaştırıyor.
# Mixed instances policy ile Auto Scaling Group oluştur
aws autoscaling create-auto-scaling-group
--auto-scaling-group-name "web-app-asg"
--min-size 2
--max-size 20
--desired-capacity 4
--vpc-zone-identifier "subnet-0abc123,subnet-0def456,subnet-0ghi789"
--mixed-instances-policy '{
"LaunchTemplate": {
"LaunchTemplateSpecification": {
"LaunchTemplateId": "lt-0abc123def456789",
"Version": "$Latest"
},
"Overrides": [
{"InstanceType": "m5.xlarge"},
{"InstanceType": "m5a.xlarge"},
{"InstanceType": "m4.xlarge"},
{"InstanceType": "m5n.xlarge"},
{"InstanceType": "m5d.xlarge"}
]
},
"InstancesDistribution": {
"OnDemandBaseCapacity": 2,
"OnDemandPercentageAboveBaseCapacity": 20,
"SpotAllocationStrategy": "capacity-optimized"
}
}'
--health-check-type "ELB"
--health-check-grace-period 300
Bu konfigürasyonda ne oluyor:
- OnDemandBaseCapacity: 2 ile minimum 2 On-Demand instance her zaman ayakta kalıyor
- Bunun üzerine çıkılan kapasitenin yüzde yirmisi On-Demand, kalanı Spot oluyor
- Beş farklı instance tipi tanımlanıyor, kapasite bulunabilirliği maksimuma çıkıyor
Bu strateji ile hem maliyet tasarrufu yapıyorsun hem de minimum bir stabilite garantisi elde ediyorsun.
Gerçek Dünya Senaryosu: Batch İşlem Sistemi
Şimdi somut bir örneğe bakalım. Diyelim ki her gece büyük log dosyalarını işleyen bir sistemin var. Bu iş her gece başlıyor, 3-4 saat sürüyor ve tamamlanması kritik değil (yani bir sonraki gece yeniden çalışabilir). Spot için biçilmiş kaftan.
#!/bin/bash
# batch-job-launcher.sh
# Bu script batch işi başlatır ve Spot'u akıllıca kullanır
REGION="us-east-1"
JOB_QUEUE_URL="https://sqs.us-east-1.amazonaws.com/123456789012/batch-jobs"
S3_CHECKPOINT_BUCKET="my-batch-checkpoints"
INSTANCE_TYPES=("c5.2xlarge" "c5a.2xlarge" "c4.2xlarge" "m5.2xlarge")
# Checkpoint kontrolü: İş daha önce yarıda kaldı mı?
check_checkpoint() {
local job_id=$1
aws s3 ls "s3://${S3_CHECKPOINT_BUCKET}/checkpoints/${job_id}/" 2>/dev/null
return $?
}
# İşi SQS'e koy
submit_job() {
local job_id=$(uuidgen)
local payload='{
"job_id": "'$job_id'",
"input_s3": "s3://my-data-bucket/raw/",
"output_s3": "s3://my-data-bucket/processed/",
"checkpoint_enabled": true,
"max_runtime_minutes": 240
}'
aws sqs send-message
--queue-url $JOB_QUEUE_URL
--message-body "$payload"
--region $REGION
echo "Job gönderildi: $job_id"
}
# Spot Fleet'i başlat
launch_spot_fleet() {
local capacity=$1
aws ec2 request-spot-fleet
--spot-fleet-request-config '{
"IamFleetRole": "arn:aws:iam::123456789012:role/spot-fleet-role",
"AllocationStrategy": "capacityOptimized",
"TargetCapacity": '$capacity',
"Type": "request",
"ValidUntil": "'$(date -u -d "+6 hours" +%Y-%m-%dT%H:%M:%SZ)'",
"LaunchSpecifications": [
{
"ImageId": "ami-0c55b159cbfafe1f0",
"InstanceType": "c5.2xlarge",
"SubnetId": "subnet-0abc123def456789",
"UserData": "'$(base64 -w0 /tmp/batch-worker-userdata.sh)'"
},
{
"ImageId": "ami-0c55b159cbfafe1f0",
"InstanceType": "c5a.2xlarge",
"SubnetId": "subnet-0bcd234ef567890"
}
]
}'
--region $REGION
}
# Ana akış
echo "Batch sistemi başlatılıyor..."
submit_job
launch_spot_fleet 5
echo "Fleet başlatıldı, işler sıraya alındı."
Maliyet İzleme ve Optimizasyon
Spot kullanıyorsun ama maliyetleri takip etmiyorsan yarısını kaçırıyorsun demektir. CloudWatch ile temel maliyet izlemeyi şöyle kurabilirsin:
# Spot Instance kesintilerini izlemek için CloudWatch alarm
aws cloudwatch put-metric-alarm
--alarm-name "SpotInterruptionRate"
--alarm-description "Spot instance kesinti oranı yüksek"
--metric-name "SpotInterruptions"
--namespace "AWS/EC2Spot"
--statistic Sum
--period 3600
--threshold 5
--comparison-operator GreaterThanThreshold
--evaluation-periods 1
--alarm-actions "arn:aws:sns:us-east-1:123456789012:ops-alerts"
--region us-east-1
# Spot savings raporunu çek
aws ce get-savings-plans-utilization
--time-period Start=$(date -d "-30 days" +%Y-%m-%d),End=$(date +%Y-%m-%d)
--region us-east-1
# Son 24 saatlik Spot harcamalarını görüntüle
aws ce get-cost-and-usage
--time-period Start=$(date -d "-1 day" +%Y-%m-%d),End=$(date +%Y-%m-%d)
--granularity DAILY
--filter '{
"Dimensions": {
"Key": "PURCHASE_TYPE",
"Values": ["Spot"]
}
}'
--metrics "BlendedCost"
--region us-east-1
Instance Selector ile Doğru Tipi Bulmak
AWS’nin ec2-instance-selector aracı, gereksinimlerine göre en uygun instance tiplerini bulmanı sağlıyor. Bu araç birden fazla instance tipi tanımlamak için altın değerinde.
# ec2-instance-selector kurulumu (Linux)
curl -Lo ec2-instance-selector
https://github.com/aws/amazon-ec2-instance-selector/releases/latest/download/ec2-instance-selector-linux-amd64
chmod +x ec2-instance-selector
sudo mv ec2-instance-selector /usr/local/bin/
# 4 vCPU, 8GB RAM istiyorum, spot uyumlu instance'ları listele
ec2-instance-selector
--vcpus 4
--memory 8
--usage-class spot
--region us-east-1
--output table-wide
# CPU mimarisi ve network performansına göre filtrele
ec2-instance-selector
--vcpus-min 4
--vcpus-max 8
--memory-min 16
--memory-max 32
--network-performance 10
--usage-class spot
--region eu-west-1
Bu araç Spot Fleet veya Auto Scaling Group için instance tipi listesi oluştururken çok işe yarıyor. Çıktıyı alıp direkt JSON konfigürasyonuna yapıştırabiliyorsun.
Spot ile Kubernetes: Karpenter Entegrasyonu
EKS üzerinde Kubernetes çalıştırıyorsan Karpenter ile Spot entegrasyonu gerçekten etkileyici sonuçlar veriyor.
# Karpenter NodePool tanımı - Spot öncelikli
cat > karpenter-nodepool.yaml << 'EOF'
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: spot-workers
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: node.kubernetes.io/instance-type
operator: In
values:
- m5.xlarge
- m5a.xlarge
- m5n.xlarge
- m4.xlarge
- m5d.xlarge
- c5.xlarge
- c5a.xlarge
nodeClassRef:
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
name: default
limits:
cpu: 1000
memory: 1000Gi
disruption:
consolidationPolicy: WhenUnderutilized
consolidateAfter: 30s
expireAfter: 720h
EOF
kubectl apply -f karpenter-nodepool.yaml
Karpenter, spot interruption’ı otomatik olarak yönetiyor. Instance kapatılma bildirimi geldiğinde pod’ları başka node’lara taşıyor, yeni Spot Instance bulup oraya schedule ediyor. İnsan müdahalesine gerek kalmıyor.
Sık Yapılan Hatalar
Birkaç yılda gördüğüm en yaygın spot hatalarını özetleyeyim:
- Tek AZ, tek instance tipi kullanmak: Kapasite bitince tüm fleet çöküyor. Mutlaka birden fazla AZ ve instance tipi tanımla
- Checkpoint olmadan uzun işler çalıştırmak: 4 saatlik bir iş 3. saatte kesilirse baştan başlamak çok can sıkıcı. Her işi checkpoint destekli yaz
- Stateful uygulamaları Spot’a koymak: Session verisi, local disk verisi, in-memory cache gibi şeyler Spot üzerinde kaybolabilir
- On-demand yerine Spot’u veritabanı için kullanmak: RDS yerine EC2 üzerinde kendi veritabanını çalıştırıyorsan ve bu Spot ise gerçek veri kaybı yaşayabilirsin
- Interrupt handler yazmamak: 2 dakika uyarı alıyorsun ama onu değerlendirmiyorsan fırsatı harcıyorsun
- Sadece en ucuz pool’a odaklanmak: lowestPrice stratejisi interrupt riskini artırır, capacityOptimized çoğu zaman daha iyi tercih
Sonuç
Spot Instance, doğru senaryolarda kullanıldığında AWS maliyetlerini dramatik biçimde aşağı çekebilen güçlü bir araç. Özellikle CI/CD işleri, batch processing, makine öğrenimi eğitimi ve stateless web uygulamaları için neredeyse ideal bir çözüm sunuyor.
Önemli olan birkaç temel kural var: Birden fazla instance tipi ve AZ kullan, interrupt handler mutlaka yaz, uzun süren işleri checkpoint destekli hale getir ve On-Demand base capacity ile kritik bir minimum garanti et. Bu kuralları uygularsan hem cebinde para kalır hem de gece 3’te uyandıran alarmlara maruz kalmazsın.
Başlamak için küçük adım at. Önce test ortamını Spot’a geçir, sonra CI/CD worker’larını taşı, ardından batch işlerini ekle. Bir süre izle, metrikleri gör, güven kazan. Sonra daha fazlasını taşıyabilirsin. Spot Instance kullanımı bir tercih meselesi değil, bulut olgunluğunun göstergesi haline geldi. Rakipleriniz büyük ihtimalle bu oyunu çoktan oynuyor.
