Pod スナップショットをトリガーする

スナップショット ポリシーを作成し、Google Kubernetes Engine(GKE)で実行中のワークロードの Pod スナップショットをトリガーする方法について説明します。

始める前に

始める前に、次のタスクを完了していることを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、 インストールして 初期化する gcloud CLI。gcloud CLI をインストール済みの場合は、最新の バージョンをgcloud components updateコマンドを実行して取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
  • 前提条件を満たし、クラスタで Pod スナップショットを有効にしていることを確認します。詳細については、Pod スナップショットの準備をご覧ください。

スナップショット ポリシーを作成する

Pod のスナップショットを有効にするには、Pod のラベルに一致するセレクタを含む PodSnapshotPolicy リソースを作成します。

  1. 次の例では、app: my-app ラベルが付いた Pod に適用され、example-pod-snapshot-storage-config ストレージ構成を使用するポリシーを作成します。次のマニフェストを example-pod-snapshot-policy.yaml として保存します。

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

    次のように置き換えます。

    • TRIGGER_TYPE: トリガーのタイプ。サポートされている値は、ワークロード ベースのトリガーの場合は workload、オンデマンド スナップショットの場合は manual です。
    • NAMESPACE: Pod の名前空間。

    構成可能なすべてのフィールドの完全なリストについては、 PodSnapshotPolicy CustomResourceDefinition(CRD)のドキュメントをご覧ください

  2. 次のようにマニフェストを適用します。

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

追加の Pod スナップショット ポリシーを構成する

PodSnapshotPolicy で、次のような追加のポリシーを構成できます。

  • スナップショット スコープ: スナップショットでキャプチャする Pod 状態の部分を指定するには、 spec.snapshotScope フィールドを構成します。サポートされている値は、アプリケーションの状態、メモリ、ファイル システムなど、Pod 全体をチェックポイントする whole-pod(デフォルト)と、コンテナのルート ファイル システムのみをチェックポイントする rootfs-only です。rootfs-only スコープには、GKE バージョン 1.35.3-gke.1031000 以降が必要です。

  • 自動クリーンアップ: 古い Pod スナップショット リソースを自動的にクリーンアップするには、spec.retentionConfig フィールドを使用して保持ポリシーを構成します。lastAccessTimeout フィールド(7d など)を使用して期間を指定できます。この期間が経過すると、スナップショットは削除されます。

  • スナップショットの整理: スナップショットを論理的にグループ化して、 同様の環境で取得されたスナップショットを コンテキストごとに区別できます。たとえば、すべてのユーザーでベース Pod が同じであるマルチテナント シナリオでは、ユーザーまたはグループごとにスナップショットを分離できます。スナップショットを分離するには、snapshotGroupingRules フィールドを使用して、ポリシーでグループ化ラベルを指定します。Pod が復元されると、同じラベル グループ内のスナップショットとのみ照合されます。復元時の互換性マッチングに対する このグループ化の影響の詳細については、 グループ化ルールのマッチングをご覧ください。

次の例では、PodSnapshotPolicy で保持設定とグループ化設定の両方を構成する方法を示します。これらの設定は個別に設定できます。

# ... other fields omitted
spec:
  snapshotScope: rootfs-only
  retentionConfig:
    lastAccessTimeout: 7d
  snapshotGroupingRules:
    groupByLabelValue:
      labels: ["tenant", "environment"]
      groupRetentionPolicy:
        maxSnapshotCountPerGroup: 5

構成可能なすべてのフィールドの完全なリストについては、 PodSnapshotPolicy のリファレンス ドキュメントをご覧ください

スナップショットのサイズを最適化する

Pod スナップショットがトリガーされると、gVisor は次のものを含むすべてのコンテナの状態全体をキャプチャします。

  • アプリケーションの状態(メモリやレジスタなど)
  • ルート ファイル システムと tmpfsemptyDir ボリュームを含む)への変更
  • カーネルの状態(開いているファイル記述子、スレッド、ソケットなど)

スナップショットのサイズは、こうした要因によって決まります。スナップショットが大きいほど、保存と復元に時間がかかります。パフォーマンスを最適化するには、スナップショットをトリガーする前に、Pod がスナップショットから復元された後に不要になるアプリケーションの状態やファイルをクリーンアップする必要があります。

スナップショット サイズの最適化は、大規模言語モデル(LLM)などのワークロードで特に重要です。LLM サーバーは、モデルの重みを GPU に読み込む前に、ローカル ストレージ(rootfs または tmpfs)にダウンロードすることがよくあります。スナップショットが生成されると、GPU の状態とモデルの重みファイルの両方が保存されます。このシナリオでは、モデルが 100 GB の場合、結果のスナップショットは約 200 GB(100 GB のモデルファイルと、GPU の状態を表す 100 GB)になります。モデルの重みが GPU に読み込まれた後、ファイル システム上のファイルが、アプリケーションの実行に必要ではなくなることがよくあります。スナップショットをトリガーする前にこれらのモデルファイルを削除すると、スナップショットのサイズを半分に減らし、レイテンシを大幅に削減してアプリケーションを復元できます。

スナップショットをトリガーする

アプリケーションの準備ができたときにワークロード内からスナップショットをトリガーすることも、特定の Pod のオンデマンド スナップショットを手動でトリガーすることもできます。

ワークロードからスナップショットをトリガーする

アプリケーション コード内からスナップショットをトリガーするには、スナップショットの準備ができたときにシグナルを送信するようにアプリケーションを構成します。準備完了を通知するには、/proc/gvisor/checkpoint ファイルに 1 を書き込みます(例: echo 1 > /proc/gvisor/checkpoint)。書き込みオペレーションは、スナップショット プロセスを非同期で開始し、すぐに戻ります。同じファイル記述子から読み取ると、スナップショットと復元が完了し、ワークロードの再開の準備が整うまで、読み取りプロセスがブロックされます。

実際の使用方法はアプリケーションによって異なりますが、次の例は Python アプリケーションのスナップショット トリガーを示しています。このワークロードの例からスナップショットをトリガーするには、次の操作を行います。

  1. 次のマニフェストを 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
            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"
    

    次のように置き換えます。

    • NAMESPACE: Pod の名前空間。
    • KSA_NAME: KSA の名前。
  2. アプリケーションをデプロイします。

    kubectl apply -f my-app.yaml
    

スナップショットを手動でトリガーする

特定の Pod のオンデマンド スナップショットを手動でトリガーするには、PodSnapshotManualTrigger リソースを作成します。

  1. 次の例では、my-pod という名前の Pod のスナップショットをトリガーします。次のマニフェストを example-manual-trigger.yaml として保存します。

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

    NAMESPACE は、Pod の名前空間に置き換えます。

  2. 次のようにマニフェストを適用します。

    kubectl apply -f example-manual-trigger.yaml
    

スナップショットが正常にトリガーされたかどうかを確認するには、PodSnapshotManualTrigger リソースの status フィールドを確認します。

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

status フィールドは、スナップショットのトリガーが成功したか失敗したかを示します。

スナップショットを確認する

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

次のように置き換えます。

  • POD_NAME: Pod の名前(my-appmy-pod など)。
  • NAMESPACE: Pod の名前空間。

出力は次のようになります。

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

次のステップ

Pod スナップショットからワークロードを復元する方法を学習する