Isolar a execução de código de IA com o Agent Sandbox no GKE

Neste documento, mostramos como executar código gerado com IA em um sandbox isolado em um cluster do Google Kubernetes Engine (GKE). Você cria um modelo de sandbox e um pool de sandboxes prontos no cluster. Em seguida, execute um script Python que solicita um sandbox do pool e executa um comando nele. O script usa o cliente Python do Agent Sandbox, uma biblioteca para criar e gerenciar sandboxes.

Executar código não confiável em um sandbox ajuda a proteger seu sistema contra possíveis vulnerabilidades no código gerado com IA, aumentar a velocidade de desenvolvimento e melhorar a segurança das suas implantações. Para uma visão geral de como o Agent Sandbox no GKE isola códigos não confiáveis gerados com IA, consulte Sobre o Agent Sandbox no GKE.

Custos

O Agent Sandbox no GKE é um software de código aberto que você pode usar sem custo financeiro adicional. Os preços do GKE se aplicam aos recursos que você cria, incluindo os recursos de computação que o controlador do Agent Sandbox usa.

Antes de começar

  1. No console do Google Cloud , na página do seletor de projetos, selecione ou crie um projeto do Google Cloud .

    Papéis necessários para selecionar ou criar um projeto

    • Selecionar um projeto: para selecionar um projeto, não é necessário ter um papel do IAM específico. É possível selecionar qualquer projeto em que você tenha um papel.
    • Criar um projeto: para criar um projeto, é preciso ter o papel de criador de projetos (roles/resourcemanager.projectCreator), que contém a permissão resourcemanager.projects.create. Saiba como conceder papéis.

    Acessar o seletor de projetos

  2. Verifique se o faturamento está ativado para o projeto do Google Cloud .

  3. Ative a API Kubernetes Engine, se ainda não estiver ativada.

    Funções necessárias para ativar APIs

    Para ativar APIs, você precisa da permissão serviceusage.services.enable. Se você criou o projeto, provavelmente já tem essa permissão pelo papel de proprietário (roles/owner). Caso contrário, é possível conseguir essa permissão pelo papel de administrador do Service Usage (roles/serviceusage.serviceUsageAdmin). Saiba como conceder papéis.

    Ativar a API

  4. No console do Google Cloud , ative o Cloud Shell.

    Ativar o Cloud Shell

  5. Verifique se você tem as permissões necessárias para concluir este documento.
  6. Verifique se você tem um cluster do GKE com o controlador do Agent Sandbox instalado e o roteador do Sandbox implantado. Caso contrário, conclua apenas as seguintes seções de Instalar o Agent Sandbox no GKE e retorne a este documento:
    1. Definir as variáveis de ambiente
    2. Crie um cluster do GKE
    3. Instalar o Agent Sandbox
    4. Implantar o roteador de sandbox
    Não é necessário concluir as outras seções desse documento, como Implantar um ambiente de sandbox. Mais adiante neste documento, você vai criar seus próprios recursos SandboxTemplate e SandboxWarmPool.

Funções exigidas

Para receber as permissões necessárias para criar e gerenciar sandboxes, peça ao administrador para conceder a você o papel do IAM de Administrador do Kubernetes Engine (roles/container.admin) no projeto. Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias usando papéis personalizados ou outros papéis predefinidos.

Definir variáveis de ambiente

Para simplificar os comandos executados neste documento, defina variáveis de ambiente no Cloud Shell. No Cloud Shell, defina as seguintes variáveis de ambiente úteis executando estes comandos:

export CLUSTER_NAME="agent-sandbox-cluster"
export LOCATION="us-central1"

Confira uma explicação dessas variáveis de ambiente:

  • CLUSTER_NAME: o nome do cluster do GKE, por exemplo, agent-sandbox-cluster.
  • LOCATION: a Google Cloud região ou zona em que o cluster do GKE está localizado. Se você usar um cluster do Autopilot, defina como a região (por exemplo, us-central1). Se você usar um cluster padrão, defina como a zona (por exemplo, us-central1-a).

Implantar um ambiente de sandbox

