Memulihkan dari snapshot Pod

Snapshot Pod Google Kubernetes Engine (GKE) membantu meningkatkan latensi startup workload dengan memulihkan snapshot Pod yang sedang berjalan. Snapshot Pod menyimpan seluruh status Pod, termasuk memori dan perubahan pada sistem file root. Saat replika baru dibuat, bukan menginisialisasi Pod dari status baru, snapshot akan dipulihkan. Kemudian, Pod melanjutkan eksekusi dari titik saat snapshot diambil.

Dokumen ini menjelaskan cara mengaktifkan dan mengonfigurasi snapshot Pod GKE untuk workload Anda.

Untuk mengetahui informasi selengkapnya tentang cara kerja snapshot Pod, lihat Tentang snapshot Pod.

Sebelum memulai

Sebelum memulai, pastikan Anda telah melakukan tugas berikut:

  • Aktifkan Google Kubernetes Engine API.
  • Aktifkan Google Kubernetes Engine API
  • Jika ingin menggunakan Google Cloud CLI untuk tugas ini, instal lalu lakukan inisialisasi gcloud CLI. Jika sebelumnya Anda telah menginstal gcloud CLI, dapatkan versi terbaru dengan menjalankan perintah gcloud components update. gcloud CLI versi sebelumnya mungkin tidak mendukung menjalankan perintah dalam dokumen ini.

Mengaktifkan snapshot Pod

Untuk mengaktifkan snapshot Pod, pertama-tama buat atau update cluster dengan fitur snapshot Pod diaktifkan. Kemudian, buat atau update node pool untuk dijalankan di GKE Sandbox.

  1. Untuk mengaktifkan fitur di cluster, selesaikan salah satu langkah berikut:

    • Untuk mengaktifkan snapshot Pod di cluster baru, jalankan perintah berikut:

      gcloud beta container clusters create CLUSTER_NAME \
          --enable-pod-snapshots \
          --cluster-version=CLUSTER_VERSION \
          --workload-pool=PROJECT_ID.svc.id.goog \
          --workload-metadata=GKE_METADATA
      

      Ganti kode berikut:

      • CLUSTER_NAME: nama cluster Anda.
      • CLUSTER_VERSION: versi cluster baru Anda, yang harus 1.34.1-gke.3084001 atau yang lebih baru.
      • PROJECT_ID: project ID Anda.
    • Untuk mengaktifkan snapshot Pod di cluster yang ada, selesaikan langkah-langkah berikut:

      1. Update cluster ke versi 1.34.1-gke.3084001 atau yang lebih baru:

        gcloud container clusters upgrade CLUSTER_NAME \
            --node-pool=NODEPOOL_NAME \
            --cluster-version=CLUSTER_VERSION
        

        Ganti kode berikut:

        • CLUSTER_NAME: nama cluster Anda.
        • NODEPOOL_VERSION: nama node pool Anda.
        • CLUSTER_VERSION: versi untuk mengupdate cluster baru Anda, yang harus berupa 1.34.1-gke.3084001 atau yang lebih baru.
      2. Aktifkan snapshot Pod di cluster Anda:

        gcloud container clusters update CLUSTER_NAME \
           --workload-pool=PROJECT_ID .svc.id.goog" \
           --enable-pod-snapshots
        

        Ganti PROJECT_ID dengan project ID Anda.

  2. Mengaktifkan GKE Sandbox di cluster Standard Anda:

    gcloud container node-pools create NODE_POOL_NAME \
      --cluster=CLUSTER_NAME \
      --node-version=NODE_VERSION \
      --machine-type=MACHINE_TYPE \
      --image-type=cos_containerd \
      --sandbox type=gvisor
    

    Ganti variabel berikut:

    • NODE_POOL_NAME: nama node pool baru.
    • NODE_VERSION: versi yang akan digunakan untuk node pool.
    • MACHINE_TYPE: jenis mesin yang akan digunakan untuk node.

    Untuk mengetahui informasi selengkapnya tentang penggunaan gVisor, lihat Mengisolasi workload Anda menggunakan GKE Sandbox.

Menyimpan snapshot

Snapshot pod disimpan di bucket Cloud Storage, yang berisi status memori dan (opsional) GPU. Snapshot Pod memerlukan Workload Identity Federation untuk GKE agar dapat mengaktifkan dan menggunakan akun layanan Pod untuk melakukan autentikasi ke Cloud Storage.

