Gerenciar o armazenamento do sandbox do agente

Este documento fornece implementações de referência para gerenciar o armazenamento de sandboxes de agentes adaptados às necessidades do ciclo de vida de dados dos seus agentes.

Dependendo das necessidades do ciclo de vida de dados dos seus agentes, escolha uma das seguintes configurações:

Para mais informações sobre como escolher uma solução de armazenamento, consulte Escolher o armazenamento para cargas de trabalho de agentes de IA.

O documento a seguir usa a StorageClass dynamic-rwo para a seleção automatizada do tipo de disco para provisionar discos compatíveis com os tipos de máquina de nós em que os pods do sandbox do agente estão programados. Para garantir que o GKE provisione volumes Hyperdisk Balanced para o armazenamento dos seus agentes, é preciso programar os sandboxes do agente nos nós de famílias de máquinas compatíveis, como N4. Caso contrário, o GKE vai usar pd-balanced.

Este documento implementa o modo de acesso aos dados espaço de trabalho isolado particular usando o acesso ReadWriteOnce (RWO). Nesse modo, um agente é iniciado com um diretório de armazenamento isolado particular ao qual ele tem acesso exclusivo de leitura e gravação.

Salvo indicação em contrário, as implementações de referência neste documento usam a criação direta de sandbox, que é aplicável a agentes que toleram latência de inicialização de vários segundos. Para alcançar a latência de inicialização de menos de um segundo para espaços de trabalho com estado ou de restauração pontual, use os pools quentes do sandbox do agente do GKE. A vinculação do armazenamento a um pod de pool quente reivindicado requer scripts personalizados e um DaemonSet privilegiado. Para uma implementação de referência, consulte este exemplo do GitHub.

Modos de acesso alternativos

Para oferecer suporte a modos de acesso alternativos, modifique as definições de volume e snapshot nas configurações:

  • Espaço de trabalho colaborativo: mude accessModes para ReadWriteMany e use uma StorageClass compatível com RWX, como o Filestore Multishares (Enterprise) (enterprise-multishare-rwx).
  • Espaço de trabalho de ramificação de exploração: monte a pasta de modelo como somente leitura e forneça um bloco de rascunho gravável separado. Para o modelo de base, use o armazenamento que oferece suporte a vários anexos somente leitura, como o Hyperdisk ML com ReadOnlyMany (ROX) modo de acesso ou o Filestore Multishares com o modo de acesso RWX.

Antes de começar

Ative o sandbox do agente no cluster.

Configurar um espaço de trabalho com estado

Use esse padrão para preservar o estado mais recente dos arquivos de um agente. Ele é útil quando o agente precisa preservar o estado quando a sessão é pausada ou encerrada (o sandbox do agente é excluído) e restaurar os dados do estado mais recente quando a sessão do agente é ativada (o sandbox do agente é recriado).

A implementação de referência nesta seção usa a criação direta de sandbox e é aplicável a agentes que toleram latência de inicialização de vários segundos.

Essa abordagem usa recursos PersistentVolumeClaim (PVC) padrão do GKE para vincular um sandbox a um PVC preexistente que contém os dados de um usuário.

O padrão de espaço de trabalho com estado segue esta sequência de eventos:

  1. Provisionamento: o administrador ou orquestrador provisiona manualmente um PVC particular para cada sessão do agente usando um identificador determinístico (por exemplo, pvc-agent-1).
  2. Referência: no recurso do sandbox, use o campo persistentVolumeClaim no bloco volumes para especificar o exato claimName do volume atual.
  3. Latência: quando o sandbox é criado, o GKE precisa anexar dinamicamente o disco do Compute Engine à VM do nó, o que gera um atraso padrão de vários segundos.
  4. Persistência: no encerramento da sessão (excluindo o sandbox), o GKE desanexa o disco, mas não destrói o PVC, o que ajuda a garantir que o estado mais recente seja preservado para a próxima sessão.

