GKE Pod スナップショットについて

Google Kubernetes Engine(GKE)Pod スナップショットは、実行中の Pod のスナップショットを復元することで、ワークロードの起動レイテンシを改善します。Pod スナップショットは、メモリやファイル システムの変更など、Pod の状態全体を保存します。新しいレプリカを作成すると、スナップショットから復元されるため、ワークロードは新しい状態から開始するのではなく、再開できます。

このドキュメントでは、GKE Pod スナップショットの概要について説明します。この機能を有効にして使用する方法については、Pod スナップショットから復元するをご覧ください。

Pod スナップショットを使用するタイミング

初期化に時間がかかるワークロード(大規模なモデルを CPU または GPU メモリに読み込む AI 推論ワークロードや、多くのライブラリと依存関係を読み込む大規模なアプリケーションなど)には、Pod スナップショットを使用します。起動時間がすでに短いワークロードでは、一般的に Pod スナップショットのメリットはありません。

Pod スナップショットの仕組み

GKE Pod スナップショットは、特定の時点での Pod のプロセス状態の正確なコピーを保存します。新しいレプリカが作成されると、Pod は新しい状態から初期化されるのではなく、スナップショットから復元され、スナップショットが取得された時点から実行が再開されます。

Pod スナップショットを使用するには、Kubernetes カスタム リソース定義(CRD)を作成して、スナップショットの動作を宣言的に構成します。各 GKE ノードで実行されているエージェントが、スナップショットのライフサイクルを管理します。定義したポリシーに基づいて、エージェントは新しいスナップショットを作成するタイミングと、既存のスナップショットを使用して新しい Pod を復元するタイミングを決定します。GKE コントロール プレーンで実行されているコントローラは、古いスナップショットをクリーンアップし、問題を解決します。Cloud Storage は Pod スナップショットを保存します。

カスタム リソース定義

Pod スナップショットは、2 つの CRD を使用して宣言的に構成されます。

  • PodSnapshotStorageConfig: スナップショットの保存場所を指定します。Cloud Storage バケットのみがサポートされています。
  • PodSnapshotPolicy: Kubernetes ラベルセレクタに基づいて、スナップショットを作成する Pod を定義します。このリソースには、スナップショット トリガーや保持ポリシーなど、機能の構成オプションの大部分が含まれています。

スナップショットの照合

Pod の照合では、Pod スナップショットが特定の Pod と互換性があるかどうかが判断されます。この照合は、Pod の重要なランタイム仕様(抽出された Pod 仕様とも呼ばれます)から一意のハッシュを作成することで実現されます。このハッシュは Pod スナップショット内に埋め込まれます。後でこの Pod スナップショットから Pod を復元するには、独自の抽出された Pod 仕様から同一のハッシュを生成する必要があります。このプロセスにより、チェックポイントされた Pod と復元された Pod のランタイム構成が同一であることが保証されます。

蒸留では、image などの重要なランタイム フィールドのみを保持し、nodeNamenodeSelector などの不要なフィールドを削除することで、Pod 仕様を簡素化します。これらの必須フィールドの値は、チェックポイントに使用される Pod と復元に使用される Pod の間で一貫している必要があります。

Pod オブジェクトの次のフィールドは、一意のハッシュに影響します。

  • metadata:
    • annotations: gVisor ランタイムに関連するアノテーション(dev.gvisor.* プレフィックスで始まるアノテーションなど)。
    • labels: batch.kubernetes.io/job-completion-index
  • spec:
    • volumes: namevolumeSourcehostPathpersistentVolumeClaimconfigMap
    • containers:
      • name
      • image
      • command
      • args
      • workingDir
      • ports: namecontainerPortprotocol
      • volumeMounts: namereadOnlyrecursiveReadOnlymountPathsubPathmountPropagationsubPathExpr
      • volumeDevices: name
      • lifecycle: postStartpreStop
      • terminationMessagePath
      • terminationMessagePolicy
      • securityContext(およびすべてのサブフィールド)
      • stdin
      • stdinOnce
      • tty
    • initContainers: containers と同じサブフィールド。
    • dnsPolicy
    • automountServiceAccountToken
    • hostNetwork
    • hostPID
    • hostIPC
    • shareProcessNamespace
    • securityContext
    • dnsConfig
    • runtimeClassName
    • os
    • hostUsers

互換性のあるスナップショットと見なされるには、次の追加条件が一致している必要があります。

  • ハードウェア: 新しい Pod は、元の Pod と同じマシンシリーズとアーキテクチャを持つノードで実行する必要があります。マシンシリーズとアーキテクチャは同じである必要があります。CPU の数とメモリ容量は変更できます。E2 マシンタイプは、基盤となる動的アーキテクチャのためサポートされていません。
  • バージョニング: gVisor カーネルのバージョンと GPU ドライバのバージョンが一致している必要があります。

GKE はスナップショットの互換性を管理します。GKE が互換性のあるスナップショットを見つけると、GKE はスナップショットから新しい Pod を復元します。互換性のあるスナップショットが存在しない場合、Pod は正常に起動します。

readiness の復元とバックグラウンドの読み込み

Pod がスナップショットから復元されると、通常は数秒で gVisor カーネルが復元されます。起動レイテンシを最小限に抑えるため、カーネルが復元されるとすぐにアプリケーションが再開され、アプリケーションのメモリが完全に読み込まれるのを待ちません。アプリケーションのメモリは、バックグラウンド ストリーミング メカニズムを使用して復元されます。