Nesta seção, mostramos como criar o blueprint do sandbox (um recurso SandboxTemplate), verificar o roteador de rede e instalar o cliente Python que você vai usar para interagir com o sandbox.

A maneira recomendada de criar e interagir com o sandbox é usando o cliente Python do Agentic Sandbox. Esse cliente oferece uma interface que simplifica todo o ciclo de vida de um sandbox, da criação à limpeza. É uma biblioteca Python que pode ser usada para criar, usar e excluir sandboxes de forma programática.

O cliente usa um roteador de sandbox como ponto de entrada central para todo o tráfego. No exemplo descrito neste documento, o cliente cria um túnel para esse roteador usando o comando kubectl port-forward, para que você não precise expor nenhum endereço IP público. O uso de kubectl port-forward não é uma solução segura e deve ser limitado a ambientes de desenvolvimento.

Criar recursos SandboxTemplate e SandboxWarmPool

Agora, defina a configuração do sandbox criando um recurso SandboxTemplate e um recurso SandboxWarmPool. O recurso SandboxTemplate funciona como um blueprint reutilizável que o controlador do Agent Sandbox usa para criar ambientes de sandbox consistentes e pré-configurados. O recurso SandboxWarmPool ajuda a garantir que um número especificado de pods pré-aquecidos esteja sempre em execução e pronto para ser reivindicado. Um sandbox pré-aquecido é um pod em execução que já foi inicializado. Essa pré-inicialização permite que novos sandboxes sejam criados em menos de um segundo e evita a latência de inicialização de um sandbox normal:

  1. No Cloud Shell, crie um arquivo chamado sandbox-template-and-pool.yaml com o seguinte conteúdo:

    apiVersion: extensions.agents.x-k8s.io/v1beta1
    kind: SandboxTemplate
    metadata:
      name: python-sandbox-template
      namespace: default
    spec:
      podTemplate:
        metadata:
          labels:
            sandbox: python-sandbox-example
        spec:
          runtimeClassName: gvisor
          automountServiceAccountToken: false # Required
          securityContext:
            runAsNonRoot: true # Required
          nodeSelector:
            sandbox.gke.io/runtime: gvisor # Required
          tolerations:
          - key: "sandbox.gke.io/runtime"
            value: "gvisor"
            effect: "NoSchedule" # Required
          containers:
          - name: python-runtime
            image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0
            ports:
            - containerPort: 8888
            readinessProbe:
              httpGet:
                path: "/"
                port: 8888
              initialDelaySeconds: 0
              periodSeconds: 1
            resources:
              requests:
                cpu: "250m"
                memory: "512Mi"
              limits:
                cpu: "500m"
                memory: "1Gi" # Required
            securityContext:
              capabilities:
                drop: ["ALL"] # Required
          restartPolicy: "OnFailure"
    ---
    apiVersion: extensions.agents.x-k8s.io/v1beta1
    kind: SandboxWarmPool
    metadata:
      name: python-sandbox-warmpool
      namespace: default
    spec:
      replicas: 2
      sandboxTemplateRef:
        name: python-sandbox-template
    
  2. Aplique os manifestos SandboxTemplate e SandboxWarmPool:

    kubectl apply -f sandbox-template-and-pool.yaml
    
  3. Aguarde até que os sandboxes do pool de aquecimento estejam prontos:

    kubectl wait sandboxwarmpool python-sandbox-warmpool \
        --for=jsonpath='{.status.readyReplicas}'=2 \
        --timeout=600s
    

    Mais adiante neste documento, o cliente Python cria um recurso SandboxClaim. Se o cliente criar a declaração antes que os sandboxes do pool estejam prontos, o controlador poderá criar um novo sandbox para a declaração em vez de atribuir um do pool. Em um cluster do Autopilot, os sandboxes podem levar vários minutos para ficarem prontos, porque o GKE pode precisar criar nós para eles.

Verificar o roteador do sandbox

O cliente Python que você vai usar para criar e interagir com ambientes de sandbox usa um componente chamado roteador de sandbox para se comunicar com os sandboxes.

