Isoler l'exécution du code d'IA avec Agent Sandbox

Vous pouvez déployer un environnement de développement pour utiliser le client Python Agent Sandbox sur un cluster Google Kubernetes Engine (GKE). Cette configuration vous aide à exécuter et à tester du code généré par l'IA de manière sécurisée en isolant le code non fiable dans un environnement Python en bac à sable. Cette isolation est essentielle pour protéger votre système contre les failles potentielles du code généré par l'IA, accélérer le développement et garantir des déploiements sécurisés. Pour obtenir une présentation de la façon dont la fonctionnalité Agent Sandbox isole le code non approuvé généré par l'IA, consultez À propos de GKE Agent Sandbox.

Coûts

Agent Sandbox est proposé sans frais supplémentaires dans GKE. La tarification GKE s'applique aux ressources que vous créez.

Avant de commencer

  1. Dans la console Google Cloud , sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud .

    Rôles requis pour sélectionner ou créer un projet

    • Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
    • Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (roles/resourcemanager.projectCreator), qui contient l'autorisation resourcemanager.projects.create. Découvrez comment attribuer des rôles.

    Accéder au sélecteur de projet

  2. Vérifiez que la facturation est activée pour votre projet Google Cloud .

  3. Activez les API Artifact Registry et Kubernetes Engine si ce n'est pas déjà fait.

    Rôles requis pour activer les API

    Pour activer les API, vous devez disposer de l'autorisation serviceusage.services.enable. Si vous avez créé le projet, vous disposez probablement déjà de cette autorisation grâce au rôle Propriétaire (roles/owner). Sinon, vous pouvez obtenir cette autorisation grâce au rôle Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin). Découvrez comment attribuer des rôles.

    Activer les API

  4. Dans la console Google Cloud , activez Cloud Shell.

    Activer Cloud Shell

  5. Vérifiez que vous disposez des autorisations requises pour suivre les instructions de ce document.
  6. Vous devez disposer d'un cluster GKE sur lequel la fonctionnalité Agent Sandbox est activée. Si vous n'en avez pas, suivez les instructions de la section Activer Agent Sandbox sur GKE pour créer un cluster ou en mettre à jour un existant.

Rôles requis

Pour obtenir les autorisations nécessaires pour créer et gérer des bacs à sable, demandez à votre administrateur de vous accorder le rôle IAM Administrateur Kubernetes Engine (roles/container.admin) sur votre projet. Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.

Définir des variables d'environnement

Pour simplifier les commandes que vous exécutez dans ce document, vous pouvez définir des variables d'environnement dans Cloud Shell. Dans Cloud Shell, définissez les variables d'environnement utiles suivantes en exécutant les commandes suivantes :

export PROJECT_ID=$(gcloud config get project)
export CLUSTER_NAME="agent-sandbox-cluster"
export LOCATION="us-central1"
export NODE_POOL_NAME="agent-sandbox-node-pool"
export MACHINE_TYPE="e2-standard-2"

Voici une explication de ces variables d'environnement :

  • PROJECT_ID : ID de votre projet Google Cloud actuel. La définition de cette variable permet de s'assurer que toutes les ressources, comme votre cluster GKE, sont créées dans le bon projet.
  • CLUSTER_NAME : nom de votre cluster GKE, par exemple agent-sandbox-cluster.
  • LOCATION : région ou zone Google Cloud dans laquelle se trouve votre cluster GKE. Définissez cette valeur sur la région (par exemple, us-central1) si vous utilisez un cluster Autopilot, ou sur la zone (par exemple, us-central1-a) si vous utilisez un cluster Standard.
  • NODE_POOL_NAME : nom du pool de nœuds qui exécutera les charges de travail en bac à sable (par exemple, agent-sandbox-node-pool).
  • MACHINE_TYPE : type de machine des nœuds de votre pool de nœuds, par exemple e2-standard-2. Pour en savoir plus sur les différentes séries de machines et sur le choix entre les différentes options, consultez le Guide des ressources de familles de machines et guide comparatif.

Déployer un environnement de bac à sable

Cette section explique comment créer le blueprint du bac à sable (SandboxTemplate), déployer le routeur réseau nécessaire et installer le client Python que vous utiliserez pour interagir avec le bac à sable.

La méthode recommandée pour créer votre bac à sable et interagir avec lui consiste à utiliser le client Python Agentic Sandbox. Ce client fournit une interface qui simplifie l'ensemble du cycle de vie d'un bac à sable, de la création au nettoyage. Il s'agit d'une bibliothèque Python que vous pouvez utiliser pour créer, utiliser et supprimer des bacs à sable de manière programmatique.