アプリケーションがまだ読み込まれていないメモリの一部にアクセスしようとすると、ページ フォールトが発生します。gVisor はこのフォールトをインターセプトし、アプリケーション スレッドを一時停止して、必要なメモリページをストレージからすぐに取得します。このオンデマンドのフェッチは、バックグラウンド ストリームよりも優先されます。

このバックグラウンド読み込みにより、アプリケーションがまだストリーミングされていないメモリを必要とする場合、復元後数秒間はメモリアクセスにわずかなレイテンシが生じる可能性があります。このレイテンシは、メモリ状態が完全に同期されると解消されます。

このバックグラウンド読み込みの動作は、GPU の状態にも適用されます。たとえば、大規模言語モデル(LLM)Pod は、GPU メモリがまだ入力中にもかかわらず、Running 状態になり、ネットワーク チェックに応答することがあります。GPU の状態が完全に復元されるまで、モデルは推論に対して完全にレスポンシブになりません。そのため、復元速度を測定する場合は、モデルサーバーが起動したタイミングを必ずキャプチャしてください。モデルサーバーの起動時刻は、最初のトークンまでの時間(TTFT)や Pod の readiness プローブなどの指標を使用して確認できます。

GPU の状態

Pod スナップショットは、GPU の状態のキャプチャをサポートしています。GPU を使用する Pod のスナップショットをトリガーすると、NVIDIA cuda-checkpoint ツールは GPU 状態をプロセスのメモリに保存します。つまり、GPU に保存されているデータ(モデルの重みなど)はスナップショットに含まれます。その後、Pod は一時停止され、スナップショットが作成されます。復元の際には前述のプロセスが逆順で実行されます。

GPU の状態はプロセスのメモリに書き込まれるため、スナップショットと復元オペレーション中に Pod のメモリ使用量が増加します。Pod のメモリ上限を設定する場合は、この追加のメモリ要件を考慮する必要があります。

復元された Pod に関する考慮事項

Kubernetes API の観点から見ると、新しい Pod が作成されます。Pod の起動時に、Pod に対応するスナップショットがある場合、Pod は元のメモリとプロセス状態を含め、そのスナップショットから復元されます。ただし、新しい一意のインスタンスとして機能するには、Pod の状態のいくつかの側面を変更する必要があります。

復元後の次の状態の変化を検討してください。

  • ネットワーク インターフェース: 復元された Pod に新しい IP アドレスが割り振られます。すべてのネットワーク インターフェースとルートが再構成されます。スナップショットの時点で存在していたアクティブなネットワーク接続は、復元時に閉じられます。リスニング ソケットは引き続き機能します。
  • ホスト名: 復元された Pod は新しい ID を想定し、新しいホスト名を受け取ります。
  • アプリケーションの状態: 各 Pod で一意である必要があるアプリケーションの状態(テスト ID や乱数シードなど)は、復元後に再初期化する必要があります。
  • Secret: スナップショットが取得される前に作成された暗号鍵と証明書は、再作成する必要があります。
  • 環境変数: スナップショットと復元の間で環境変数を変更できます。ただし、環境変数はアプリケーション メモリに保存されるため、GKE Sandbox は環境変数を確実に検出して置換できません。ワークロードが復元後に新しい環境変数に依存している場合、Pod はそれらの変数を手動で更新する必要があります。新しい環境変数は /proc/gvisor/spec_environ ファイルで使用できます。ファイル形式は /proc/<pid>/environ と同じです。

復元後に変更される状態

復元時にすべての状態が保持されるわけではありません。Pod が新しい ID を想定できるように、Pod 状態の次の部分が変更されます。

  • ネットワーク インターフェース: 復元された Pod に新しい IP アドレスが割り振られます。すべてのインターフェースとルートが再構成されます。スナップショットの時点で存在していたアクティブなネットワーク接続は、復元時に閉じられます。リスニング ソケット、ループバック接続、Unix ドメイン ソケット接続は引き続き機能します。
  • ホスト名: 復元された Pod は新しい ID を想定し、新しいホスト名を受け取ります。
  • 実時間: 実時間が現在の時刻にジャンプします。

制限事項と要件

GKE Pod スナップショットには次の制限があります。

  • Pod スナップショットは GKE Sandbox が提供する gVisor コンテナ ランタイムに依存するため、Pod は GKE Sandbox で実行する必要があります。
  • Pod スナップショットは、E2 マシンタイプをサポートしていません。
  • Pod スナップショットは、単一 GPU Pod で動作します。次のマルチ GPU 構成のみがサポートされています。
    • g2-standard-4(1 x L4)
    • g2-standard-8(1 x L4)
    • g2-standard-12(1 x L4)
    • g2-standard-16(1 x L4)
    • g2-standard-32(1 x L4)
    • g2-standard-48(4 x L4)
    • g2-standard-96(8 x L4)
    • a2-highgpu-1g(1 x A100-40GB)
    • a2-ultragpu-1g(1 x A100-80GB)
    • a3-highgpu-1g(1 x H100-80GB)
  • GPU の部分的な使用はサポートされていません。ノードに複数の GPU がある場合、Pod はそれらをすべて使用する必要があります。たとえば、4 つの GPU を搭載したマシンで、それぞれ 1 つの GPU を使用する 4 つの Pod を含む Pod スナップショットを使用することはできません。
  • Pod スナップショットでの Cloud Storage FUSE CSI ドライバのサイドカー コンテナの使用はサポートされていません。

次のステップ