Snapshot pod memerlukan konfigurasi berikut untuk bucket:

  • Namespace hierarkis: harus diaktifkan untuk memungkinkan kueri baca dan tulis yang lebih tinggi per detik. Namespace hierarkis juga mengharuskan akses level bucket yang seragam diaktifkan.
  • Hapus sementara: karena snapshot Pod menggunakan upload gabungan paralel, Anda harus menonaktifkan fitur perlindungan data seperti hapus sementara. Jika tetap diaktifkan, penghapusan objek sementara dapat meningkatkan tagihan penyimpanan Anda secara signifikan.
  • Lokasi: Lokasi bucket Cloud Storage harus sama dengan lokasi cluster GKE karena performa dapat terpengaruh jika snapshot ditransfer di berbagai region.

Membuat bucket Cloud Storage

Untuk membuat bucket dan izin yang diperlukan, selesaikan langkah-langkah berikut:

  1. Membuat bucket Cloud Storage. Perintah berikut akan membuat bucket dengan konfigurasi yang diperlukan:

    gcloud storage buckets create "gs://BUCKET_NAME" \
       --uniform-bucket-level-access \
       --enable-hierarchical-namespace \
       --soft-delete-duration=0d \
       --location="LOCATION"
    

    Ganti kode berikut:

    • BUCKET_NAME: nama bucket Anda.
    • LOCATION: lokasi bucket Anda.

    Untuk mengetahui daftar lengkap opsi pembuatan bucket, lihat opsi buckets create.

Memberikan izin workload untuk mengakses bucket Cloud Storage

Secara default, GKE tidak memiliki izin untuk mengakses Cloud Storage. Untuk membaca dan menulis file snapshot, Anda harus memberikan izin IAM ke akun layanan Kubernetes (KSA) yang digunakan oleh Pod workload Anda.

  1. Dapatkan kredensial agar Anda dapat berkomunikasi dengan cluster menggunakan perintah kubectl:

    gcloud container clusters get-credentials "CLUSTER_NAME"
    
  2. Untuk setiap Pod, selesaikan langkah-langkah berikut:

    1. Buat KSA untuk setiap Pod:

      kubectl create serviceaccount "KSA_NAME" \
          --namespace "NAMESPACE"
      

      Ganti kode berikut:

      • KSA_NAME: nama KSA Anda.
      • NAMESPACE: namespace untuk Pod Anda.
    2. Beri KSA izin untuk mengakses bucket:

      gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="roles/storage.bucketViewer"
      
      gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="roles/storage.objectUser"
      

      Ganti kode berikut:

      • PROJECT_NUMBER: nomor project Anda.
      • PROJECT_ID: project ID Anda.

(Opsional) Buat folder terkelola untuk bucket Cloud Storage

Membuat folder memungkinkan Anda mengisolasi izin untuk snapshot dari Pod yang saling tidak tepercaya, yang berguna dalam kasus penggunaan multi-tenant. Untuk menyiapkan folder terkelola, selesaikan langkah-langkah berikut:

  1. Buat peran IAM kustom yang hanya berisi izin yang diperlukan untuk Snapshot pod:

    gcloud iam roles create podSnapshotGcsReadWriter \
        --project="PROJECT_ID" \
        --permissions="storage.objects.get,storage.objects.create,storage.objects.delete,storage.folders.create"
    
  2. Berikan peran roles/storage.bucketViewer kepada semua KSA di namespace target. Peran ini memungkinkan KSA membaca metadata bucket, tetapi tidak memberikan izin baca atau tulis ke objek dalam bucket.

    gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/namespace/NAMESPACE" \
        --role="roles/storage.bucketViewer"
    

    Ganti kode berikut:

    • PROJECT_NUMBER: nomor project Anda.
    • PROJECT_ID: project ID Anda.
  3. Untuk setiap KSA yang perlu menyimpan snapshot Pod, selesaikan langkah-langkah berikut:

    1. Buat folder terkelola untuk KSA:

      gcloud storage managed-folders create "gs://BUCKET_NAME/FOLDER_PATH/"
      

      Ganti FOLDER_PATH dengan jalur untuk folder terkelola, misalnya my-app-snapshots.

    2. Berikan peran podSnapshotGcsReadWriter kustom kepada KSA di folder terkelola:

      gcloud storage managed-folders add-iam-policy-binding "gs://BUCKET_NAME/FOLDER_PATH/" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="projects/PROJECT_ID/roles/podSnapshotGcsReadWriter"
      

      Ganti KSA_NAME dengan nama KSA.