Le client utilise un routeur bac à sable comme point d'entrée central pour tout le trafic. Dans l'exemple décrit dans ce document, le client crée un tunnel vers ce routeur à l'aide de la commande kubectl port-forward, de sorte que vous n'avez pas besoin d'exposer d'adresses IP publiques. Sachez que l'utilisation de kubectl port-forward n'est pas une solution sécurisée et doit être limitée aux environnements de développement.

Créer un SandboxTemplate et un SandboxWarmPool

Vous allez maintenant définir la configuration de votre bac à sable en créant une ressource SandboxTemplate et une ressource SandboxWarmPool. SandboxTemplate sert de plan réutilisable que le contrôleur Agent Sandbox utilise pour créer des environnements bac à sable cohérents et préconfigurés. La ressource SandboxWarmPool permet de s'assurer qu'un nombre spécifié de pods pré-chauffés sont toujours en cours d'exécution et prêts à être revendiqués. Un bac à sable préchauffé est un pod en cours d'exécution qui est déjà initialisé. Cette pré-initialisation permet de créer des bacs à sable en moins d'une seconde et évite la latence de démarrage d'un bac à sable standard :

  1. Dans Cloud Shell, créez un fichier nommé sandbox-template-and-pool.yaml et contenant ce qui suit :

    apiVersion: extensions.agents.x-k8s.io/v1beta1
    kind: SandboxTemplate
    metadata:
      name: python-runtime-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-runtime-template
    
  2. Appliquez les fichiers manifestes SandboxTemplate et SandboxWarmPool :

    kubectl apply -f sandbox-template-and-pool.yaml
    

Déployer le routeur de bac à sable

Le client Python que vous utiliserez pour créer des environnements bac à sable et interagir avec eux utilise un composant appelé routeur de bac à sable pour communiquer avec les bacs à sable.

Pour cet exemple, vous allez utiliser le mode développeur du client pour les tests. Ce mode est destiné au développement local et utilise la commande kubectl port-forward pour établir un tunnel direct entre votre machine locale et le service Sandbox Router exécuté dans le cluster. Cette approche de tunneling évite d'avoir besoin d'une adresse IP publique ou d'une configuration d'entrée complexe, et simplifie l'interaction avec les bacs à sable depuis votre environnement local.

Pour déployer le routeur Sandbox :

  1. Dans Cloud Shell, créez un fichier nommé sandbox-router.yaml avec le contenu suivant :

    # A ClusterIP Service to provide a stable endpoint for the router pods.
    apiVersion: v1
    kind: Service
    metadata:
      name: sandbox-router-svc
      namespace: default
    spec:
      type: ClusterIP
      selector:
        app: sandbox-router
      ports:
      - name: http
        protocol: TCP
        port: 8080 # The port the service will listen on
        targetPort: 8080 # The port the router container listens on (from the sandbox_router/Dockerfile)
    ---
    # The Deployment to manage and run the router pods.
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sandbox-router-deployment
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sandbox-router
      template:
        metadata:
          labels:
            app: sandbox-router
        spec:
          # Ensure pods are spread across different zones for HA
          topologySpreadConstraints:
            - maxSkew: 1
              topologyKey: topology.kubernetes.io/zone
              whenUnsatisfiable: ScheduleAnyway
              labelSelector:
                matchLabels:
                  app: sandbox-router
          containers:
          - name: router
            image: us-central1-docker.pkg.dev/k8s-staging-images/agent-sandbox/sandbox-router:latest-main
            ports:
            - containerPort: 8080
            readinessProbe:
              httpGet:
                path: /healthz
                port: 8080
              initialDelaySeconds: 5
              periodSeconds: 5
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8080
              initialDelaySeconds: 10
              periodSeconds: 10
            resources:
              requests:
                cpu: "100m"
                memory: "512Mi"
              limits:
                cpu: "1000m"
                memory: "1Gi"
          securityContext:
            runAsUser: 1000
            runAsGroup: 1000
    
  2. Appliquez le fichier manifeste pour déployer le routeur sur votre cluster :

    kubectl apply -f sandbox-router.yaml
    
  3. Vérifiez que le déploiement du routeur Sandbox s'exécute correctement :

    kubectl get deployment sandbox-router-deployment
    

    Attendez que le déploiement affiche 2/2 ou 1/1 dans la colonne READY.

