Esecuzione del codice in Cloud Run

Cloud Run è già in sandbox e isolato, il che lo rende ideale per l'hosting di agenti di AI. Quando attivi le sandbox di Cloud Run, lo strumento a riga di comando sandbox diventa disponibile nel tuo container. Utilizza questo strumento a riga di comando per eseguire codice non attendibile scritto in qualsiasi linguaggio, in un ambiente sandbox altamente ottimizzato, isolato dal resto del container.

Gli agenti AI possono sfruttare le sandbox per eseguire in modo sicuro i subagenti, eseguire attività di calcolo o aprire browser in un ambiente veloce e isolato senza rischiare di danneggiare il sistema host.

Le sandbox Cloud Run offrono i seguenti vantaggi principali:

  • Creazione rapida: le sandbox sono interattive e pronte a eseguire i comandi quasi istantaneamente. Se crei sandbox all'interno di una risorsa Cloud Run esistente in cui viene eseguito l'agente, riduci i tempi di creazione rispetto alla creazione di una nuova risorsa Cloud Run per ogni attività. Questa efficienza contribuisce a garantire che l'agente rimanga reattivo.

  • Sicurezza: le sandbox isolano l'esecuzione dei processi. Per impostazione predefinita, le sandbox non hanno accesso al carico di lavoro principale, alle variabili di ambiente, ai secret o al server di metadati Google Cloud . Tutte le sandbox sono completamente isolate l'una dall'altra.

  • Controllo dell'accesso e ambiente: i processi vengono eseguiti con privilegi sudo come utente non root, consentendoti di installare strumenti utilizzando gestori di pacchetti come apt, pip o npm durante l'esecuzione. Sebbene l'ambiente sandbox sia temporaneo ed eliminato al termine, puoi utilizzare directory persistenti o snapshot per salvare spazi di lavoro specifici o mappare i dati su un bucket Cloud Storage.

Prima di iniziare

  1. Accedi al tuo account Google Cloud . Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei carichi di lavoro.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. Installa e inizializza gcloud CLI.
  7. Esegui il deployment di un servizio Cloud Run nell'ambiente di esecuzione di seconda generazione.

Abilitare le sandbox

Quando abiliti le sandbox, il servizio Cloud Run viene sottoposto a deployment nell'ambiente di esecuzione di seconda generazione. Per attivare le sandbox nei servizi Cloud Run, utilizza Google Cloud CLI o una configurazione YAML:

gcloud

Per eseguire il deployment o l'aggiornamento del servizio, specifica il flag --sandbox-launcher:

  • Per eseguire il deployment di un nuovo servizio, esegui questo comando:

    gcloud beta run deploy SERVICE --image IMAGE_URL --sandbox-launcher

    Sostituisci quanto segue:

    • SERVICE: il nome del tuo servizio Cloud Run.
    • IMAGE_URL: un riferimento all'immagine container, ad esempio us-docker.pkg.dev/cloudrun/container/hello:latest. Se utilizzi Artifact Registry, il repository REPO_NAME deve essere già stato creato. L'URL segue il formato LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
  • Per aggiornare un servizio esistente, esegui questo comando:

    gcloud beta run services update SERVICE --sandbox-launcher

YAML

  1. Se stai creando un nuovo servizio, salta questo passaggio. Se stai aggiornando un servizio esistente, scarica la relativa configurazione YAML:

    gcloud run services describe SERVICE --format export > service.yaml
  2. Aggiorna il file YAML del servizio in modo da includere l'attributo sandboxLauncher impostato su true all'interno della configurazione del container:

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: SERVICE
      annotations:
        run.googleapis.com/launch-stage: BETA
    spec:
      template:
        spec:
          containers:
          - name: CONTAINER
            image: IMAGE_URL
            sandboxLauncher: true
            port: 8080
    

    Sostituisci quanto segue:

    • SERVICE: il nome del tuo servizio Cloud Run.
    • CONTAINER: il nome del contenitore.
    • IMAGE_URL: un riferimento all'immagine container, ad esempio us-docker.pkg.dev/cloudrun/container/hello:latest. Se utilizzi Artifact Registry, il repository REPO_NAME deve essere già stato creato. L'URL segue il formato LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
  3. Crea o aggiorna il servizio utilizzando il seguente comando:

    gcloud run services replace service.yaml

    Il comando gcloud run services replace utilizza per impostazione predefinita il file service.yaml, se presente.

I sandbox condividono la CPU e la memoria allocate al container host. Assicurati che i limiti principali del container per CPU e memoria siano sufficienti per ospitare sia l'applicazione sia le sandbox attive che esegui contemporaneamente.

Disattivare le sandbox

Per disattivare la possibilità di avviare una sandbox nel tuo servizio, utilizza Google Cloud CLI o una configurazione YAML:

gcloud

Aggiorna il servizio utilizzando il flag --no-sandbox-launcher eseguendo questo comando:

gcloud beta run services update SERVICE --no-sandbox-launcher

Sostituisci SERVICE con il nome del servizio.

YAML

  1. Se stai creando un nuovo servizio, salta questo passaggio. Se stai aggiornando un servizio esistente, scarica la relativa configurazione YAML:

    gcloud run services describe SERVICE --format export > service.yaml
  2. Aggiorna il file YAML del servizio per rimuovere l'attributo sandboxLauncher all'interno della configurazione del container:

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: SERVICE
    spec:
      template:
        spec:
          containers:
          - name: CONTAINER
            image: IMAGE_URL
            port: 8080
    

    Sostituisci quanto segue:

    • SERVICE: il nome del tuo servizio Cloud Run.
    • CONTAINER: il nome del contenitore.
    • IMAGE_URL: un riferimento all'immagine container, ad esempio us-docker.pkg.dev/cloudrun/container/hello:latest. Se utilizzi Artifact Registry, il repository REPO_NAME deve essere già stato creato. L'URL segue il formato LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
  3. Crea o aggiorna il servizio utilizzando il seguente comando:

    gcloud run services replace service.yaml

    Il comando gcloud run services replace utilizza per impostazione predefinita il file service.yaml, se presente.

Avviare le sandbox

Dopo aver attivato le sandbox, puoi avviarle dall'ambiente di esecuzione del container. Il binario della sandbox si trova in /usr/local/gcp/bin/sandbox.

Puoi eseguire il file binario facendo riferimento al suo percorso assoluto nel codice sorgente. Ad esempio, per stampare Hello all'interno della sandbox isolata, scegli una delle seguenti opzioni:

Node.js

Per eseguire il comando sandbox da un'applicazione Node.js, includi il seguente codice:

exec(`/usr/local/gcp/bin/sandbox do -- /bin/echo "Hello"`, (e, stdout, stderr) => {
    res.send({ stdout, stderr });
});

Python

Per eseguire il comando sandbox da un'applicazione Python, includi il seguente codice:

import subprocess
result = subprocess.run(
    ["/usr/local/gcp/bin/sandbox", "do", "--", "/bin/echo", "Hello"],
    capture_output=True,
    text=True,
)
return {"stdout": result.stdout, "stderr": result.stderr}

Go

Per eseguire il comando sandbox da un'applicazione Go, includi il seguente codice:

cmd := exec.Command("/usr/local/gcp/bin/sandbox", "do", "--", "/bin/echo", "Hello")
out, err := cmd.CombinedOutput()

Interfaccia a riga di comando di Sandbox

Per eseguire il comando sandbox direttamente dalla riga di comando, esegui questo comando:

/usr/local/gcp/bin/sandbox do -- /bin/echo "Hello"

Gli esempi in questa guida utilizzano il comando sandbox anziché il percorso assoluto /usr/local/gcp/bin/sandbox.

Per visualizzare l'elenco completo dei comandi disponibili, esegui il comando /usr/local/gcp/bin/sandbox -h.

Utilizzare le funzionalità della riga di comando della sandbox

Lo strumento a riga di comando sandbox contiene comandi per eseguire, configurare e gestire sandbox.

Esegui un comando nel sandbox

Puoi eseguire un'istruzione in una nuova sandbox effimera utilizzando il comando sandbox do. Il comando sandbox do esegue le seguenti attività:

  1. Crea un ambiente sandbox (sandbox run).
  2. Esegue il comando specificato (sandbox exec).
  3. Elimina la sandbox dopo l'esecuzione riuscita (sandbox delete).

Ad esempio, per eseguire un calcolo matematico all'interno della sandbox, esegui i seguenti snippet di codice per la lingua che preferisci. Assicurati che qualsiasi comando o strumento che esegui, ad esempio python3, sia installato nell'immagine container:

Node.js

Per eseguire il comando sandbox da un'applicazione Node.js:

exec(`sandbox do -- /usr/bin/python3 -c "print(1+2)"`, (e, stdout, stderr) => {
    res.send({ stdout, stderr });
});

Python

Per eseguire il comando sandbox da un'applicazione Python:

import subprocess
result = subprocess.run(
    ["sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)"],
    capture_output=True,
    text=True,
)
return {"stdout": result.stdout, "stderr": result.stderr}

Go

Per eseguire il comando sandbox da un'applicazione Go:

cmd := exec.Command("sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)")
out, err := cmd.CombinedOutput()

Interfaccia a riga di comando di Sandbox

Per eseguire il comando sandbox direttamente dalla riga di comando:

sandbox do -- /usr/bin/python3 -c "print(1+2)"