Neste exemplo, você vai usar o modo de desenvolvedor do cliente para testes. Esse modo é destinado ao desenvolvimento local e usa o comando kubectl port-forward para estabelecer um túnel direto da máquina local para o serviço do roteador do sandbox em execução no cluster. Essa abordagem de tunelamento evita a necessidade de um endereço IP público ou de uma configuração de entrada complexa e simplifica a interação com sandboxes do ambiente local.

Verifique se o roteador do Sandbox está em execução no namespace agent-sandbox-system:

kubectl get deployment sandbox-router --namespace=agent-sandbox-system

Quando o roteador está em execução, a coluna READY mostra que todas as réplicas estão prontas, por exemplo, 2/2. Se o comando retornar um erro NotFound, implante o roteador seguindo as etapas em Implantar o roteador do Sandbox.

Instalar o cliente do Python

Agora que os componentes no cluster, como o roteador do Sandbox, foram implantados, a etapa preparatória final é instalar o cliente Python do Agentic Sandbox na máquina local. Esse cliente é uma biblioteca Python que permite criar, usar e excluir sandboxes de maneira programática. Você vai usá-lo na próxima seção para testar o ambiente:

  1. Crie e ative um ambiente virtual Python:

    python3 -m venv .venv
    source .venv/bin/activate
    
  2. Instale o pacote do cliente. Use a mesma versão do controlador do Agent Sandbox:

    pip install k8s-agent-sandbox==1.0.6
    

Testar o sandbox

Com todos os componentes de configuração prontos, agora é possível criar e interagir com um sandbox usando o cliente Python do Agentic Sandbox.

  1. Crie um script em Python chamado test_sandbox.py com o seguinte conteúdo:

    from k8s_agent_sandbox import SandboxClient
    from k8s_agent_sandbox.models import SandboxLocalTunnelConnectionConfig
    
    # Tunnels to svc/sandbox-router-svc in the agent-sandbox-system namespace.
    # cleanup=True deletes the sandbox when the script exits.
    client = SandboxClient(
        connection_config=SandboxLocalTunnelConnectionConfig(),
        cleanup=True,
    )
    
    sandbox = client.create_sandbox(warmpool="python-sandbox-warmpool", namespace="default")
    try:
        print(sandbox.commands.run("echo 'Hello from the sandboxed environment!'").stdout)
    except Exception as e:
        print(f"An error occurred: {e}")
    
  2. No terminal (com o ambiente virtual ainda ativo), execute o script de teste:

    python3 test_sandbox.py
    

Você verá a mensagem "Hello from the sandboxed environment!", que é a saída do sandbox.

Parabéns! Você executou um comando shell em um sandbox seguro. Usando o método sandbox.commands.run(), é possível executar qualquer comando shell, e o Agent Sandbox no GKE executa o comando em uma barreira segura que protege os nós do cluster e outras cargas de trabalho contra códigos não confiáveis. Isso fornece uma maneira segura e confiável para um agente de IA ou qualquer fluxo de trabalho automatizado executar tarefas.

Quando você executa o script, o SandboxClient processa todas as etapas para você. Ele cria o recurso SandboxClaim para iniciar o sandbox, aguarda que ele esteja pronto e usa o método sandbox.commands.run() para executar comandos do shell bash dentro do contêiner seguro. Em seguida, o cliente captura e imprime o stdout desse comando. Como o script define o parâmetro cleanup como True, o cliente exclui o sandbox quando o programa é encerrado.

Quando um recurso SandboxClaim é criado, um sandbox disponível do pool de espera é atribuído à declaração, que é marcada como pronta. O recurso SandboxWarmPool é reabastecido automaticamente para manter o número configurado de réplicas.

Para verificar se um sandbox específico foi reivindicado ou está disponível, confira o ownerReferences nos metadados do recurso Sandbox. Se o valor do campo kind for SandboxClaim, o sandbox está em uso. Se o valor do campo kind for SandboxWarmPool, o sandbox estará inativo e aguardando para ser reivindicado.

Executar sandboxes na produção

