Un container per task risolve l’isolamento, e lascia l’utente ad aspettare 45 secondi
Secondo articolo della serie sul sandbox per agenti. Un container per task sembra ovvio, e fa aspettare l’utente dai 45 ai 90 secondi dopo l’invio. Dove finiscono davvero quei secondi, e perché l’interfaccia costruita per amministrare un cluster non deve stare sul percorso che l’utente clicca.
L’articolo precedente finiva qui: con tutti i task stipati in un solo programma, un guasto li abbatte tutti, e il codice di chiunque può leggere i dati e le chiavi di chiunque.
La correzione è naturale — dare a ogni task un container tutto suo. Usa e getta, nessuno tocca nessuno.
Su Kubernetes si scrive con una facilità quasi imbarazzante. Tanta da far dubitare che l’articolo precedente non stesse esagerando.
Il codice: arriva un task, si costruisce un container
# arriva la richiesta → si chiede a K8s di costruire un nuovo container
v1.create_namespaced_pod(namespace="default", body=pod_manifest)
# poi si continua a chiedere «è pronto? è pronto?» — è l’attesa che subisce l’utente
while True:
pod = v1.read_namespaced_pod(name=task_id, namespace="default")
if pod.status.phase == "Running":
break
time.sleep(0.5) # chiedere troppo spesso mette in ginocchio il sistema di gestione
return {"time_to_interactive_seconds": round(time.time() - start_time, 2)}
L’isolamento è autentico: un container per task, uno sforamento di memoria uccide solo il proprio task, le chiavi non sono più condivise. I due muri dell’articolo precedente sono davvero spariti.
Poi si guarda l’ultima riga: registra quanto ha aspettato l’utente tra il clic e l’inizio effettivo del lavoro.
Da mezzo secondo a 45–90 secondi
Non è codice lento: c’è semplicemente una fila di commissioni da sbrigare prima.
| Dove finiscono i secondi | Chi è impegnato | Si può ottimizzare |
|---|---|---|
| Registrare il nuovo container | il registro del cluster scrive e conferma che ha tenuto | Quasi no |
| Scegliere una macchina | lo scheduler filtra, assegna punteggi, ne seleziona una | In parte |
| Scaricare l’immagine del programma | quella macchina scarica il pacchetto da un registry | Il pre-download aiuta, per le immagini note |
| Creare il container e collegare la rete | il runtime lo avvia, il plugin di rete assegna un IP | Quasi no |
| Il programma che si avvia | parte Python, si caricano le dipendenze | In parte |
Il primo istinto è incolpare la dimensione dell’immagine. Ma dopo il primo download l’immagine resta sulla macchina, e non diventa comunque abbastanza veloce da essere accettabile: il grosso è registrare, collocare, inizializzare — il ritmo intrinseco del sistema, non codice lento. Ecco perché «ottimizziamo l’immagine» esaurisce presto la strada: ottimizza l’unica fetta ottimizzabile.
Il ciclo «continua a chiedere» è la metà peggiore
Si guardi il commento: chiedere troppo spesso mette in ginocchio il sistema di gestione. Nel momento in cui si scrive quella riga, il problema ha cambiato natura.
Un’analogia. K8s ha due metà: un ufficio amministrativo che registra, approva e assegna risorse, e un reparto produttivo dove il lavoro accade davvero. Creare un container e controllarne lo stato sono entrambe pratiche da ufficio amministrativo. E un ufficio del genere è progettato per la burocrazia interna: senza fretta, ripetibile, e va bene se ci mette un momento.
Quello che fa questo codice è accompagnare ogni singolo cliente allo sportello dell’ufficio, e sollecitare ogni mezzo secondo.
Un cliente va bene. Una folla no:
- ogni richiesta in attesa controlla due volte al secondo: 100 persone insieme fanno 200 interrogazioni al secondo;
- ogni nuovo task va registrato, e registrare significa scrivere nel registro centrale e confermare che ha tenuto;
- prima resta indietro l’ufficio, poi rallentano le scritture sul registro — e quando quei due rallentano, rallenta l’intero cluster, compresi i carichi che con i tuoi agenti non c’entrano nulla.
La frase da conservare: l’interfaccia per amministrare il sistema serve all’amministrazione, non ai clic degli utenti. L’avvio a freddo è solo la prima fattura; il rischio vero è trascinare giù tutto il cluster.
Cosa stabilisce questo passo
Due cose valgono insieme:
- l’isolamento era giusto, non serve tornare indietro;
- costruire su richiesta è il tempismo sbagliato: non si inizia a costruire quando l’ospite è già arrivato.
La mossa successiva è obbligata: spostare la costruzione a prima dell’arrivo dell’utente. Tenere pronti dei container in attesa, e lasciare che la richiesta ne occupi uno.
L’attesa scende da 45 secondi a una frazione di secondo. E quel gruppo di container fermi comincia a bruciare denaro al minuto. Il prossimo articolo fa quel conto.
In una riga: l’errore non era l’isolamento, ma aspettare l’utente prima di prepararsi.
Codice: agent-sandbox-oss/lab2 — un solo file, ed eseguirlo una volta convince più che leggerne i numeri.
- Kubernetes
- AI Agent
- Avvio a freddo
- Cloud Native
- Architettura