Se esegui un comando per nome senza il percorso assoluto, ad esempio python3 anziché /usr/bin/python3, configura esplicitamente la variabile di ambiente PATH nel sandbox utilizzando il flag --env.

Mantenere i dati tra esecuzioni diverse

Le sandbox sono effimere per impostazione predefinita. Per rendere persistenti i dati tra diverse esecuzioni sandbox all'interno della stessa istanza Cloud Run, puoi importare ed esportare lo stato del file system dello spazio di lavoro utilizzando file di archivio tar standard. In alternativa, puoi configurare i montaggi bind per condividere le directory direttamente tra il container host e gli ambienti sandbox.

Utilizza i seguenti flag quando esegui il comando sandbox do:

  • --export-tar: acquisisce i file di overlay modificati in un file di archivio tar al termine dell'operazione.
  • --import-tar: estrae i file da un file di archivio tar nella sandbox prima dell'esecuzione.
  • --sync-tar: esegue una sincronizzazione bidirezionale importando prima dell'esecuzione ed esportando al termine.

Ad esempio, per trasferire dati tra due chiamate sandbox utilizzando file di archivio, esegui questi comandi:

  1. Scrivi i dati all'interno di una sandbox ed esporta lo stato in un file di archivio:

    sandbox do --write --export-tar=/tmp/work.tar \
      -- /usr/bin/bash -c "mkdir -p /tmp/work && echo 'task-complete' > /tmp/work/status.txt"
    
  2. Importa il file di archivio in una chiamata successiva per recuperare i dati:

    sandbox do --write --import-tar=/tmp/work.tar \
      -- /usr/bin/bash -c "cat /tmp/work/status.txt"
    

In alternativa, per importare automaticamente lo stato dell'archivio esistente ed esportare le nuove modifiche in un unico comando, utilizza --sync-tar=/tmp/work.tar. Quando un processo sandbox termina, Cloud Run elimina definitivamente i file di overlay temporanei che non sono stati esportati in un file di archivio.

Eseguire un comando in background

Per eseguire processi di lunga durata, browser headless o server di background, ad esempio un ciclo di agenti di background che ascolta continuamente le richieste in entrata, utilizza il flag --detach.

Ad esempio, esegui questo comando per avviare una sandbox separata con un programma inattivo o in background:

sandbox run my-web-server --detach -- /usr/bin/long_running_or_idle_program

Puoi utilizzare il flag detach per riutilizzare la stessa sandbox per più test. Per interagire o eseguire comandi aggiuntivi all'interno di una sandbox detached in esecuzione, utilizza il comando sandbox exec e scegli come target la sandbox in base al nome.

Ad esempio, per eseguire un comando di test all'interno della sandbox in background my-web-server esistente, esegui questo comando:

sandbox exec my-web-server -- /usr/bin/python3 -c "print('test-complete')"

Configura le variabili di ambiente

Configura le variabili di ambiente nelle sandbox come faresti con qualsiasi altro container. Le sandbox non ereditano le variabili di ambiente dal container host. Devi fornirli esplicitamente utilizzando il flag --env quando esegui il comando sandbox.

Ad esempio, per passare una variabile di configurazione in una sandbox, esegui questo comando:

sandbox do --env AGENT_MODE="test" -- /usr/bin/bash -c "echo \$AGENT_MODE"

Evita di passare i secret utilizzando il flag env, in quanto potrebbero essere visibili ai processi sandbox.

Crea snapshot del file system

Esegui il deployment di una sandbox denominata in background per gestire attività continue come server web o flussi di lavoro degli agenti a esecuzione prolungata, esegui dinamicamente i comandi sulla sandbox e acquisisci il relativo stato del file system modificato in un file di archivio tar.

Ad esempio, per eseguire il deployment di una sandbox in background, scrivere un file nella relativa overlay e creare uno snapshot del relativo stato per verificare che i dati siano stati acquisiti, esegui questi comandi:

  1. Esegui il deployment di una sandbox denominata in background con l'accesso in scrittura abilitato, creando un file all'interno del relativo workspace:

    sandbox run --write my-sandbox --detach -- /usr/bin/bash -c "echo 'hi' > /tmp/hello.txt && sleep 1h"
    
  2. Crea uno snapshot del file system modificato della sandbox in esecuzione utilizzando il comando sandbox tar:

    sandbox tar my-sandbox --file=/tmp/foo.tar
    
  3. Estrai e verifica che il file di archivio dell'istantanea contenga i dati scritti all'interno della sandbox:

    tar -xvf /tmp/foo.tar
    

    Dovresti vedere i seguenti risultati:

    ./
    ./tmp/
    ./tmp/hello.txt
    

Configura il networking