Neste documento, você interage com sandboxes de fora do cluster usando o Cloud Shell. O cliente Python usa suas credenciais de usuário para autenticar no cluster e gerenciar recursos de sandbox, além de usar o comando kubectl port-forward para estabelecer uma conexão com sandboxes. Essas etapas funcionam bem para cenários de desenvolvimento.

Em um cenário de produção, um aplicativo controlador (como um orquestrador de IA) é responsável por criar e gerenciar recursos de sandbox. Para usar o Agent Sandbox no GKE em produção, considere o seguinte:

  • Autenticação: o aplicativo do controlador precisa se autenticar no servidor de API do cluster para executar sandboxes. A configuração da autenticação depende de onde o aplicativo do controlador é executado, da seguinte maneira:

  • Roteamento: as solicitações do cliente Python no aplicativo do controlador precisam chegar ao roteador do sandbox no cluster. Na produção, use um dos seguintes métodos para estabelecer uma conexão de rede:

    • Se o aplicativo do controlador for executado no mesmo cluster, use a função SandboxDirectConnectionConfig para segmentar o URL e a porta que o serviço do roteador do Sandbox usa.
    • Se o aplicativo do controlador for executado fora do cluster, use a API gateway do GKE Gateway para criar um balanceador de carga interno ou externo. No código do cliente, use a função SandboxGatewayConnectionConfig para referenciar o gateway.

    Para mais informações sobre esses métodos de roteamento, consulte os exemplos de uso no GitHub e as etapas de implantação do gateway para o roteador.

  • Acesso do sandbox aos recursos do Google Cloud : se o código do sandbox precisar enviar solicitações para as APIs do Google Cloud , como o Cloud Storage, use uma política do IAM com a Federação de Identidade da Carga de Trabalho para GKE para conceder à conta de serviço do Kubernetes usada pelo pod do sandbox as permissões necessárias para esse acesso. Como a política de rede padrão bloqueia o acesso ao servidor de metadados do Google Cloud (169.254.169.254), é necessário personalizar a política de rede para permitir esse tráfego.

  • Restrições da política de rede: por padrão, o Agent Sandbox no GKE aplica uma postura de rede estrita de segurança por padrão (networkPolicyManagement: Managed). As seguintes restrições se aplicam a essa postura:

    • A entrada é bloqueada de todas as origens, exceto do roteador de sandbox designado (pods que têm o rótulo app: sandbox-router no namespace agent-sandbox-system).
    • A saída é permitida para a Internet pública, mas a saída para intervalos de LAN privados (RFC 1918), DNS de cluster interno (CoreDNS) e o servidor de metadados do provedor de nuvem (169.254.0.0/16) é explicitamente bloqueada.

    Para usar a federação de identidade da carga de trabalho para GKE ou acessar outros recursos particulares, é necessário definir políticas de rede personalizadas no recurso SandboxTemplate. Para detalhes de configuração e modelos personalizáveis (como sandboxes com isolamento físico ou integração da Federação de Identidade da Carga de Trabalho para GKE), consulte Gerenciamento de políticas de rede do Agent Sandbox.

Políticas de segurança do sandbox

Por padrão, o Agent Sandbox no GKE não aplica políticas de segurança aos sandboxes. Para ajudar a aplicar as configurações de isolamento dos sandboxes, aplique a secure-sandbox-policy política de admissão de validação (VAP, na sigla em inglês) do Kubernetes recomendada no repositório do GitHub do Agent Sandbox. Para instruções, consulte Aplicar a política de segurança recomendada.

A política aplica requisitos de isolamento, como exigir o gVisor, desativar hostNetwork e bloquear volumes hostPath. A política também aplica requisitos de proteção, como descartar todos os recursos, impedir a adição de novos recursos e exigir que os contêineres sejam executados como não raiz e definam limites de recursos. Para ver a lista completa de requisitos, consulte Requisitos de implantação do Agent Sandbox no GKE.

Modificar ou remover restrições de política

Como você aplica a política, é possível alterá-la para se adequar às suas cargas de trabalho. Se as cargas de trabalho exigirem isenções de algumas das regras, modifique a política para remover restrições específicas ou exclua totalmente a vinculação de política. A remoção de uma restrição reduz o isolamento fornecido pela política. Portanto, remova apenas as restrições exigidas pelas cargas de trabalho.