Para configurar um espaço de trabalho com estado que preserve os dados entre as sessões, conclua as etapas nas subseções a seguir.

Provisionar um espaço de trabalho permanente (PVC)

Crie um PersistentVolumeClaim (PVC) particular que use um identificador determinístico, como pvc-agent-1.

  1. Salve o seguinte manifesto como 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. Aplique o manifesto:

    kubectl apply -f pvc-agent-1.yaml
    

Como a classe de armazenamento usa a vinculação dinâmica de volume, o disco ainda não está anexado a nenhum nó. Ele permanece no estado Pending até que um pod que o solicite seja programado.

Implantar o sandbox do agente

Implante o recurso personalizado do sandbox, referenciando o PVC determinístico.

  1. Salve o seguinte manifesto como 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. Aplique o manifesto:

    kubectl apply -f sandbox-agent-1.yaml
    

O GKE verifica a capacidade do nó e anexa o disco, o que leva alguns segundos. O contêiner é inicializado dentro de um kernel gVisor do espaço do usuário.

Gravar dados do agente

Simule um agente de IA ativo executando modificações de arquivo no espaço de trabalho gravando um arquivo de texto no disco montado.

# 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

Encerrar a sessão do agente

Para simular a redução ou o encerramento da sessão quando o agente fica inativo, exclua o recurso do sandbox, mas preserve o armazenamento subjacente.

kubectl delete sandbox sandbox-agent-1

O GKE desativa e desanexa o disco. O PVC pvc-agent-1 permanece, preservando os dados.

Reativar a sessão do agente

Para reativar a sessão, reimplemente um novo recurso de sandbox que referencie o mesmo PVC.

kubectl apply -f sandbox-agent-1.yaml

O disco é anexado novamente (gerando o atraso de anexo) e o contêiner é inicializado.

Verificar a preservação de dados

Inspecione o contêiner de sandbox recém-criado para verificar se os dados da sessão anterior foram preservados.

# 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

A saída precisa mostrar Workspace State Saved - Agent 1.

Limpar recursos

Exclua o sandbox do agente e a reivindicação de volume permanente associada:

kubectl delete sandbox sandbox-agent-1
kubectl delete pvc pvc-agent-1

Configurar uma restauração pontual e transferência de propriedade

Use esse padrão para clonar conjuntos de dados para executar experimentos paralelos, depuração ou trabalho independente. O espaço de trabalho de um agente é inicializado a partir de um conjunto de dados histórico (ou estado compartilhado), salvando modificações subsequentes em uma camada gravável separada e particular sem modificar o modelo de base.

A implementação de referência nesta seção usa a criação direta de sandbox e é aplicável a agentes que toleram latência de inicialização de vários segundos. Essa abordagem depende do orquestrador para provisionar dinamicamente novos PersistentVolumeClaims (PVCs) de VolumeSnapshots históricos antes de iniciar uma nova sessão de sandbox.

Criar o VolumeSnapshotClass

Crie um VolumeSnapshotClass que especifique o driver CSI e a política de exclusão. Para o Hyperdisk, use o driver pd.csi.storage.gke.io.

  1. Salve o seguinte manifesto como 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. Aplique o manifesto:

    kubectl apply -f 1-snapshot-class.yaml
    

Provisionar o espaço de trabalho inicial

Crie um volume em que o agente vai realizar o trabalho inicial.

  1. Salve o seguinte manifesto como 2-source-pvc.yaml:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: agent-source-pvc
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: dynamic-rwo
      resources:
        requests:
          storage: 10Gi
    
  2. Aplique o manifesto:

    kubectl apply -f 2-source-pvc.yaml
    

Gerar dados de estado

Implante um pod de sandbox para gravar dados no volume.

  1. Salve o seguinte manifesto como 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. Aplique o manifesto:

    kubectl apply -f 3-source-sandbox.yaml
    
  3. Aguarde até que o pod esteja em execução e grave um arquivo de estado:

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