Per impostazione predefinita, tutto il traffico in uscita dal sandbox viene bloccato. Per consentire l'accesso alla rete in uscita, utilizza il flag --allow-egress:

Ad esempio, per recuperare i dati da un endpoint esterno, esegui questo comando:

sandbox do --allow-egress -- /usr/bin/python3 -c 'import urllib.request; print(urllib.request.urlopen("https://google.com").getcode())'

Questo comando restituisce il codice di stato HTTP standard 200, che indica una connessione riuscita.

Accedere al file system

Per impostazione predefinita, i processi eseguiti all'interno della sandbox hanno accesso in sola lettura al file system root del container host. Puoi utilizzare il flag --write per abilitare la scrittura in un overlay del file system temporaneo (tmpfs). Tuttavia, le scritture andranno perse quando la sandbox viene eliminata. Per abilitare la scrittura permanente nel container host, puoi configurare i montaggi di binding.

Accesso predefinito di sola lettura

All'interno della sandbox, i processi possono leggere i file dal container host e non possono scrivere nel file system principale.

I seguenti esempi presuppongono che tu stia eseguendo i comandi dalla directory root (/) del container host.

Per verificare l'accesso in sola lettura predefinito, esegui questi comandi:

  1. Crea uno script Python nel container host:

    mkdir -p /tmp/my-scripts
    echo "print('hi')" > /tmp/my-scripts/task.py
    
  2. Verifica che il file esista localmente:

    cat /tmp/my-scripts/task.py
    
  3. Esegui il file all'interno della sandbox:

    sandbox do -- /usr/bin/python3 /tmp/my-scripts/task.py
    

    Questo comando restituisce hi, confermando che la sandbox ha accesso in lettura.

    Se tenti di scrivere dati direttamente nel file system radice della sandbox senza configurazione aggiuntiva, l'esecuzione non riesce. Ad esempio, il tentativo di scrittura in /tmp all'interno della sandbox predefinita restituisce un errore del file system di sola lettura:

    Esegui questo comando per scrivere nel file system root:

    sandbox do -- /usr/bin/bash -c "echo 'hi' > /tmp/testfile.txt"
    

    Il comando non va a buon fine e viene visualizzato il seguente errore:

    /usr/bin/bash: line 1: /tmp/testfile.txt: Read-only file system
    Error: failed to exec in container: cmd.Wait(exec) failed: exit status 1
    

Condividere i dati utilizzando i bind mount

Per consentire ai processi all'interno della sandbox di scrivere dati persistenti, collega un volume condiviso utilizzando il flag --mount:

  1. Crea una directory di volumi condivisi nel container host e inserisci un file iniziale:

    mkdir -p /tmp/my-volume
    echo 'read' > /tmp/my-volume/readwrite.txt
    
  2. Esegui la sandbox per leggere il file dal percorso di montaggio bind:

    sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount -- /usr/bin/bash -c "cat /mnt/my-mount/readwrite.txt"
    

    Questo comando restituisce read.

  3. Esegui la sandbox per riscrivere i nuovi dati nell'host dall'interno del punto di montaggio:

    sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount -- /usr/bin/bash -c "echo 'write' > /mnt/my-mount/readwrite.txt"
    
  4. Verifica nel container host che la sandbox abbia modificato correttamente il file:

    cat /tmp/my-volume/readwrite.txt
    

    Questo comando restituisce write.

Configura i montaggi di sola lettura

Per concedere alla sandbox l'accesso a una directory host impedendo esplicitamente la modifica dei file, aggiungi l'attributo readonly alla specifica di montaggio.

Ad esempio, esegui questo comando per testare le restrizioni di scrittura su un montaggio bind di sola lettura:

sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount,readonly -- /usr/bin/bash -c "echo 'fails' > /mnt/my-mount/hello.txt"

Il tentativo di scrittura non riesce e viene visualizzato il seguente errore:

/usr/bin/bash: line 1: /mnt/my-mount/hello.txt: Read-only file system
Error: failed to exec in container: cmd.Wait(exec) failed: exit status 1

Visualizza i log

Cloud Run acquisisce automaticamente gli eventi del ciclo di vita della sandbox, come gli avvii e le uscite dell'esecuzione, in Cloud Logging.

La CLI sandbox scrive l'output standard (stdout) e l'errore standard (stderr) dai comandi in sandbox direttamente ai flussi standard del processo di chiamata. Per visualizzare questi log in Cloud Logging, indirizza i flussi all'output standard e all'errore standard del container:

Node.js

const { exec } = require('child_process');
const child = exec('sandbox do -- /usr/bin/python3 -c "print(1+2)"');
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);

Python

subprocess.run(
    ["sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)"],
    stdout=sys.stdout,
    stderr=sys.stderr,
)

Go

cmd := exec.Command("sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()

Passaggi successivi