Para modificar a política e remover uma restrição específica (por exemplo, para permitir que os contêineres sejam executados como raiz ou omitir limites de recursos), edite o recurso ValidatingAdmissionPolicy:

kubectl edit validatingadmissionpolicy secure-sandbox-policy

No editor de texto que será aberto, localize a seção validations e remova ou modifique a expressão de restrição que bloqueia sua carga de trabalho.

Como alternativa, se você quiser interromper a aplicação da política no cluster, exclua a vinculação de política:

kubectl delete validatingadmissionpolicybinding secure-sandbox-binding

Problemas conhecidos

Nesta seção, descrevemos problemas conhecidos ao usar o Agent Sandbox no GKE e como resolvê-los ou contorná-los.

A política de segurança bloqueia recursos ao usar uma malha de serviço

Se você aplicou a política de segurança recomendada e tentar implantar um sandbox que se integra a um arquivo secundário de malha de serviço (por exemplo, Envoy ou Istio), a criação do sandbox poderá ser bloqueada pela política com um erro como este:

sandbox create error: sandboxes.agents.x-k8s.io "claude-cli-claim-managed" is forbidden:
ValidatingAdmissionPolicy 'secure-sandbox-policy' with binding 'secure-sandbox-binding'
denied request: Security Violation: Capabilities.add must be empty. You cannot add capabilities.
  • Causa: os sidecars de malha de serviço geralmente usam um contêiner de inicialização, como istio-init ou proxy-init. Esses contêineres de inicialização exigem recursos como NET_ADMIN ou NET_RAW para configurar regras iptables para roteamento de saída transparente. A ValidatingAdmissionPolicy secure-sandbox-policy bloqueia todas as adições de recursos em todos os tipos de contêiner.
  • Solução alternativa: como você gerencia essa política no cluster, é possível modificar o ValidatingAdmissionPolicy para permitir que contêineres de inicialização confiáveis específicos solicitem recursos NET_ADMIN e NET_RAW. Para instruções sobre como modificar ou remover restrições de política, consulte Modificar ou remover restrições de política. Por exemplo, é possível atualizar as expressões de validação ou as variáveis da política para isentar nomes de contêineres confiáveis da regra de recursos.

Latência de saída ou tempo limite ao se conectar às APIs do Google por IPv6

As cargas de trabalho dentro do sandbox podem apresentar tempos limite de conexão ou alta latência, de até dois minutos, ao tentar se conectar a recursos externos ou APIs do Google (como Vertex AI ou Cloud Storage).

  • Causa: se o cluster do GKE tiver o IPv6 de pilha dupla ativado, a resolução de DNS para as APIs do Google vai retornar endereços IPv4 (A) e IPv6 (AAAA). Alguns algoritmos em mecanismos de ambiente de execução, como o Node.js, tentam se conectar primeiro por IPv6. Se a VPC do GKE não tiver uma rota de saída IPv6 válida, como um Cloud NAT ou um gateway de Internet para IPv6, a conexão TCP vai parar de responder até que o tempo limite do TCP SYN expire. Em seguida, a conexão TCP volta para o IPv4.
  • Resolução: para resolver esse problema, siga uma das seguintes recomendações:

    • Configurar a saída IPv6: para permitir que o tráfego IPv6 de saída retorne ao cluster, configure um Cloud NAT IPv6 válido ou um gateway de Internet na rede VPC.
    • Preferir IPv4 na carga de trabalho: para preferir a resolução de DNS IPv4, configure o ambiente de execução da carga de trabalho. Por exemplo, em um aplicativo Node.js, é possível definir as seguintes variáveis de ambiente na definição de SandboxTemplate:

      env:
      - name: NODE_OPTIONS
        value: "--dns-result-order=ipv4first --no-network-family-autoselection"
      

Limpar recursos

Para evitar cobranças na sua conta do Google Cloud , exclua o cluster do GKE que você criou:

gcloud container clusters delete ${CLUSTER_NAME} \
    --location=${LOCATION} \
    --quiet

A seguir