Mengonfigurasi penyimpanan untuk snapshot

Untuk menentukan tempat menyimpan file snapshot, buat resource PodSnapshotStorageConfig.

  1. Contoh berikut mengonfigurasi GKE untuk menyimpan snapshot Pod di jalur FOLDER_PATH/ dalam bucket Cloud Storage BUCKET_NAME. Simpan manifes berikut sebagai example-pod-snapshot-storage-config:

    apiVersion: podsnapshot.gke.io/v1alpha1
    kind: PodSnapshotStorageConfig
    metadata:
      name: example-pod-snapshot-storage-config
      namespace: NAMESPACE
    spec:
      snapshotStorageConfig:
        gcs:
          bucket: "BUCKET_NAME"
          path: "FOLDER_PATH"
    

    Ganti kode berikut:

    • NAMESPACE: namespace untuk Pod Anda. Secara default, nilainya adalah default.
    • BUCKET_NAME: nama bucket Cloud Storage Anda.
    • FOLDER_PATH: jalur untuk folder terkelola Cloud Storage.
  2. Terapkan manifes:

    kubectl apply -f example-pod-snapshot-storage-config.yaml
    

Membuat kebijakan snapshot

Untuk mengaktifkan snapshot untuk Pod, buat resource PodSnapshotPolicy dengan pemilih yang cocok dengan label Pod.

  1. Contoh berikut membuat kebijakan yang berlaku untuk Pod dengan label app: my-app dan menggunakan konfigurasi penyimpanan example-pod-snapshot-storage-config. Simpan manifes berikut sebagai example-pod-snapshot-policy.yaml:

    apiVersion: podsnapshot.gke.io/v1alpha1
    kind: PodSnapshotPolicy
    metadata:
      name: example-pod-snapshot-policy
      namespace: NAMESPACE
    spec:
      storageConfigName: example-pod-snapshot-storage-config
      selector:
        matchLabels:
          app: my-app
      triggerConfig:
        type: workload
        postCheckpoint: resume
    
  2. Terapkan manifes:

    kubectl apply -f example-pod-snapshot-policy.yaml --namespace NAMESPACE
    

Mengoptimalkan ukuran snapshot

Saat snapshot Pod dipicu, gVisor akan merekam seluruh status semua container, termasuk:

  • Status aplikasi, seperti memori dan register
  • Perubahan pada sistem file root dan tmpfs (termasuk volume emptyDir)
  • Status kernel, seperti deskriptor file terbuka, thread, dan soket

Ukuran snapshot ditentukan oleh faktor-faktor berikut. Snapshot yang lebih besar memerlukan waktu lebih lama untuk disimpan dan dipulihkan. Untuk mengoptimalkan performa, sebelum memicu snapshot, Anda harus membersihkan status atau file aplikasi yang tidak diperlukan setelah Pod dipulihkan dari snapshot.

Mengoptimalkan ukuran snapshot sangat penting untuk workload seperti model bahasa besar (LLM). Server LLM sering kali mendownload bobot model ke penyimpanan lokal (rootfs atau tmpfs) sebelum memuatnya ke GPU. Saat snapshot diambil, status GPU dan file bobot model akan disimpan. Dalam skenario ini, jika modelnya berukuran 100 GB, snapshot yang dihasilkan berukuran sekitar 200 GB (100 GB file model, ditambah 100 GB yang merepresentasikan status GPU). Setelah bobot model dimuat ke GPU, file di sistem file sering kali tidak diperlukan agar aplikasi dapat berjalan. Dengan menghapus file model ini sebelum Anda memicu snapshot, Anda dapat mengurangi ukuran snapshot hingga setengahnya dan memulihkan aplikasi dengan latensi yang jauh lebih rendah.

Memicu snapshot

Anda dapat memicu snapshot dari dalam workload saat aplikasi siap, atau Anda dapat memicu snapshot sesuai permintaan secara manual untuk Pod tertentu.

Memicu snapshot dari workload

