Настройка Spot/Preemptible Instances для batch-задач
Spot Instances (AWS) и Preemptible VMs (GCP) — облачные ресурсы с дополнительной ёмкостью провайдера по цене 60-90% ниже on-demand. Обратная сторона: могут быть принудительно остановлены с уведомлением за 2 минуты. Это не проблема для batch-задач, которые умеют перезапускаться.
Подходящие workloads для Spot
Хорошо подходит:
- CI/CD воркеры (каждый билд — отдельная задача)
- Обработка изображений и видео (transcoding, resize)
- ML training (checkpoint-based)
- Парсинг и ETL-пайплайны
- Рендеринг
- Антивирусные сканы, аналитические запросы
Не подходит:
- Stateful базы данных (критические данные)
- Web-серверы без быстрого замещения
- Сервисы с жёсткими SLA и отсутствием DR
AWS Spot Instances: практика
Spot Fleet с несколькими типами инстансов — ключ к стабильности. Если m5.xlarge недоступен в одном AZ, Fleet берёт m4.xlarge или c5.xlarge в другом:
{
"SpotFleetRequestConfig": {
"AllocationStrategy": "capacityOptimized",
"TargetCapacity": 10,
"LaunchTemplateConfigs": [
{
"LaunchTemplateSpecification": {"LaunchTemplateId": "lt-xxx", "Version": "1"},
"Overrides": [
{"InstanceType": "m5.xlarge", "WeightedCapacity": 1},
{"InstanceType": "m5a.xlarge", "WeightedCapacity": 1},
{"InstanceType": "m4.xlarge", "WeightedCapacity": 1},
{"InstanceType": "c5.xlarge", "WeightedCapacity": 1}
]
}
]
}
}
Стратегия capacityOptimized снижает вероятность прерывания выбирая пулы с наибольшей доступной ёмкостью.
Обработка Spot Interruption Notice
За 2 минуты до остановки AWS отправляет instance metadata event. Приложение должно перехватить и gracefully завершить задачу:
import requests
import signal
import sys
def check_spot_interruption():
"""Вызывать каждые 5 секунд из воркера"""
try:
response = requests.get(
'http://169.254.169.254/latest/meta-data/spot/interruption-notice',
timeout=1
)
if response.status_code == 200:
return True # Прерывание ожидается
except requests.exceptions.RequestException:
pass
return False
class BatchWorker:
def process_task(self, task):
# Checkpoint каждые N элементов
for i, item in enumerate(task.items):
if i % 100 == 0 and check_spot_interruption():
self.save_checkpoint(task.id, i)
sys.exit(0) # Graceful exit, задача будет перезапущена
self.process_item(item)
task.mark_complete()
AWS EventBridge для Spot Interruption
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Spot Instance Interruption Warning"],
"detail": {
"instance-action": ["terminate"]
}
}
EventBridge → Lambda → сохранить checkpoint + убрать инстанс из пула + поставить задачу обратно в очередь.
Kubernetes с Spot Nodes
Karpenter (AWS) автоматически выбирает тип инстанса (в том числе Spot) и обрабатывает прерывания:
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: batch-workers
spec:
requirements:
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot", "on-demand"]
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["m5.xlarge", "m5a.xlarge", "m4.xlarge", "c5.xlarge"]
taints:
- key: batch
effect: NoSchedule
consolidation:
enabled: true
При Spot Interruption Karpenter cordon + drain ноду, поды перепланируются на другие узлы.
GCP Preemptible / Spot VMs
GCP Preemptible: максимум 24 часа жизни + уведомление за 30 секунд (в 15 раз меньше, чем AWS). Spot VMs: без лимита 24 часа, только по availability.
gcloud compute instances create batch-worker \
--machine-type=n2-standard-4 \
--provisioning-model=SPOT \
--instance-termination-action=STOP \
--zone=us-central1-a
Эффективность и сбережения
Реальные примеры:
- CI/CD пайплайн: переход с on-demand t3.xlarge на Spot → экономия 70%
- ML training на Spot p3.2xlarge: $0.918/час вместо $3.06/час
Overhead от прерываний и перезапусков: обычно 5-15% дополнительного времени. Итоговая экономия: 60-80% при грамотной реализации checkpoint.
Сроки настройки
- Spot Fleet / Launch Template — 1-2 дня
- Interruption handling в приложении — 2-3 дня
- Kubernetes Karpenter с Spot — 2-3 дня
- Тестирование симуляцией прерывания — 1 день







