Gerenciar o armazenamento do sandbox do agente

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

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

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

O documento a seguir usa a StorageClass dynamic-rwo para seleção automatizada de tipo de disco e provisiona discos compatíveis com os tipos de máquina dos nós em que os pods da sandbox do agente são programados. Para garantir que o GKE provisione volumes Hyperdisk Balanced para o armazenamento dos seus agentes, programe os Agent Sandboxes 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 do Private Isolated Workspace usando o acesso ReadWriteOnce (RWO). Nesse modo, um agente é iniciado com um diretório de armazenamento isolado e privado ao qual tem acesso exclusivo de leitura e gravação.

Salvo especificaçã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 uma latência de inicialização inferior a um segundo para espaços de trabalho com estado ou de restauração pontual, use os pools quentes do GKE Agent Sandbox. A vinculação do armazenamento a um pod de pool quente reivindicado exige 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 o accessModes para ReadWriteMany e use uma StorageClass compatível com RWX, como Filestore Multishares (Enterprise) (enterprise-multishare-rwx).
  • Espaço de trabalho de ramificação de análise detalhada: monte a pasta de modelo como somente leitura e forneça um bloco de notas gravável separado. Para o modelo de base, use um armazenamento que ofereça suporte a várias anexações somente leitura, como o Hyperdisk ML com modo de acesso ReadOnlyMany (ROX) ou o Filestore Multishares com 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. Isso é ú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 é 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 padrão do GKE PersistentVolumeClaim (PVC) para vincular uma 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 claimName exato do volume atual.
  3. Latência: quando a sandbox é criada, o GKE precisa anexar dinamicamente o disco do Compute Engine à VM do nó, o que causa um atraso padrão de vários segundos.
  4. Persistência: ao encerrar a sessão (excluindo o Sandbox), o GKE desconecta 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, siga as etapas nas subseções abaixo.

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á conectado 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 em um kernel gVisor de 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 dele 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 o escalonamento reduzido 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 desmonta e remove o disco. O pvc-agent-1 PVC permanece, preservando os dados.

Reativar a sessão do agente

Para reativar a sessão, reimplante um novo recurso de sandbox que faça referência ao mesmo PVC.

kubectl apply -f sandbox-agent-1.yaml

O disco é reconectado (causando o atraso de conexão), 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 vai 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 uma transferência de propriedade

Use esse padrão para clonar conjuntos de dados e executar experimentos paralelos, depurar ou trabalhar de forma independente. O espaço de trabalho de um agente é inicializado com um conjunto de dados históricos (ou estado compartilhado), salvando as 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 a VolumeSnapshotClass

Crie uma 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 tirar 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 do Sandbox que faça referência ao 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

Saída esperada: Point-in-Time Snapshot - v1

Limpar recursos

Exclua as caixas de simulação 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 efêmero

Use o padrão de espaço de trabalho efêmero 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 em menos de um segundo

Use pools quentes da sandbox do agente para pré-provisionar volumes vazios em segundo plano.

Definir o SandboxTemplate

Defina o armazenamento temporário 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 é acionado quando um usuário inicia 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 em 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 e o modelo de 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 efêmero que tolera latência de vários segundos, use a criação direta do Agent Sandbox 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 do anexo antes que ele 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 sessão do agente

Exclua o recurso da sandbox para encerrar automaticamente o pod e destruir o armazenamento efêmero dele:

kubectl delete sandbox sandbox-direct-stateless

A seguir