Skip to content

Spot Pods và Extended Duration Pods

Spot Pods trong Autopilot

Khái niệm và cơ chế

Spot Pods là cách để chạy Autopilot workloads trên Spot VMs — máy ảo có thể bị Compute Engine reclaim bất cứ lúc nào khi cần capacity cho Standard VMs. Đổi lại, bạn được giảm giá đáng kể.

Điểm khác biệt quan trọng: trong Standard clusters, bạn phải tự tạo node pool dùng Spot VMs và cấu hình tolerations. Trong Autopilot, chỉ cần thêm một nodeSelector và Autopilot tự xử lý mọi thứ:

yaml
spec:
  nodeSelector:
    cloud.google.com/gke-spot: "true"
  # Autopilot tự động thêm taint và toleration cho Spot
  containers:
  - name: app
    resources:
      requests:
        cpu: "2"
        memory: "4Gi"

Khi bạn request Spot Pod, Autopilot:

  1. Tự động provision Spot VM phù hợp
  2. Thêm taint cloud.google.com/gke-spot=true:NoSchedule vào node
  3. Thêm toleration tương ứng vào Pod
  4. Quản lý autoscaling và rescheduling khi node bị reclaim

Preemption behavior

Khi nào Spot VM bị reclaim: Compute Engine gửi preemption signal khi cần capacity cho Standard workloads hoặc khi Spot supply thấp. Không có cảnh báo trước và không có schedule — có thể xảy ra bất kỳ lúc nào.

Trình tự shutdown:

Compute Engine → gửi preemption notice

       ▼ (ngay lập tức)
GKE nhận notice → bắt đầu graceful termination

       ▼ (countdown bắt đầu)
SIGTERM gửi đến containers trong Pod

       ▼ (tối đa terminationGracePeriodSeconds)
SIGKILL nếu container chưa thoát


Compute Engine reclaim VM

Grace period cho Spot Pods: Tối đa 25 giây cho terminationGracePeriodSeconds khi node bị reclaim do preemption. Ngay cả khi bạn set terminationGracePeriodSeconds: 3600, GKE chỉ cho phép 25 giây trên Spot nodes.

Đây là constraint cứng: workloads cần cleanup phức tạp (flush buffer, save checkpoint, deregister từ service discovery) phải hoàn thành trong 25 giây.

yaml
spec:
  terminationGracePeriodSeconds: 25  # Maximum cho Spot Pods
  nodeSelector:
    cloud.google.com/gke-spot: "true"
  containers:
  - name: app
    lifecycle:
      preStop:
        exec:
          command: ["/bin/sh", "-c", "flush-data && deregister && sleep 5"]

Spot Pods và PodDisruptionBudget

PDB (PodDisruptionBudget) không bảo vệ Spot Pods khỏi preemption. PDB chỉ áp dụng cho voluntary disruptions — các disruptions do cluster operator hoặc Kubernetes kiểm soát (như node draining trong upgrade).

Preemption từ Compute Engine là involuntary disruption — nằm ngoài tầm kiểm soát của Kubernetes, và GKE sẽ preempt Spot Pods bất kể PDB nói gì.

yaml
# PDB này KHÔNG bảo vệ Spot Pods khỏi preemption
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: my-app

Implication cho production: Nếu chạy Spot Pods cho workload cần high availability, bạn phải tự thiết kế redundancy — không thể dựa vào PDB.

Chi phí và khi nào dùng Spot Pods

Giảm giá Spot so với On-demand (xấp xỉ, thay đổi theo region và resource type):

  • CPU: giảm ~60-70%
  • Memory: giảm ~70-80%

Thực tế với một Pod General Purpose (1 vCPU, 4 GiB):

  • On-demand: ~$0.0455 + ~$0.0194 = ~$0.065/giờ
  • Spot: ~$0.013 + ~$0.006 = ~$0.019/giờ (giảm ~71%)

