Spot ve Preemptible Instance Kullanım Stratejileri
Bulut maliyetlerini düşürmenin en etkili yollarından biri, spot ve preemptible instance’ları akıllıca kullanmak. Ancak bu instance türlerini “ucuz diye açtım, çalıştı mı çalıştı” mantığıyla kullanırsanız, gecenin bir yarısı production sisteminizin çöktüğünü görürsünüz. Yıllar içinde edindiğim deneyimlere göre bu instance türlerini doğru stratejiyle kullanmak, AWS ya da GCP faturanızı %60-70 oranında düşürebilir. Ama yanlış kullanmak da o kadar kolay.
Spot ve Preemptible Instance Nedir, Ne Değildir?
Önce kavramları netleştirelim. AWS Spot Instance, Amazon’un kullanılmayan EC2 kapasitesini açık artırmayla (artık sabit fiyatla) sunduğu, normal fiyatın %90’a kadar altında olan instance türüdür. Google Cloud Preemptible VM ise benzer mantıkla çalışan, maksimum 24 saat çalışabilen ve Google’ın ihtiyaç duyduğunda 30 saniyelik uyarıyla sonlandırabileceği sanal makinelerdir. Azure’da bu konseptin karşılığı Spot Virtual Machines olarak geçiyor.
Bu instance’ların ortak özelliği şu: kapasite sağlayıcı bunları geri alabilir. Bu yüzden stateful, uzun süreli ve kesintiye tahammülü olmayan işler için bu instance türlerini kullanmak felakete davetiye çıkarmaktır.
Peki ne için kullanılabilir?
- Batch işleme ve veri pipeline’ları
- CI/CD build worker’ları
- Makine öğrenmesi model eğitimi (checkpoint’li)
- Video/resim işleme görevleri
- Web crawling ve scraping işleri
- Stateless mikro servis katmanları (uygun mimaride)
- Test ortamları
AWS Spot Instance Stratejileri
Instance Fleet ile Çeşitlendirme
Tek bir instance türüne bağlı kalmak, spot kullanımında yapılan en büyük hatalardan biri. AWS, instance fleet özelliğiyle birden fazla instance tipi ve availability zone kombinasyonu belirlemenize olanak tanıyor. Böylece m5.xlarge kesildiğinde fleet otomatik olarak m5a.xlarge ya da m4.xlarge‘a geçiş yapıyor.
# Spot Fleet isteği oluşturma
aws ec2 request-spot-fleet
--spot-fleet-request-config '{
"IamFleetRole": "arn:aws:iam::123456789:role/SpotFleetRole",
"TargetCapacity": 10,
"AllocationStrategy": "diversified",
"LaunchSpecifications": [
{
"ImageId": "ami-0abcdef1234567890",
"InstanceType": "m5.xlarge",
"SubnetId": "subnet-11111111"
},
{
"ImageId": "ami-0abcdef1234567890",
"InstanceType": "m5a.xlarge",
"SubnetId": "subnet-22222222"
},
{
"ImageId": "ami-0abcdef1234567890",
"InstanceType": "m4.xlarge",
"SubnetId": "subnet-33333333"
}
]
}'
diversified stratejisi, kapasiteyi farklı pool’lara dağıtıyor. lowestPrice stratejisi ise sadece en ucuz pool’u kullanıyor ama kesilme riskini artırıyor. Production benzeri ortamlarda her zaman diversified kullanın.
Interruption Notice’ı Yakalamak
AWS, bir spot instance’ı sonlandırmadan 2 dakika önce uyarı veriyor. Bu süreyi değerlendirmek hayat kurtarıcı. EC2 instance metadata servisinden bu uyarıyı polling ile yakalayabilirsiniz.
#!/bin/bash
# spot_monitor.sh - Spot interruption izleme scripti
METADATA_URL="http://169.254.169.254/latest/meta-data/spot/interruption-action"
CHECKPOINT_DIR="/var/checkpoints"
LOG_FILE="/var/log/spot_monitor.log"
check_interruption() {
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}"
--connect-timeout 2
"$METADATA_URL")
if [ "$HTTP_CODE" == "200" ]; then
echo "$(date): UYARI - Spot instance kesilecek!" >> "$LOG_FILE"
# Uygulamayı graceful shutdown için sinyal gönder
pkill -SIGTERM -f "myapp"
# Checkpoint kaydet
cp -r /var/app/state "$CHECKPOINT_DIR/$(date +%s)/"
# SQS kuyruğuna mesaj gönder (başka bir instance devam etsin)
aws sqs send-message
--queue-url "https://sqs.us-east-1.amazonaws.com/123456789/spot-failover"
--message-body '{"action": "resume", "checkpoint": "/checkpoints/latest"}'
echo "$(date): Checkpoint kaydedildi, failover başlatıldı" >> "$LOG_FILE"
fi
}
# Her 30 saniyede bir kontrol et
while true; do
check_interruption
sleep 30
done
Bu scripti systemd servisi olarak çalıştırın ve instance başladığında otomatik devreye girsin.
# /etc/systemd/system/spot-monitor.service
cat > /etc/systemd/system/spot-monitor.service << 'EOF'
[Unit]
Description=Spot Instance Interruption Monitor
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/spot_monitor.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable spot-monitor
systemctl start spot-monitor
Spot Price History Analizi
Hangi instance tipinin daha az kesildiğini anlamak için spot price history’yi analiz etmek gerekiyor. Fiyat dalgalanması az olan instance tipler, genellikle kesilme sıklığı da düşük olan tiplerdir.
# Son 7 günlük spot fiyat geçmişini çek
aws ec2 describe-spot-price-history
--instance-types m5.xlarge m5a.xlarge m4.xlarge
--product-descriptions "Linux/UNIX"
--start-time $(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%S)
--query 'SpotPriceHistory[*].{Type:InstanceType,AZ:AvailabilityZone,Price:SpotPrice,Time:Timestamp}'
--output json | python3 -c "
import json, sys
from collections import defaultdict
data = json.load(sys.stdin)
prices = defaultdict(list)
for item in data:
key = f"{item['Type']} / {item['AZ']}"
prices[key].append(float(item['Price']))
for combo, price_list in sorted(prices.items()):
avg = sum(price_list) / len(price_list)
variance = max(price_list) - min(price_list)
print(f'{combo}: Ort={avg:.4f}, Dalgalanma={variance:.4f}')
"
Google Cloud Preemptible VM Stratejileri
Preemptible VM ile Managed Instance Group
GCP’de preemptible instance kullanmanın en sağlam yolu, Managed Instance Group (MIG) ile birleştirmektir. MIG, sonlanan instance’ları otomatik yeniden başlatır.
# Instance template oluştur (preemptible ile)
gcloud compute instance-templates create spot-worker-template
--machine-type=n1-standard-4
--image-family=debian-11
--image-project=debian-cloud
--preemptible
--boot-disk-size=50GB
--metadata-from-file startup-script=startup.sh
--scopes=cloud-platform
# Managed Instance Group oluştur
gcloud compute instance-groups managed create spot-worker-group
--template=spot-worker-template
--size=5
--zone=us-central1-a
# Autoscaling ekle
gcloud compute instance-groups managed set-autoscaling spot-worker-group
--zone=us-central1-a
--min-num-replicas=2
--max-num-replicas=20
--target-cpu-utilization=0.7
--cool-down-period=60
Preemption Sinyalini Yakalamak
GCP’de preemption sinyali ACPI g2 soft-off eventi olarak geliyor. Bunu shutdown script ile yakalayabilirsiniz.
#!/bin/bash
# /etc/preemption-handler.sh
# GCP metadata'dan preemption uyarısını izle
METADATA_BASE="http://metadata.google.internal/computeMetadata/v1"
HEADERS="-H 'Metadata-Flavor: Google'"
# Preemption zamanını izle (long polling)
monitor_preemption() {
curl -s
-H "Metadata-Flavor: Google"
"${METADATA_BASE}/instance/preempted?wait_for_change=true&last_etag=0&timeout_sec=60"
local result=$?
if [ $result -eq 0 ]; then
echo "$(date): Preemption sinyali alındı!"
# Çalışan job'ı checkpoint'e al
if pgrep -f "training_job.py" > /dev/null; then
kill -USR1 $(pgrep -f "training_job.py")
sleep 10
fi
# Durumu GCS'e kaydet
gsutil -m cp -r /var/app/checkpoints gs://my-bucket/checkpoints/$(hostname)/
# Pub/Sub'a bildir
gcloud pubsub topics publish job-status
--message='{"status": "preempted", "host": "'"$(hostname)"'", "time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"}'
fi
}
while true; do
monitor_preemption
sleep 5
done
Karma Mimari: On-Demand + Spot/Preemptible
Tamamen spot tabanlı sistemler riskli olduğu için production’da karma mimari kullanmak en doğrusu. Minimum kapasiteyi on-demand ile karşılayıp, yük arttığında spot ile scale ediyorsunuz.
# AWS EKS için node group yapılandırması
# eksctl ile spot + on-demand karma cluster
cat > cluster-config.yaml << 'EOF'
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: production-cluster
region: us-east-1
nodeGroups:
# On-demand baseline (kritik servisler için)
- name: on-demand-baseline
instanceType: m5.xlarge
desiredCapacity: 3
minSize: 2
maxSize: 5
labels:
node-type: on-demand
taints:
- key: node-type
value: on-demand
effect: NoSchedule
# Spot worker pool (batch ve scale işleri için)
- name: spot-workers
instancesDistribution:
maxPrice: 0.08
instanceTypes:
- m5.xlarge
- m5a.xlarge
- m4.xlarge
- m5d.xlarge
onDemandBaseCapacity: 0
onDemandPercentageAboveBaseCapacity: 0
spotAllocationStrategy: diversified
desiredCapacity: 5
minSize: 0
maxSize: 50
labels:
node-type: spot
EOF
eksctl create cluster -f cluster-config.yaml
Kubernetes’te Spot Instance Yönetimi
Kubernetes ortamında spot kullanmak ayrı bir sanat. Pod’larınızı doğru şekilde yapılandırmazsanız, node kesildiğinde uzun süre recovery beklentisiyle karşılaşabilirsiniz.
Pod Disruption Budget ve Tolerations
# Spot node'lara tolerations ekle
cat > spot-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: batch-processor
spec:
replicas: 10
selector:
matchLabels:
app: batch-processor
template:
metadata:
labels:
app: batch-processor
spec:
# Spot node tercih et ama zorla değil
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: node-type
operator: In
values:
- spot
tolerations:
- key: "spot-instance"
operator: "Equal"
value: "true"
effect: "NoSchedule"
# Graceful shutdown için terminationGracePeriod
terminationGracePeriodSeconds: 90
containers:
- name: processor
image: myapp:latest
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"
# SIGTERM handler'ı aktif et
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10 && /app/graceful-shutdown.sh"]
---
# Pod Disruption Budget - minimum %50 hazır olsun
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: batch-processor-pdb
spec:
minAvailable: 5
selector:
matchLabels:
app: batch-processor
EOF
kubectl apply -f spot-deployment.yaml
AWS Node Termination Handler
Kubernetes cluster’ınızda AWS Node Termination Handler kurarak spot interruption event’lerini otomatik yönetebilirsiniz.
# Helm ile AWS Node Termination Handler kurulumu
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-node-termination-handler
eks/aws-node-termination-handler
--namespace kube-system
--set enableSpotInterruptionDraining=true
--set enableScheduledEventDraining=true
--set enableRebalanceMonitoring=true
--set enableSqsTerminationDraining=true
--set queueURL=https://sqs.us-east-1.amazonaws.com/123456789/nth-queue
--set logLevel=info
Maliyet Optimizasyonu: Gerçek Dünya Senaryosu
Bir e-ticaret müşterisinin video thumbnail oluşturma pipeline’ını spot instance’lara taşıdığımda yaşadıklarım iyi bir örnek. Önceki yapıda 10 adet c5.2xlarge on-demand instance 7/24 çalışıyordu. Aylık maliyet yaklaşık 2.800 dolar.
Yeni yapıda:
- 2 adet on-demand
c5.xlarge(koordinasyon ve SQS tüketici) - 8-20 adet spot
c5.2xlarge(iş yüküne göre auto-scale) - SQS kuyruğu (işler kaybolmasın diye)
- S3’te checkpoint mekanizması
Aylık maliyet: yaklaşık 750-900 dolar. Yüzde 68 tasarruf.
Burada kritik nokta şu: iş birimleri idempotent olmalı. Bir video işleme job’ı kesildiğinde, başka bir instance aynı job’ı alıp baştan başlatmalı ve sonuç aynı olmalı. Bunun için her video işinin durumunu DynamoDB’de tutuyorduk.
# DynamoDB'de job state yönetimi
# Job başladığında "processing" yap
aws dynamodb update-item
--table-name video-jobs
--key '{"job_id": {"S": "'$JOB_ID'"}}'
--update-expression "SET #s = :processing, worker_id = :wid, started_at = :ts"
--condition-expression "#s = :pending"
--expression-attribute-names '{"#s": "status"}'
--expression-attribute-values '{
":processing": {"S": "processing"},
":pending": {"S": "pending"},
":wid": {"S": "'$(hostname)'"},
":ts": {"S": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}
}'
--return-values NONE 2>/dev/null
# Eğer conditional check başarısız olduysa başka worker almış demek
if [ $? -ne 0 ]; then
echo "Job $JOB_ID başka bir worker tarafından alınmış, atlanıyor."
exit 0
fi
Spot Instance için Monitoring ve Alerting
Spot kesintilerini izlemek için CloudWatch Events kullanabilirsiniz. Bu sayede kaç tane kesinti yaşandığını, hangi instance tiplerinde sorun çıktığını takip edebilirsiniz.
# CloudWatch'a spot interruption metriği gönder
aws cloudwatch put-metric-data
--namespace "SpotInstances"
--metric-data '[
{
"MetricName": "InterruptionCount",
"Dimensions": [
{"Name": "InstanceType", "Value": "m5.xlarge"},
{"Name": "AvailabilityZone", "Value": "us-east-1a"}
],
"Value": 1,
"Unit": "Count"
}
]'
# Alarm kur: 1 saatte 3'ten fazla kesinti olursa uyar
aws cloudwatch put-metric-alarm
--alarm-name "SpotInterruptionHigh"
--alarm-description "Spot kesinti orani yuksek"
--metric-name "InterruptionCount"
--namespace "SpotInstances"
--statistic Sum
--period 3600
--threshold 3
--comparison-operator GreaterThanOrEqualToThreshold
--evaluation-periods 1
--alarm-actions arn:aws:sns:us-east-1:123456789:ops-alerts
Yaygın Hatalar ve Kaçınma Yolları
Tek AZ’de spot kullanmak: Bir availability zone’daki kapasite bittiğinde tüm spot instance’larınız kesilir. Her zaman çoklu AZ kullanın.
Stateful uygulamaları doğrudan spot’a taşımak: Veritabanı, cache veya oturum bilgisi tutan uygulamaları spot’a almadan önce state’i dışarı çıkarın. Redis, RDS, DynamoDB gibi managed servisler burada yardımcı olur.
Max price belirlememek: AWS spot’ta max fiyat belirlememek, beklenmedik maliyet artışlarına yol açabilir. Spot fiyatı on-demand fiyatına yaklaştığında ne yapacağınızı önceden belirleyin.
Checkpointing yapmadan uzun süren joblar çalıştırmak: 6 saatlik bir ML eğitimini checkpoint’siz spot’ta çalıştırmak riskli. En az 30 dakikada bir checkpoint alın.
Instance tipine çok bağımlı olmak: Belirli bir instance tipine özel optimizasyon yapmak (örneğin sadece AVX-512 için), farklı instance tipine fallback yaparken sorun çıkarır.
Hangi İş Yükleri İçin Kesinlikle Kullanmayın
- Primary veritabanları (okuma replikaları için düşünülebilir ama dikkatli olun)
- Real-time ödeme işleme sistemleri
- WebSocket bağlantıları tutan uygulamalar (bağlantı kopması kabul edilemez olan)
- Tek node’da çalışan kritik monitoring sistemleri
- License sunucuları (çoğu lisans sistemi instance değişikliğine duyarlıdır)
Sonuç
Spot ve preemptible instance’lar, doğru kullanıldığında bulut faturanızı dramatik biçimde düşüren güçlü araçlar. Ancak bu araçları kullanmak için uygulama mimarinizi buna göre tasarlamanız şart. Kesintilere dayanıklı, idempotent iş birimleri, düzgün checkpoint mekanizmaları ve çoklu instance tipi stratejileri olmadan spot kullanmak, zaman kazanmak yerine zaman kaybettirir.
Başlangıç için şu adımları takip edin: önce mevcut iş yüklerinizi analiz edin ve hangilerinin kesintiye toleranslı olduğunu belirleyin, batch ve CI/CD pipeline’larından başlayın, monitoring ve alerting kurun, ardından yavaş yavaş daha fazla iş yükünü spot’a taşıyın. Acele etmeyin, her adımda ne kadar tasarruf ettiğinizi ve kaç kesinti yaşadığınızı ölçün. Zaman içinde hangi kombinasyonun sizin iş yükleri için en iyi çalıştığını göreceksiniz.