Installer le client Python

Maintenant que les composants du cluster, comme le routeur Sandbox, sont déployés, la dernière étape préparatoire consiste à installer le client Python Agentic Sandbox sur votre machine locale. Rappelez-vous que ce client est une bibliothèque Python qui vous permet de créer, d'utiliser et de supprimer des bacs à sable de manière programmatique. Vous l'utiliserez dans la section suivante pour tester l'environnement :

  1. Créez et activez un environnement virtuel Python :

    python3 -m venv .venv
    source .venv/bin/activate
    
  2. Installez le package client :

    pip install k8s-agent-sandbox
    

Tester le bac à sable

Maintenant que tous les composants de configuration sont en place, vous pouvez créer un bac à sable et interagir avec lui à l'aide du client Python Agentic Sandbox.

  1. Dans votre répertoire agent-sandbox, créez un script Python nommé test_sandbox.py avec le contenu suivant :

    from k8s_agent_sandbox import SandboxClient
    from k8s_agent_sandbox.models import SandboxLocalTunnelConnectionConfig
    
    # Automatically tunnels to svc/sandbox-router-svc
    client = SandboxClient(
        connection_config=SandboxLocalTunnelConnectionConfig()
    )
    
    sandbox = client.create_sandbox(template="python-runtime-template", 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. Depuis votre terminal (avec l'environnement virtuel toujours actif), exécutez le script de test :

    python3 test_sandbox.py
    

Le message "Hello from the sandboxed environment!" (Bonjour depuis l'environnement de bac à sable !) doit s'afficher.

Félicitations ! Vous avez exécuté une commande shell dans un bac à sable sécurisé. La méthode sandbox.run() vous permet d'exécuter n'importe quelle commande shell. L'Agent Sandbox exécute la commande dans une barrière sécurisée qui protège les nœuds de votre cluster et les autres charges de travail contre le code non fiable. Cela permet à un agent IA ou à tout workflow automatisé d'exécuter des tâches de manière sécurisée et fiable.

Lorsque vous exécutez le script, SandboxClient gère toutes les étapes pour vous. Il crée la ressource SandboxClaim pour démarrer le bac à sable, attend que le bac à sable soit prêt, puis utilise la méthode sandbox.run() pour exécuter des commandes de shell bash dans le conteneur sécurisé. Le client capture et imprime ensuite le stdout de cette commande. Le bac à sable est automatiquement supprimé après l'exécution du programme.

Lorsqu'une ressource SandboxClaim est créée, un pod disponible est attribué à partir du pool de préchauffage à l'objet Sandbox, et la revendication est marquée comme prête. Le SandboxWarmPool se réapprovisionne ensuite automatiquement pour maintenir le nombre d'instances répliquées configuré.

Pour vérifier si un bac à sable spécifique est revendiqué ou disponible, consultez ownerReferences dans les métadonnées du pod du bac à sable. Si la valeur du champ kind est Sandbox, le pod est utilisé. Si la valeur du champ kind est SandboxWarmPool, le pod est inactif et en attente d'être revendiqué.

Exécuter des bacs à sable en production

Dans ce document, vous interagissez avec les bacs à sable en dehors du cluster à l'aide de Cloud Shell. Le client Python utilise vos identifiants utilisateur pour s'authentifier auprès du cluster et gérer les ressources du bac à sable. Il utilise la commande kubectl port-forward pour établir une connexion avec les bacs à sable. Ces étapes fonctionnent bien pour les scénarios de développement.

Dans un scénario de production, une application de contrôleur (comme un orchestrateur d'IA) est chargée de créer et de gérer les ressources du bac à sable. Pour utiliser le bac à sable de l'agent en production, tenez compte des points suivants :

  • Authentification : votre application de contrôleur doit s'authentifier auprès du serveur d'API du cluster pour exécuter des bacs à sable. La façon dont vous configurez l'authentification dépend de l'endroit où l'application de contrôleur s'exécute, comme suit :

    • Si l'application de contrôleur s'exécute en tant que pod dans le même cluster, utilisez Kubernetes RBAC ou Workload Identity Federation for GKE avec des stratégies IAM pour accorder au compte de service Kubernetes du pod les autorisations nécessaires pour surveiller les bacs à sable ou découvrir les points de terminaison réseau.
    • Si l'application de contrôleur s'exécute en dehors du cluster, utilisez la fédération d'identité de charge de travail ou les comptes de service IAM pour attribuer une identité à l'application, que vous pourrez référencer dans les règles d'autorisation.
  • Routage : les requêtes du client Python dans votre application de contrôleur doivent atteindre le routeur Sandbox de votre cluster. En production, utilisez l'une des méthodes suivantes pour établir une connexion réseau :

    • Si l'application de contrôleur s'exécute dans le même cluster, utilisez la fonction SandboxDirectConnectionConfig pour cibler l'URL et le port utilisés par le service Sandbox Router.
    • Si l'application de contrôleur s'exécute en dehors du cluster, utilisez l'API GKE Gateway pour créer un équilibreur de charge interne ou externe. Dans votre code client, utilisez la fonction SandboxGatewayConnectionConfig pour faire référence à votre passerelle.

    Pour en savoir plus sur ces méthodes de routage, consultez les exemples d'utilisation sur GitHub et les étapes de déploiement de la passerelle pour le routeur.

  • Accès au bac à sable aux ressources Google Cloud  : si votre code de bac à sable doit envoyer des requêtes aux API Google Cloud , telles que Cloud Storage, utilisez une règle IAM avec Workload Identity Federation for GKE pour accorder au compte de service Kubernetes utilisé par le pod de bac à sable les autorisations requises pour cet accès. Étant donné que la règle de réseau par défaut bloque l'accès au serveur de métadonnées Google Cloud (169.254.169.254), vous devez personnaliser la règle de réseau pour autoriser ce trafic.

  • Restrictions concernant les règles de réseau : par défaut, Agent Sandbox applique une posture réseau Secure-by-Default stricte (networkPolicyManagement: Managed). Les restrictions suivantes s'appliquent dans cette posture :

    • L'entrée est bloquée pour toutes les sources, à l'exception du routeur sandbox désigné.
    • La sortie est autorisée vers l'Internet public, mais la sortie vers les plages de LAN privés (RFC 1918), le DNS interne du cluster (CoreDNS) et le serveur de métadonnées du fournisseur de cloud (169.254.0.0/16) est explicitement bloquée.

    Pour utiliser Workload Identity Federation for GKE ou accéder à d'autres ressources privées, vous devez définir des règles de réseau personnalisées dans SandboxTemplate. Pour obtenir des informations détaillées sur la configuration et des modèles personnalisables (tels que les bacs à sable isolés ou l'intégration de Workload Identity Federation for GKE), consultez Gestion des règles de réseau du bac à sable de l'agent.

Règles de sécurité du bac à sable

Pour contribuer à garantir un environnement sécurisé par défaut, le module complémentaire GKE Agent Sandbox utilise des règles de validation de l'admission Kubernetes (VAP) pour appliquer des contraintes de sécurité aux ressources Sandbox et SandboxTemplate. Ces règles sont appliquées automatiquement.

Pour plus de flexibilité, le module complémentaire divise l'application de la sécurité en un modèle de règles à deux niveaux. Les sections suivantes décrivent ces stratégies : la stratégie de base strictement gérée et la stratégie de renforcement personnalisable.

Règles de sécurité de base (sandbox-core-policy)

La règle de sécurité de base applique des exigences d'isolation qui contribuent à protéger l'intégrité du bac à sable. Cette règle inclut des règles qui exigent l'utilisation de gVisor, l'isolation du réseau (par exemple, la désactivation de hostNetwork) et l'isolation du système de fichiers (par exemple, le blocage de hostPath). Étant donné que GKE gère cette règle via le paramètre addonmanager.kubernetes.io/mode: Reconcile, vous ne pouvez pas modifier ni remplacer ces règles de base.

Renforcement de la règle de sécurité (sandbox-hardening-policy)

La stratégie de renforcement de la sécurité fournit des options de gestion et des bonnes pratiques de sécurité supplémentaires. Il applique des contraintes telles que la suppression de toutes les capacités, l'empêchement de l'ajout de nouvelles capacités et l'obligation d'exécuter les conteneurs en tant qu'utilisateur non racine avec des limites de ressources. GKE déploie cette règle en mode EnsureExists via le paramètre addonmanager.kubernetes.io/mode: EnsureExists. Ce paramètre signifie que GKE crée la règle si elle est manquante, mais vous pouvez la modifier ou la supprimer, ainsi que sa liaison, si nécessaire.

Modifier ou supprimer des contraintes de renforcement

Étant donné que la stratégie de renforcement est déployée en mode EnsureExists, GKE crée la stratégie si elle est manquante, mais n'écrase pas vos modifications. Si vos charges de travail nécessitent des exemptions à ces règles de renforcement, vous pouvez modifier la règle pour supprimer des contraintes spécifiques ou supprimer complètement l'association de règles.

Pour modifier la stratégie de renforcement et supprimer une contrainte spécifique (par exemple, pour autoriser les conteneurs à s'exécuter en tant que racine ou omettre les limites de ressources), modifiez la ressource ValidatingAdmissionPolicy :

kubectl edit validatingadmissionpolicy sandbox-hardening-policy

Dans l'éditeur de texte qui s'ouvre, recherchez la section validations, puis supprimez ou modifiez l'expression de contrainte qui bloque votre charge de travail.

Si vous souhaitez désactiver complètement la règle de renforcement pour votre cluster, supprimez la liaison de règle :

kubectl delete validatingadmissionpolicybinding sandbox-hardening-binding

Problèmes connus

Cette section décrit les problèmes connus lors de l'utilisation de l'Agent Sandbox dans GKE, ainsi que la manière de les résoudre ou de les contourner.

Une règle de sécurité bloque des fonctionnalités lors de l'utilisation d'un maillage de services

Si vous tentez de déployer un bac à sable qui s'intègre à un side-car de maillage de services (par exemple, Envoy ou Istio), la création du bac à sable peut être bloquée par la stratégie de sécurité renforcée avec une erreur semblable à la suivante :

sandbox create error: sandboxes.agents.x-k8s.io "claude-cli-claim-managed" is forbidden:
ValidatingAdmissionPolicy 'sandbox-hardening-policy' with binding 'sandbox-hardening-binding'
denied request: Security Violation: Capabilities.add must be empty. You cannot add capabilities.
  • Cause : les sidecars de maillage de services utilisent souvent un conteneur init, tel que istio-init ou proxy-init. Ces conteneurs d'initialisation nécessitent des capacités telles que NET_ADMIN ou NET_RAW pour configurer les règles iptables pour le routage de sortie transparent. Par défaut, le sandbox-hardening-policy GKE bloque tous les ajouts de capacités dans tous les types de conteneurs.
  • Solution de contournement : étant donné que la stratégie de renforcement GKE est déployée en mode EnsureExists, vous pouvez modifier ValidatingAdmissionPolicy pour autoriser des conteneurs init de confiance spécifiques à demander les capacités NET_ADMIN et NET_RAW. Pour savoir comment modifier ou supprimer ces contraintes de renforcement, consultez Modifier ou supprimer des contraintes de renforcement. Par exemple, vous pouvez mettre à jour les expressions ou variables de validation de la règle pour exempter les noms de conteneurs approuvés de la règle de capacités.

Latence ou délai avant expiration de la sortie lors de la connexion aux API Google via IPv6

Les charges de travail dans le bac à sable peuvent rencontrer des délais avant expiration de connexion ou une latence élevée (jusqu'à deux minutes) lorsqu'elles tentent de se connecter à des ressources externes ou à des API Google (telles que Vertex AI ou Cloud Storage).

  • Cause : si la double pile IPv6 est activée dans votre cluster GKE, la résolution DNS pour les API Google renvoie des adresses IPv4 (A) et IPv6 (AAAA). Certains algorithmes des moteurs d'exécution, tels que Node.js, tentent d'abord de se connecter via IPv6. Si votre VPC GKE ne dispose pas d'une route de sortie IPv6 valide, telle qu'une passerelle Cloud NAT ou Internet pour IPv6, la connexion TCP cesse de répondre jusqu'à l'expiration du délai avant expiration TCP SYN. La connexion TCP repasse ensuite à IPv4.
  • Résolution : pour résoudre ce problème, effectuez l'une des opérations suivantes :

    • Configurer la sortie IPv6 : pour autoriser le trafic IPv6 sortant à revenir au cluster, configurez une passerelle Cloud NAT ou Internet IPv6 valide dans votre réseau VPC.
    • Privilégier IPv4 dans la charge de travail : pour privilégier la résolution DNS IPv4, configurez l'exécution de votre charge de travail. Par exemple, dans une application Node.js, vous pouvez définir les variables d'environnement suivantes dans votre définition SandboxTemplate :

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

Effectuer un nettoyage des ressources

Pour éviter que des frais ne soient facturés sur votre compte Google Cloud , supprimez le cluster GKE que vous avez créé :

gcloud container clusters delete $CLUSTER_NAME --location=$LOCATION --quiet

Étapes suivantes