Phù hợp với Spot Pods:

  • Batch jobs có thể retry (ML training checkpoints, ETL pipelines)
  • Stateless workers xử lý queue messages (nếu có retry logic phía queue)
  • Test và CI/CD runners
  • Rendering jobs, transcoding jobs

Không phù hợp:

  • Primary database instances
  • Stateful services không có replica
  • Workloads cần SLA chặt chẽ
  • Jobs không thể checkpoint và resume

Anti-patterns với Spot Pods

Anti-pattern 1: Spot Pods không có retry logic

yaml
# WRONG: Job không có restart policy và retry
apiVersion: batch/v1
kind: Job
spec:
  template:
    spec:
      nodeSelector:
        cloud.google.com/gke-spot: "true"
      restartPolicy: Never  # Nếu bị preempt → job fail forever
      containers:
      - name: processor
        command: ["process-data", "--no-checkpoint"]
yaml
# CORRECT: Job với retry và checkpoint
apiVersion: batch/v1
kind: Job
spec:
  backoffLimit: 10  # Retry khi bị preempt
  template:
    spec:
      nodeSelector:
        cloud.google.com/gke-spot: "true"
      restartPolicy: OnFailure
      containers:
      - name: processor
        command: ["process-data", "--checkpoint-dir=/checkpoints"]
        volumeMounts:
        - name: checkpoints
          mountPath: /checkpoints
      volumes:
      - name: checkpoints
        persistentVolumeClaim:
          claimName: checkpoint-pvc

Anti-pattern 2: Dùng Spot Pods cho stateful primary

yaml
# WRONG: Primary Redis trên Spot
spec:
  nodeSelector:
    cloud.google.com/gke-spot: "true"  # Redis sẽ mất data khi preempt

Nếu cần Redis với Spot savings, dùng Redis Cluster với primary trên on-demand và replicas trên Spot.

Extended Duration Pods

Vấn đề Extended Duration giải quyết

Trong Autopilot, GKE có thể evict Pods vì hai lý do chính:

  1. Cluster scale-down: Không cần node nữa
  2. Node upgrade: GKE cần upgrade node OS/Kubernetes version

Đối với batch workloads dài (machine learning training, large ETL jobs), bị evict giữa chừng gây ra:

  • Mất toàn bộ progress
  • Phải restart từ đầu (nếu không có checkpoint)
  • Chi phí compute tăng do re-processing
  • Delay timeline

Extended Duration Pods giải quyết vấn đề này bằng cách trì hoãn eviction từ GKE lên đến 7 ngày.

Cách kích hoạt

Thêm annotation cluster-autoscaler.kubernetes.io/safe-to-evict: "false" vào Pod:

yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: ml-training-job
spec:
  template:
    metadata:
      annotations:
        cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
    spec:
      containers:
      - name: trainer
        image: my-ml-trainer:v1.0
        resources:
          requests:
            cpu: "8"
            memory: "32Gi"

Với annotation này, GKE sẽ không evict Pod này trong quá trình:

  • Node upgrades
  • Cluster autoscaler scale-down decisions

Limits của Extended Duration

Không phải mọi Pod đều có thể dùng Extended Duration. Có giới hạn:

Maximum 50 Extended Duration workloads per cluster. Workloads được phân biệt theo CPU request value, không phải số lượng Pod.

Ví dụ: Nếu bạn có 3 Jobs, mỗi Job có 10 Pods với CPU request 4 vCPU
→ Autopilot coi đây là 3 distinct workloads (cùng CPU value = cùng workload)
→ Vẫn còn 47 slots

Nhưng nếu mỗi Job có CPU request khác nhau (4, 8, 16): → 3 × 10 = 30 Pods, nhưng chỉ chiếm 3 workload slots.

Không compatible với:

  • Spot Pods (Extended Duration và Spot là hai chiến lược ngược nhau)
  • Custom compute classes với node configurations phức tạp
  • Kubernetes inter-pod affinity (podAffinity/podAntiAffinity)

Eviction vẫn xảy ra với Extended Duration Pods