Arquivar o estado histórico (VolumeSnapshot do CSI)

Acione um VolumeSnapshot do CSI para congelar o estado atual. Ao fazer um snapshot, siga as práticas recomendadas para snapshots de disco.

  1. Salve o seguinte manifesto como 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. Aplique o manifesto:

    kubectl apply -f 4-volume-snapshot.yaml
    

Restaurar o volume do snapshot

Implante um novo PVC com o dataSource apontando para o VolumeSnapshot do CSI.

  1. Salve o seguinte manifesto como 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. Aplique o manifesto:

    kubectl apply -f 5-restored-pvc.yaml
    

Iniciar a sessão restaurada do sandbox do agente

Provisione um novo recurso de sandbox que referencie o PVC recém-restaurado.

  1. Salve o seguinte manifesto como 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. Aplique o manifesto:

    kubectl apply -f 6-restored-sandbox.yaml
    

Verificar persistência e restauração

Verifique se o agente pode ler os dados históricos.

NEW_POD_NAME=agent-session-v2-restored
kubectl exec $NEW_POD_NAME -- cat /workspace/state.txt

Resposta esperada: Point-in-Time Snapshot - v1

Limpar recursos

Exclua os sandboxes do agente, os PVCs e o 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

Configurar um espaço de trabalho temporário

Use o padrão de espaço de trabalho temporário quando um agente precisar de um volume de armazenamento para armazenar arquivos temporários enquanto estiver ativo. Nenhum dado precisa ser preservado na exclusão do sandbox do agente.

Configurar com inicialização de menos de um segundo

Use os pools quentes do sandbox do agente para provisionar volumes vazios em segundo plano.

Definir o SandboxTemplate

Defina o armazenamento temporário de backup no bloco volumeClaimTemplate.

  1. Salve o seguinte manifesto como 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
    

Iniciar o pool quente do sandbox

  1. Salve o seguinte manifesto como 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. Aplique os dois manifestos:

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

Reivindicar o sandbox

Defina um SandboxClaim que seja acionado quando um usuário iniciar uma sessão.

  1. Salve o seguinte manifesto como 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. Aplique o manifesto:

    kubectl apply -f stateless-sandbox-claim.yaml
    

Verificar a execução de menos de um segundo

Capture o nome do pod do sandbox do agente e verifique se o diretório /workspace está montado e pronto para uso imediato:

export POD_NAME=$(kubectl get sandboxclaim agent-1-claim -o jsonpath='{.status.sandbox.name}')
kubectl exec $POD_NAME -- ls -la /workspace

Encerrar a sessão do agente

Para encerrar a sessão do agente e liberar o sandbox reivindicado, exclua o recurso SandboxClaim:

kubectl delete sandboxclaim agent-1-claim

Limpar recursos

Exclua o pool quente do sandbox e o modelo do sandbox:

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

Configurar com inicialização de vários segundos

Para implementar um espaço de trabalho temporário que tolere latência de vários segundos, use a criação direta do sandbox do agente sem um pool quente.

Definir um sandbox do agente sem estado

  1. Salve o seguinte manifesto como 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
    

Implantar o sandbox do agente

Para provisionar dinamicamente o disco e anexá-lo ao nó programado, aplique o manifesto:

kubectl apply -f sandbox-direct-stateless.yaml

Verificar a latência e a execução da inicialização

Monitore o status do pod para observar o atraso de anexo antes que o pod faça a transição para o estado Running:

kubectl get pods -w

Depois que o pod estiver em execução, capture o nome dele e verifique se o diretório /workspace está disponível:

POD_NAME=sandbox-direct-stateless
kubectl exec $POD_NAME -- ls -la /workspace

Encerrar a sessão do agente

Exclua o recurso do sandbox para encerrar automaticamente o pod e destruir o armazenamento temporário dele:

kubectl delete sandbox sandbox-direct-stateless

A seguir