Untuk memicu snapshot dari dalam kode aplikasi, konfigurasikan aplikasi Anda untuk mengirim sinyal saat siap untuk snapshot. Untuk menandakan kesiapan, tulis 1 ke file /proc/gvisor/checkpoint, misalnya echo 1 > /proc/gvisor/checkpoint. Operasi penulisan memulai proses snapshot secara asinkron dan segera kembali. Membaca dari deskriptor file yang sama akan memblokir proses membaca hingga snapshot dan pemulihan selesai serta beban kerja siap dilanjutkan.

Penggunaan yang tepat akan bervariasi bergantung pada aplikasi Anda, tetapi contoh berikut menunjukkan pemicu snapshot untuk aplikasi Python. Untuk memicu Snapshot dari contoh workload ini, selesaikan langkah-langkah berikut:

  1. Simpan manifes berikut sebagai my-app.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-app
      namespace: NAMESPACE
      labels:
        app: my-app
    spec:
      serviceAccountName: KSA_NAME
      runtimeClassName: gvisor
      containers:
      - name: my-container
        image: python:3.10-slim
        command: ["python3", "-c"]
        args:
          - |
            import time
            def trigger_snapshot():
              try:
                with open("/proc/gvisor/checkpoint", "r+") as f:
                  f.write("1")
                  res = f.read().rstrip()
                  print(f"GKE Pod Snapshot: {res}")
              except FileNotFoundError:
                print("GKE Pod Snapshot file does not exist -- Pod Snapshots is disabled")
                return
              except OSError as e:
                return e
            i = 0
            while True:
              print(f"Count: {i}", flush=True)
              if (i == 20): #simulate the application being ready to snapshot at 20th count
                trigger_snapshot()
              i += 1
              time.sleep(1)
        resources:
          limits:
            cpu: "500m"
            memory: "512Mi"
          requests:
            cpu: "250m"
            memory: "256Mi"
    
  2. Deploy aplikasi:

    kubectl apply -f my-app.yaml
    

Memicu snapshot secara manual

Untuk memicu snapshot on-demand secara manual untuk Pod tertentu, buat resource PodSnapshotManualTrigger. Pemicuan snapshot secara manual tersedia di GKE versi 1.34.1-gke.3556000 dan yang lebih baru.

  1. Contoh berikut memicu snapshot untuk Pod bernama my-pod. Simpan manifes berikut sebagai example-manual-trigger.yaml:

    apiVersion: podsnapshot.gke.io/v1alpha1
    kind: PodSnapshotManualTrigger
    metadata:
      name: example-manual-trigger
      namespace: NAMESPACE
    spec:
      targetPod: my-pod
    
  2. Terapkan manifes:

    kubectl apply -f example-manual-trigger.yaml --namespace NAMESPACE
    

Untuk mengonfirmasi apakah snapshot berhasil dipicu, periksa kolom status resource PodSnapshotManualTrigger:

kubectl get podsnapshotmanualtriggers.podsnapshot.gke.io example-manual-trigger -n NAMESPACE -o yaml

Kolom status menunjukkan apakah pemicuan snapshot berhasil atau gagal.

Memverifikasi snapshot

Anda dapat mengonfirmasi bahwa snapshot telah diambil dengan memeriksa histori peristiwa untuk peristiwa GKEPodSnapshotting:

kubectl get events -o \
custom-columns=NAME:involvedObject.name,CREATIONTIME:.metadata.creationTimestamp,REASON:.reason,MESSAGE:.message \
--namespace NAMESPACE \
--field-selector involvedObject.name=POD_NAME,reason=GKEPodSnapshotting

Ganti POD_NAME dengan nama Pod Anda, misalnya my-app atau my-pod.

Outputnya akan terlihat seperti berikut:

NAME                                    CREATIONTIME           REASON               MESSAGE
default/5b449f9c7c-bd7pc                2025-11-05T16:25:11Z   GKEPodSnapshotting   Successfully checkpointed the pod to PodSnapshot

Mengelola snapshot

Saat Anda membuat snapshot Pod, resource CRD PodSnapshot akan dibuat untuk menyimpan status Pod pada saat itu. Kolom status dari resource ini menunjukkan apakah operasi snapshot berhasil dan apakah snapshot tersedia untuk pemulihan.

Untuk melihat semua resource PodSnapshot dalam namespace, jalankan perintah berikut:

kubectl get podsnapshots.gke.io --namespace NAMESPACE

Outputnya akan terlihat seperti berikut:

NAME                                   STATUS                  POLICY           AGE
de334898-1e7a-4cdb-9f2e-7cc2181c29e4   AllSnapshotsAvailable   example-policy   47h

Memulihkan beban kerja dari snapshot

Untuk memulihkan workload dari snapshot terbaru, Anda dapat menghapus Pod yang ada setelah snapshot diambil, lalu men-deploy ulang Pod. Atau, Anda dapat men-deploy Pod baru dengan spesifikasi yang identik. GKE secara otomatis memulihkan Pod dari snapshot yang cocok.

Langkah-langkah berikut menunjukkan cara memulihkan Pod dari snapshot yang cocok dengan menghapus dan men-deploy ulang Pod:

  1. Hapus Pod:

    kubectl delete -f POD_NAME.yaml
    

    Ganti POD_NAME dengan nama Pod Anda, misalnya my-app.

  2. Terapkan kembali Pod:

    kubectl apply -f POD_NAME.yaml
    
  3. Lihat log untuk mengonfirmasi pemulihan snapshot:

    kubectl logs my-app --namespace NAMESPACE
    

    Output bergantung pada cara Anda mengonfigurasi aplikasi. Di aplikasi contoh, log menampilkan GKE Pod Snapshot: restore saat operasi pemulihan terjadi.

Memulihkan dari snapshot tertentu

Secara default, GKE memulihkan workload dari resource PodSnapshot terbaru yang cocok dengan Pod. Saat snapshot diambil, GKE akan otomatis membuat nama unik (UUID) untuk resource PodSnapshot, yang dapat Anda lihat dengan menjalankan kubectl get podsnapshots.gke.io --namespace NAMESPACE.

Untuk memulihkan workload dari resource PodSnapshot yang lebih lama atau spesifik, tambahkan anotasi podsnapshot.gke.io/ps-name ke spesifikasi Pod workload Anda, dengan menentukan nama resource PodSnapshot yang akan digunakan untuk memulihkan workload:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: NAMESPACE
  labels:
    app: my-app
  annotations:
    podsnapshot.gke.io/ps-name: "POD_SNAPSHOT_NAME"
spec:
  serviceAccountName: KSA_NAME
  runtimeClassName: gvisor
  containers:
  ...

Ganti POD_SNAPSHOT_NAME dengan nama snapshot yang ingin Anda pulihkan. Anda bisa mendapatkan nama snapshot dengan menjalankan perintah kubectl get podsnapshots.gke.io --namespace NAMESPACE.

Agar GKE dapat menggunakan snapshot yang ditentukan untuk pemulihan, kondisi status resource PodSnapshot harus Ready dan ada di namespace yang sama dengan Pod. Jika PodSnapshot bukan Ready atau tidak ada di namespace yang sama dengan Pod, beban kerja akan melakukan cold start, bukan memulihkan dari snapshot.

Menonaktifkan snapshot

Menghapus CRD PodSnapshotPolicy akan mencegah Pod di-snapshot dan dipulihkan. Pod yang sedang berjalan tidak terpengaruh oleh penghapusan resource. Namun, jika Anda menghapus kebijakan saat Pod sedang disimpan atau dipulihkan, Pod mungkin memasuki status gagal.

Untuk menonaktifkan pembuatan snapshot dan pemulihan untuk Pod baru yang diatur oleh kebijakan, hapus PodSnapshotPolicy dengan menjalankan perintah berikut:

kubectl delete podsnapshotpolicies.podsnapshot.gke.io SNAPSHOT_POLICY --namespace=NAMESPACE

Ganti SNAPSHOT_POLICY dengan nama PodSnapshotPolicy yang ingin Anda hapus, misalnya example-pod-snapshot-policy.

Anda juga dapat menghapus resource PodSnapshot tertentu sehingga Pod tidak lagi dipulihkan dari snapshot tertentu tersebut. Menghapus resource PodSnapshot juga akan menghapus file yang disimpan di Cloud Storage.

Untuk mencegah snapshot tertentu digunakan untuk pemulihan di masa mendatang, hapus objek PodSnapshot dengan menjalankan perintah berikut:

kubectl delete podsnapshots.podsnapshot.gke.io POD_SNAPSHOT_NAME --namespace=NAMESPACE

Ganti POD_SNAPSHOT_NAME dengan nama snapshot yang ingin Anda hapus, misalnya example-podsnapshot.

Langkah berikutnya