このドキュメントでは、エージェントのデータライフサイクルのニーズに合わせて調整された Agent Sandbox のストレージを管理するためのリファレンス実装について説明します。
エージェントのデータライフサイクルのニーズに応じて、次のいずれかの構成を選択します。
ストレージ ソリューションの選択の詳細については、AI エージェント ワークロードのストレージを選択するをご覧ください。
次のドキュメントでは、dynamic-rwo StorageClass を使用してディスクタイプの自動
選択
を行い、Agent Sandbox
Pod がスケジュールされているノードのマシンタイプと互換性のあるディスクをプロビジョニングします。GKE がエージェントのストレージに
Hyperdisk Balanced ボリュームをプロビジョニングするようにするには、
互換性のあるマシン
ファミリーのノードで Agent Sandbox をスケジュールする必要があります。そうしないと、GKE はpd-balancedにフォールバックします。
このドキュメントでは、ReadWriteOnce(RWO)アクセスを使用して、プライベート分離ワークスペース データアクセス モードを実装します。このモードでは、エージェントは、読み取りと書き込みのアクセス権を持つプライベート分離ストレージ ディレクトリで起動します。
特に指定がない限り、このドキュメントのリファレンス実装では、数秒の起動レイテンシを許容できるエージェントに適用可能な直接サンドボックス作成を使用します。ステートフル ワークスペースまたはポイントインタイム復元ワークスペースで 1 秒未満の起動レイテンシを実現するには、GKE Agent Sandbox ウォームプールを使用する必要があります。ストレージを要求されたウォームプール Pod にバインドするには、カスタム スクリプトと特権 DaemonSet が必要です。リファレンス実装については、こちらの GitHub の例をご覧ください。
代替アクセスモード
代替アクセスモードをサポートするには、構成でボリュームとスナップショットの定義を変更します。
- コラボレーション ワークスペース:
accessModesをReadWriteManyに変更し、 Filestore マルチシェア(Enterprise)(enterprise-multishare-rwx)などの RWX 対応の StorageClass を使用します。 - 探索ブランチ ワークスペース: テンプレート フォルダを読み取り専用としてマウントし、書き込み可能な別のスクラッチパッドを提供します。
ベース テンプレートには、複数の読み取り専用
アタッチをサポートするストレージを使用する必要があります。たとえば、Hyperdisk ML(ROX)
アクセス モードの
ReadOnlyManyや RWX アクセス モードの Filestore マルチシェアなどです。
始める前に
ステートフル ワークスペースを構成する
このパターンを使用して、エージェントのファイルの最新の状態を保持します。エージェント セッションが一時停止または終了(Agent Sandbox が削除)されたときにエージェントが状態を保持し、エージェント セッションがアクティブ化(Agent Sandbox が再作成)されたときに最新の状態からデータを復元する必要がある場合に便利です。
このセクションのリファレンス実装では、直接サンドボックス作成を使用します。これは、数秒の起動レイテンシを許容できるエージェントに適用できます。
このアプローチでは、標準の GKE PersistentVolumeClaim(PVC)リソースを使用して、サンドボックスをユーザーのデータを含む既存の PVC にリンクします。
ステートフル ワークスペース パターンは、次の一連のイベントに従います。
- プロビジョニング: 管理者またはオーケストレータは、決定論的識別子(
たとえば、
pvc-agent-1)を使用して、各エージェント セッションに プライベート PVC を手動でプロビジョニングします。 - 参照: Sandbox リソースで、
persistentVolumeClaimブロック内のvolumesフィールドを使用して、既存のボリュームの正確なclaimNameを指定します。 - レイテンシ: サンドボックスが作成されると、GKE は Compute Engine ディスクをノード VM に動的にアタッチする必要があります。 これにより、標準の数秒の遅延が発生します。
- 永続性: セッションの終了時(サンドボックスの削除)に、 GKE はディスクを切断しますが、PVC は破棄しません。これにより、 次のセッションで最新の状態が保持されます。
セッション間でデータを保持するステートフル ワークスペースを構成するには、次のサブセクションの手順を完了します。
永続ワークスペース(PVC)をプロビジョニングする
pvc-agent-1 などの決定論的識別子を使用するプライベート PersistentVolumeClaim(PVC)を作成します。
次のマニフェストを
pvc-agent-1.yamlとして保存します。apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-agent-1 # Derived directly from the deterministic assignment ID namespace: default spec: accessModes: - ReadWriteOnce storageClassName: dynamic-rwo # Selects disk type compatible with the node machine family resources: requests: storage: 10Gi次のようにマニフェストを適用します。
kubectl apply -f pvc-agent-1.yaml
ストレージ クラスは動的ボリューム バインディングを使用するため、ディスクはまだどのノードにもアタッチされていません。リクエストする Pod がスケジュールされるまで、Pending 状態のままになります。
Agent Sandbox をデプロイする
決定論的 PVC を参照して、Sandbox カスタム リソースをデプロイします。
次のマニフェストを
sandbox-agent-1.yamlとして保存します。apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: sandbox-agent-1 # Traceable sandbox name namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor # Required automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace-disk mountPath: /workspace # Mounts the private disk into the container resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace-disk persistentVolumeClaim: claimName: pvc-agent-1 # Binds this specific Sandbox to Agent 1's PVC restartPolicy: OnFailure次のようにマニフェストを適用します。
kubectl apply -f sandbox-agent-1.yaml
GKE はノード容量を確認し、ディスクをアタッチします。これには数秒かかります。コンテナはユーザー空間の gVisor カーネル内で初期化されます。
エージェントからデータを書き込む
マウントされたディスクにテキスト ファイルを書き込んで、ワークスペース内でファイル変更を実行するアクティブな AI エージェントをシミュレートします。
# Set the active Pod name
POD_NAME=sandbox-agent-1
# Write a state file to the persistent directory
kubectl exec $POD_NAME -- sh -c "echo 'Workspace State Saved - Agent 1' > /workspace/modified_data.txt"
# Confirm the file exists on the disk
kubectl exec $POD_NAME -- cat /workspace/modified_data.txt
エージェント セッションを終了する
エージェントがアイドル状態になったときにスケールダウンまたはセッションを終了するのをシミュレートするには、Sandbox リソースを削除しますが、基盤となるストレージは保持します。
kubectl delete sandbox sandbox-agent-1
GKE はディスクをマウント解除して切断します。pvc-agent-1 PVC は残り、データが保持されます。
エージェント セッションを再アクティブ化する
セッションを再アクティブ化するには、同じ PVC を参照する新しい Sandbox リソースを再デプロイします。
kubectl apply -f sandbox-agent-1.yaml
ディスクが再アタッチされ(アタッチの遅延が発生します)、コンテナが起動します。
データの保持を確認する
新しく作成したサンドボックス コンテナを調べて、前のセッションのデータが保持されていることを確認します。
# Set the active Pod name of the new session
NEW_POD_NAME=sandbox-agent-1
# Read the file from the newly booted sandbox
kubectl exec -it $NEW_POD_NAME -- cat /workspace/modified_data.txt
出力には Workspace State Saved - Agent 1 が表示されます。
リソースのクリーンアップ
Agent Sandbox と関連する永続ボリュームのクレームを削除します。
kubectl delete sandbox sandbox-agent-1
kubectl delete pvc pvc-agent-1
ポイントインタイム復元と所有権の転送を構成する
このパターンを使用して、並列実験、デバッグ、独立した作業を行うためのデータセットをクローンします。エージェントのワークスペースは履歴データセット(または共有状態)から初期化され、後続の変更はベース テンプレートを変更せずに、別のプライベート書き込み可能レイヤに保存されます。
このセクションのリファレンス実装では、直接サンドボックス作成を使用します。これは、数秒の起動レイテンシを許容できるエージェントに適用できます。このアプローチでは、オーケストレータが新しいサンドボックス セッションを開始する前に、履歴 VolumeSnapshot から新しい PersistentVolumeClaim(PVC)を動的にプロビジョニングします。
VolumeSnapshotClass を作成する
CSI ドライバと削除ポリシーを指定する VolumeSnapshotClass を作成します。
Hyperdisk の場合は、pd.csi.storage.gke.io ドライバを使用します。
次のマニフェストを
1-snapshot-class.yamlとして保存します。apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshotClass metadata: name: standard-rwo-snapshot driver: pd.csi.storage.gke.io deletionPolicy: Delete次のようにマニフェストを適用します。
kubectl apply -f 1-snapshot-class.yaml
初期ワークスペースをプロビジョニングする
エージェントが最初の作業を行うボリュームを作成します。
次のマニフェストを
2-source-pvc.yamlとして保存します。apiVersion: v1 kind: PersistentVolumeClaim metadata: name: agent-source-pvc spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo resources: requests: storage: 10Gi次のようにマニフェストを適用します。
kubectl apply -f 2-source-pvc.yaml
状態データを生成する
サンドボックス Pod をデプロイして、ボリュームにデータを書き込みます。
次のマニフェストを
3-source-sandbox.yamlとして保存します。apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: agent-session-v1 namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace persistentVolumeClaim: claimName: agent-source-pvc restartPolicy: OnFailure次のようにマニフェストを適用します。
kubectl apply -f 3-source-sandbox.yamlPod が実行されるまで待ってから、状態ファイルを書き込みます。
POD_NAME=agent-session-v1 kubectl exec $POD_NAME -- sh -c "echo 'Point-in-Time Snapshot - v1' > /workspace/state.txt"
履歴状態をアーカイブする(CSI VolumeSnapshot)
CSI VolumeSnapshot をトリガーして、現在の状態をフリーズします。スナップショットを作成する場合は、ディスク スナップショットのベスト プラクティスに従ってください。
次のマニフェストを
4-volume-snapshot.yamlとして保存します。apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshot metadata: name: agent-session-v1-snapshot spec: volumeSnapshotClassName: standard-rwo-snapshot source: persistentVolumeClaimName: agent-source-pvc次のようにマニフェストを適用します。
kubectl apply -f 4-volume-snapshot.yaml
スナップショットからボリュームを復元する
dataSource が CSI VolumeSnapshot を指す新しい PVC をデプロイします。
次のマニフェストを
5-restored-pvc.yamlとして保存します。apiVersion: v1 kind: PersistentVolumeClaim metadata: name: agent-restored-pvc spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo dataSource: name: agent-session-v1-snapshot kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io resources: requests: storage: 10Gi次のようにマニフェストを適用します。
kubectl apply -f 5-restored-pvc.yaml
復元された Agent Sandbox セッションを開始する
新しく復元された PVC を参照する新しい Sandbox リソースをプロビジョニングします。
次のマニフェストを
6-restored-sandbox.yamlとして保存します。apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: agent-session-v2-restored namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace persistentVolumeClaim: claimName: agent-restored-pvc restartPolicy: OnFailure次のようにマニフェストを適用します。
kubectl apply -f 6-restored-sandbox.yaml
永続性と復元を確認する
エージェントが履歴データを読み取れることを確認します。
NEW_POD_NAME=agent-session-v2-restored
kubectl exec $NEW_POD_NAME -- cat /workspace/state.txt
予想される出力: Point-in-Time Snapshot - v1
リソースのクリーンアップ
Agent Sandbox、PVC、VolumeSnapshot を削除します。
kubectl delete sandbox agent-session-v1
kubectl delete sandbox agent-session-v2-restored
kubectl delete pvc agent-source-pvc
kubectl delete pvc agent-restored-pvc
kubectl delete volumesnapshot agent-session-v1-snapshot
kubectl delete volumesnapshotclass standard-rwo-snapshot
エフェメラル ワークスペースを構成する
エージェントがアクティブなときに一時ファイルを保存するためのストレージ ボリュームが必要な場合は、エフェメラル ワークスペース パターンを使用します。Agent Sandbox の削除時にデータを保持する必要はありません。
1 秒未満の起動で構成する
Agent Sandbox ウォームプールを使用して、バックグラウンドで空のボリュームを事前プロビジョニングします。
SandboxTemplate を定義する
volumeClaimTemplate ブロック内で、エフェメラル ストレージのバッキングを定義します。
次のマニフェストを
stateless-template.yamlとして保存します。apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxTemplate metadata: name: stateless-sandbox-template namespace: default spec: podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: ephemeral-disk mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumeClaimTemplates: - metadata: name: ephemeral-disk spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo # Selects disk type compatible with node machine family resources: requests: storage: 10Gi
サンドボックス ウォームプールを起動する
次のマニフェストを
stateless-warmpool.yamlとして保存します。apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxWarmPool metadata: name: stateless-warmpool namespace: default spec: replicas: 5 # Keep five standby Pods with pre-attached empty disks sandboxTemplateRef: name: stateless-sandbox-template両方のマニフェストを適用します。
kubectl apply -f stateless-template.yaml kubectl apply -f stateless-warmpool.yaml
サンドボックスを要求する
ユーザーがセッションを開始したときにトリガーされる SandboxClaim を定義します。
次のマニフェストを
stateless-sandbox-claim.yamlとして保存します。apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxClaim metadata: name: agent-1-claim spec: sandboxTemplateRef: name: stateless-sandbox-template次のようにマニフェストを適用します。
kubectl apply -f stateless-sandbox-claim.yaml
1 秒未満の実行を確認する
Agent Sandbox Pod 名を取得し、/workspace ディレクトリがマウントされ、すぐに使用できることを確認します。
export POD_NAME=$(kubectl get sandboxclaim agent-1-claim -o jsonpath='{.status.sandbox.name}')
kubectl exec $POD_NAME -- ls -la /workspace
エージェント セッションを終了する
エージェント セッションを終了して、要求されたサンドボックスを解放するには、SandboxClaim リソースを削除します。
kubectl delete sandboxclaim agent-1-claim
リソースのクリーンアップ
サンドボックス ウォームプールとサンドボックス テンプレートを削除します。
kubectl delete sandboxwarmpool stateless-warmpool
kubectl delete sandboxtemplate stateless-sandbox-template
数秒の起動で構成する
数秒のレイテンシを許容するエフェメラル ワークスペースを実装するには、ウォームプールなしで Agent Sandbox を直接作成します。
ステートレス Agent Sandbox を定義する
次のマニフェストを
sandbox-direct-stateless.yamlとして保存します。apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: sandbox-direct-stateless namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: ephemeral-disk mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required restartPolicy: OnFailure volumeClaimTemplates: - metadata: name: ephemeral-disk spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo resources: requests: storage: 10Gi
Agent Sandbox をデプロイする
ディスクを動的にプロビジョニングして、スケジュールされたノードにアタッチするには、マニフェストを適用します。
kubectl apply -f sandbox-direct-stateless.yaml
起動レイテンシと実行を確認する
Pod のステータスをモニタリングして、Pod が Running 状態に移行する前のアタッチの遅延を確認します。
kubectl get pods -w
Pod が実行されたら、Pod 名を取得し、/workspace ディレクトリが使用可能であることを確認します。
POD_NAME=sandbox-direct-stateless
kubectl exec $POD_NAME -- ls -la /workspace
エージェント セッションを終了する
Sandbox リソースを削除して、Pod を自動的に終了し、エフェメラル ストレージを破棄します。
kubectl delete sandbox sandbox-direct-stateless
次のステップ
- GKE Agent Sandbox の詳細を確認する。
- Agent Sandbox で AI コード実行を分離する方法を確認する。
- Pod スナップショットを使用して Agent Sandbox 環境を保存して復元する方法を確認する。