管理 Agent Sandbox 存储空间

本文档提供了用于管理智能体沙盒存储的参考实现,这些实现根据智能体的数据生命周期需求量身定制。

根据智能体的数据生命周期需求,选择以下配置之一:

如需详细了解如何选择存储解决方案,请参阅 为 AI 智能体工作负载选择存储

以下文档使用 dynamic-rwo StorageClass 进行 自动磁盘类型 选择 ,以预配与安排 Agent Sandbox Pod 的节点机器类型兼容的磁盘。为帮助确保 GKE 为智能体的存储预配 Hyperdisk Balanced 卷,您必须 在 兼容机器 系列(例如 N4)的节点上安排 Agent Sandbox;否则,GKE 会回退到 pd-balanced

本文档通过使用 ReadWriteOnce (RWO) 访问权限实现“专用隔离工作区”数据访问模式。 在此模式下,智能体启动时会使用一个专用隔离存储目录,该目录具有专属的读写权限。

除非另有说明,否则本文档中的参考实现使用 直接沙盒创建,适用于可容忍多秒启动延迟的智能体。如需为有状态或时间点恢复工作区实现亚秒级启动延迟,您必须使用 GKE Agent Sandbox Warm Pools。将存储绑定到已声明的 Warm Pool Pod 需要自定义脚本和具有特权的 DaemonSet。如需查看参考实现,请参阅此 GitHub 示例

替代访问模式

如需支持替代访问模式,您可以修改配置中的卷和快照定义:

  • 协作工作区:将 accessModes 更改为 ReadWriteMany,并 使用支持 RWX 的 StorageClass,例如 Filestore Multishares (Enterprise) (enterprise-multishare-rwx)。
  • 探索分支工作区:将 模板文件夹装载为只读,并提供单独的可写草稿本。 对于基本模板,您必须使用支持多个只读 挂接的存储,例如具有 Hyperdisk ML ReadOnlyMany (ROX) 访问模式的 Hyperdisk ML 或具有 RWX 访问模式的 Filestore Multishares。

准备工作

在集群中启用 Agent Sandbox

配置有状态工作区

使用此模式可保留智能体文件的最新状态。当智能体必须在智能体会话暂停或终止(Agent Sandbox 被删除)时保留状态,并在智能体会话激活(Agent Sandbox 被重新创建)时从最新状态恢复数据时,此模式非常有用。

本部分中的参考实现使用直接沙盒创建,适用于可容忍多秒启动延迟的智能体。

此方法使用标准 GKE PersistentVolumeClaim (PVC) 资源将沙盒链接到包含用户数据的预先存在的 PVC。

有状态工作区模式遵循以下事件序列:

  1. 预配:管理员或编排器使用确定性标识符(例如 pvc-agent-1)为每个智能体会话手动预配 专用 PVC。
  2. 引用:在 Sandbox 资源中,您可以使用 persistentVolumeClaim 块中的 volumes 字段来指定现有卷的 确切 claimName
  3. 延迟时间:创建沙盒时,GKE 必须 将 Compute Engine 磁盘动态挂接到节点虚拟机, 这会产生标准的多秒延迟。
  4. 持久性:在会话终止(删除沙盒)时, GKE 会分离磁盘,但不会销毁 PVC,这有助于确保 为下一个会话保留最新状态。

如需配置在会话之间保留数据的有状态工作区,请完成以下子部分中的步骤。

预配永久性工作区 (PVC)

创建一个使用确定性标识符(例如 pvc-agent-1)的专用 PersistentVolumeClaim (PVC)。

  1. 将以下清单保存为 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
    
  2. 应用清单:

    kubectl apply -f pvc-agent-1.yaml
    

由于存储类别使用动态卷绑定,因此磁盘尚未挂接到任何节点。在安排请求该磁盘的 Pod 之前,它将保持 Pending 状态。

部署 Agent Sandbox

部署 Sandbox 自定义资源,引用确定性 PVC。

  1. 将以下清单保存为 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
    
  2. 应用清单:

    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. 将以下清单保存为 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
    
  2. 应用清单:

    kubectl apply -f 1-snapshot-class.yaml
    

预配初始工作区

创建一个卷,智能体将在其中执行其初始工作。

  1. 将以下清单保存为 2-source-pvc.yaml

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: agent-source-pvc
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: dynamic-rwo
      resources:
        requests:
          storage: 10Gi
    
  2. 应用清单:

    kubectl apply -f 2-source-pvc.yaml
    

生成状态数据

部署沙盒 Pod 以将数据写入卷。

  1. 将以下清单保存为 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
    
  2. 应用清单:

    kubectl apply -f 3-source-sandbox.yaml
    
  3. 等待 Pod 运行,然后写入状态文件:

    POD_NAME=agent-session-v1
    kubectl exec $POD_NAME -- sh -c "echo 'Point-in-Time Snapshot - v1' > /workspace/state.txt"
    

归档历史状态 (CSI VolumeSnapshot)

触发 CSI VolumeSnapshot 以冻结当前状态。拍摄快照时,请遵循磁盘快照的最佳实践

  1. 将以下清单保存为 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
    
  2. 应用清单:

    kubectl apply -f 4-volume-snapshot.yaml
    

从快照恢复卷

部署一个新 PVC,其 dataSource 指向 CSI VolumeSnapshot

  1. 将以下清单保存为 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
    
  2. 应用清单:

    kubectl apply -f 5-restored-pvc.yaml
    

启动恢复的 Agent Sandbox 会话

预配引用新恢复的 PVC 的新 Sandbox 资源。

  1. 将以下清单保存为 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
    
  2. 应用清单:

    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 时,无需保留任何数据。

配置亚秒级启动

使用 Agent Sandbox Warm Pools 在后台预配空卷。

定义 SandboxTemplate

volumeClaimTemplate 块中定义临时存储后备。

  1. 将以下清单保存为 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
    

启动 Sandbox Warm Pool

  1. 将以下清单保存为 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
    
  2. 应用这两个清单:

    kubectl apply -f stateless-template.yaml
    kubectl apply -f stateless-warmpool.yaml
    

声明沙盒

定义在用户启动会话时触发的 SandboxClaim。

  1. 将以下清单保存为 stateless-sandbox-claim.yaml

    apiVersion: extensions.agents.x-k8s.io/v1alpha1
    kind: SandboxClaim
    metadata:
      name: agent-1-claim
    spec:
      sandboxTemplateRef:
        name: stateless-sandbox-template
    
  2. 应用清单:

    kubectl apply -f stateless-sandbox-claim.yaml
    

验证亚秒级执行

捕获 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

清理资源

删除 Sandbox Warm Pool 和 Sandbox 模板:

kubectl delete sandboxwarmpool stateless-warmpool
kubectl delete sandboxtemplate stateless-sandbox-template

配置多秒启动

如需实现可容忍多秒延迟的临时工作区,请使用直接 Agent Sandbox 创建,而无需使用 Warm Pool。

定义无状态 Agent Sandbox

  1. 将以下清单保存为 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

后续步骤