Extended Duration không bảo vệ hoàn toàn. Pod vẫn bị terminate nếu:

  1. OOM Kill: Container vượt memory limit
  2. Priority-based preemption: Pod priority cao hơn cần resources
  3. Node auto-repair: Node hardware failure yêu cầu thay thế
  4. User-initiated drain: Bạn hoặc admin chủ động drain node
  5. Compute Engine maintenance: VM maintenance event
  6. Sau 7 ngày: Bảo vệ tối đa 7 ngày, sau đó GKE evict bình thường

Extended Duration và resource overhead

Khi dùng Extended Duration với workload separation (workload isolation), Autopilot yêu cầu minimum resources cao hơn:

ConfigurationMinimum CPUMinimum Memory
Standard Pod0.25 vCPU512 MiB
Extended Duration (Balanced)1 vCPU4 GiB
Extended Duration với separation (Balanced)2 vCPU8 GiB

Lý do: để đảm bảo node có đủ capacity cho Pod sống lâu dài, Autopilot đặt Pod trên node đủ lớn.

Tương tác với node upgrades

Đây là use case chính của Extended Duration:

Node upgrade được triggered


GKE kiểm tra Pods trên node

       ├── Pod thường → evict ngay (với grace period)

       └── Extended Duration Pod → delay eviction

              └── Chờ tối đa 7 ngày

                     ├── Job hoàn thành trong 7 ngày → GKE upgrade node sau
                     └── Sau 7 ngày → evict và upgrade node

Điều này không có nghĩa là cluster upgrade bị delay 7 ngày — GKE upgrade các node khác trước, rồi upgrade node có Extended Duration Pod sau khi Pod hoàn thành hoặc sau 7 ngày.

Thiết kế pattern cho long-running batch jobs

Pattern được recommend cho ML training hoặc batch jobs dài trong Autopilot:

yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: training-job
spec:
  backoffLimit: 3  # Retry nếu bị terminate ngoài ý muốn
  template:
    metadata:
      annotations:
        cluster-autoscaler.kubernetes.io/safe-to-evict: "false"  # Extended Duration
    spec:
      # Không dùng Spot Pods cho jobs cần Extended Duration
      containers:
      - name: trainer
        image: ml-framework:latest
        command:
        - python
        - train.py
        - --checkpoint-dir=/mnt/checkpoints
        - --resume-from-checkpoint  # Resume nếu restart
        env:
        - name: CHECKPOINT_INTERVAL
          value: "300"  # Checkpoint mỗi 5 phút
        resources:
          requests:
            cpu: "8"
            memory: "32Gi"
        volumeMounts:
        - name: checkpoints
          mountPath: /mnt/checkpoints
      volumes:
      - name: checkpoints
        persistentVolumeClaim:
          claimName: training-checkpoints  # Persistent storage
      restartPolicy: OnFailure
      terminationGracePeriodSeconds: 300  # 5 phút để flush checkpoint

So sánh Spot Pods vs Extended Duration

ChiềuSpot PodsExtended Duration
Mục đíchGiảm chi phíBảo vệ long-running jobs
Compatible với nhau?❌ Không❌ Không
Bảo vệ khỏi upgrade eviction❌ Không✅ Lên đến 7 ngày
Bảo vệ khỏi preemption❌ Không❌ Không (chỉ cho upgrades)
Resource minimumStandardCao hơn (2 vCPU / 8 GiB với separation)
Chi phíThấp hơn ~70%Standard (không giảm)
Khi nào dùngWorkload chịu được interruptWorkload cần thời gian dài liên tục

Decision framework

Job cần chạy bao lâu?
├── < 1 giờ: Spot Pods (rủi ro thấp, tiết kiệm lớn)

├── 1-24 giờ:
│   ├── Có checkpoint mechanism? → Spot Pods với retry
│   └── Không có checkpoint? → On-demand (không Spot, không Extended Duration)

└── > 24 giờ:
    ├── Có checkpoint, chấp nhận restart? → Spot với retry
    └── Không muốn restart? → On-demand + Extended Duration

References