Distribuire su Kubernetes
Installa il server di Claude Managed Agents self-hosted e le sue sandbox su un cluster Kubernetes con i due chart Helm contenuti nell’archivio della release, poi esegui una prima sessione in un pod sandbox.
Questa pagina porta un cluster Google Kubernetes Engine (GKE) vuoto fino a una sessione che esegue uno strumento in un pod sandbox. Usa i due “Helm chart” (chart Helm) contenuti nell’archivio della release, che eseguono l’intero stack sul cluster:
cma-server: Applica lo schema del database ed esegue due server dietro un Service, nel namespacecma-server.cma-sandboxes: Esegue un dispatcher e i pod sandbox nel namespacecma. Il dispatcher interroga il server per ottenere lavoro e assegna a ogni sessione il proprio pod sandbox, dove un worker esegue gli strumenti di shell e di file dell’agente.
Il tuo database PostgreSQL resta al di fuori di entrambi. Su un altro tipo di cluster, i passaggi sono gli stessi, ma i prerequisiti del cluster e alcuni valori dei chart sono diversi. Consulta Altri cluster.
Prerequisiti
- Un cluster: Kubernetes 1.30 o successivo, con:
- Il controller Agent Sandbox (su GKE, l’add-on Agent Sandbox)
- Nodi che eseguono gVisor (su GKE, un pool di nodi GKE Sandbox)
- Un plugin di rete che applica le NetworkPolicy (su GKE, Dataplane V2 o Calico)
- Un database: PostgreSQL 16 o successivo raggiungibile dal cluster.
- Un registry: Uno da cui il cluster possa eseguire il pull. Le immagini le compili tu.
- Una chiave API di Claude: Il server la usa per le chiamate al modello. Per usare un altro provider, consulta Provider di inferenza.
- Permessi: Diritti di cluster-admin o equivalenti. L’installazione crea namespace, Role e un ClusterRoleBinding.
- Strumenti sulla tua macchina:
helm,kubectl,docker buildx,openssle la CLIant. - L’archivio della release: Per richiedere l’accesso al download, contatta il tuo team account di Anthropic. Estrai l’archivio. Esegui ogni comando di questa pagina dalla sua directory principale.
Installare lo stack
Compilare e caricare le immagini
Imposta queste variabili con i tuoi valori.
PLATFORMè l’architettura dei tuoi nodi.TAGè la versione della release, che si trova nel nome dell’archivio dopo lav. Entrambi i chart si aspettano immagini che abbiano questa versione come tag.REGISTRY=us-docker.pkg.dev/my-project/cma TAG=1.2.3 PLATFORM=linux/amd64Poi compila e carica le tre immagini:
docker buildx build --platform "$PLATFORM" -f kubernetes/server/Dockerfile -t "$REGISTRY/cma-server-image:$TAG" --push . docker buildx build --platform "$PLATFORM" -f kubernetes/dispatcher/Dockerfile -t "$REGISTRY/cma-dispatcher:$TAG" --push . docker buildx build --platform "$PLATFORM" -t "$REGISTRY/cma-sandbox:$TAG" --push kubernetes/sandboxCreare un file dei segreti e il database
Crea un file con una password del database generata e un segnaposto per la tua chiave API di Claude:
cat > secrets.env <<EOF PG_PASSWORD=$(openssl rand -hex 32) UPSTREAM_KEY=sk-ant-... EOF chmod 600 secrets.envApri
secrets.envin un editor e sostituiscisk-ant-...con la tua chiave API di Claude. Poi connettiti al tuo server di database come amministratore, ad esempio conpsql. Esegui questo SQL, usando il valore diPG_PASSWORDal posto di...:CREATE ROLE cma_server LOGIN PASSWORD '...'; GRANT cma_server TO CURRENT_USER; CREATE DATABASE cma_server OWNER cma_server;Creare il namespace e i Secret del server
Crea il namespace del server e i relativi Secret:
source secrets.env ENCRYPTION_KEY=$(openssl rand -base64 32) kubectl create namespace cma-server kubectl label namespace cma-server pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=latest kubectl -n cma-server create secret generic cma-server-db \ --from-literal=PGPASSWORD="$PG_PASSWORD" kubectl -n cma-server create secret generic cma-server-keys \ --from-literal=CMA_SERVER__API_KEY="$(openssl rand -hex 32)" \ --from-literal=CMA_STORE__CREDENTIALS_ENCRYPTION_KEY="$ENCRYPTION_KEY" kubectl -n cma-server create secret generic cma-server-upstream \ --from-literal=ANTHROPIC_API_KEY="$UPSTREAM_KEY"Stampa la chiave di cifratura con
echo "$ENCRYPTION_KEY"e conservane una copia al di fuori del cluster. Il server usa questa chiave per cifrare le credenziali che memorizza, e un database ripristinato ne ha bisogno. Poi eliminasecrets.env. Il Secretcma-server-dbconserva la password del database.Creare il namespace e il certificato delle sandbox
Crea il namespace delle sandbox e un certificato che il dispatcher presenta e che le sandbox considerano attendibile:
kubectl create namespace cma kubectl label namespace cma pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=latest openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -days 825 \ -subj "/CN=cma-dispatcher.cma.svc" \ -addext "subjectAltName=DNS:cma-dispatcher.cma.svc,DNS:cma-dispatcher.cma.svc.cluster.local" \ -keyout tls.key -out tls.crt kubectl -n cma create secret tls cma-dispatcher-tls --cert=tls.crt --key=tls.key --dry-run=client -o yaml | kubectl apply -f - kubectl -n cma create configmap cma-dispatcher-ca --from-file=ca.crt=tls.crt --dry-run=client -o yaml | kubectl apply -f -Installare il server
Salva questo come
cma-server-values.yaml, con il tuo registry e l’indirizzo del tuo database:earlierNames: false # a new install image: registry: us-docker.pkg.dev/my-project/cma # REGISTRY in the build commands database: url: host=10.20.0.5 port=5432 user=cma_server dbname=cma_server sslmode=require # your database's address environments: - name: default namespace: cmaPoi installa il chart:
helm install cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait kubectl -n cma-server logs job/cma-server-environment-defaultL’installazione crea l’ambiente
defaulte memorizza la sua chiave nel Secretcma-environmentnel namespacecma. Il secondo comando stampa una riga che inizia confilled Secret cma/cma-environment. Se un primohelm installnon riesce, eseguihelm uninstallper quella release prima di installare di nuovo.Trovare gli indirizzi del cluster da bloccare
Questa installazione consente alle sandbox di raggiungere internet pubblico. L’endpoint API di un cluster di solito ha un indirizzo pubblico, quindi anche le sandbox potrebbero raggiungerlo. Per bloccarlo, elenca il suo indirizzo in
egress.clusterCIDRsnel passaggio successivo.Per stampare l’indirizzo, esegui
gcloud container clusters describe my-cluster --format 'value(endpoint)'con il nome del tuo cluster.Il chart stesso blocca gli intervalli privati
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16e100.64.0.0/10. Se il tuo cluster ha un intervallo di pod, service o nodi al di fuori di questi quattro, elenca anche quell’intervallo.Installare le sandbox
Salva questo come
cma-values.yaml, con il tuo registry e gli indirizzi del passaggio precedente:platform: gke image: registry: us-docker.pkg.dev/my-project/cma # REGISTRY in the build commands egress: mode: publicInternet clusterCIDRs: - 203.0.113.10/32 # the cluster's API endpoint cmaServer: pods: namespace: cma-server matchLabels: anthropic.com/role: server port: 8400egress.cmaServerapre il percorso verso i tuoi server. Per confrontarepublicInternetcon gli altri due modi, consulta Cosa possono raggiungere le sandbox.Se il tuo cluster usa una di queste configurazioni DNS, aggiungi una riga al file:
- Cloud DNS per GKE, usato dai cluster Autopilot:
gke: {dns: cloudDns} - NodeLocal DNSCache:
gke: {dns: nodeLocalCache, kubeDnsUpstreamIP: <address>}. Per stampare l’indirizzo, eseguikubectl -n kube-system get svc kube-dns-upstream -o jsonpath='{.spec.clusterIP}'.
Poi installa il chart:
helm install cma kubernetes/chart --namespace cma -f cma-values.yaml --wait- Cloud DNS per GKE, usato dai cluster Autopilot:
Eseguire una sessione
Questi passaggi usano i nomi di una nuova installazione. Se il file dei valori del tuo server contiene earlierNames: true, trova i nomi da usare al loro posto in Kubernetes: i nomi dei tuoi oggetti.
Inoltrare la porta del server
In un terminale, inoltra la porta del server alla tua macchina:
kubectl -n cma-server port-forward svc/cma-server 8400:8400Puntare la CLI al tuo server
In un secondo terminale, punta la CLI
antalla porta inoltrata e leggi la chiave API del server dal Secretcma-server-keys:export ANTHROPIC_BASE_URL=http://127.0.0.1:8400 export ANTHROPIC_API_KEY=$(kubectl -n cma-server get secret cma-server-keys -o jsonpath='{.data.CMA_SERVER__API_KEY}' | base64 -d)Creare un agente e chiedergli di eseguire un comando
Segui tre passaggi della sezione Eseguire la tua prima sessione della guida rapida: Creare un agente, Avviare una sessione e Chiedere all’agente di eseguire un comando. In Avviare una sessione, sostituisci
compose-sandboxcondefault, il nome dell’ambiente che i chart creano.Trovare il pod sandbox
L’agente risponde con l’hostname del pod che ha eseguito il comando. In un terzo terminale,
kubectl -n cma get podselenca un pod con quel nome accanto a quello del dispatcher. Per impostazione predefinita, il pod scompare circa 5 minuti dopo la fine del turno dell’agente. Se non compare nell’elenco, chiedi di nuovo all’agente di eseguirehostname.Per uscire dalla chat, premi Ctrl+C.
Mettere TLS davanti al server
Il server parla HTTP in chiaro sulla porta 8400, e le richieste dalle tue applicazioni trasportano la chiave API del server. Prima che i client esterni al cluster si connettano, metti un load balancer o un ingress che termini TLS davanti al Service cma-server. Deve:
- Lasciar passare i percorsi delle richieste senza modificarli.
- Accettare corpi di richiesta fino a 32 MiB.
- Lasciar passare le risposte senza buffering.
- Impostare un timeout di lettura predefinito di 2 minuti. Per le richieste Git, impostare un timeout di lettura di 10 minuti per i percorsi che corrispondono a
^/cma-[a-z]+/git/. - Inviare traffico solo ai server che sono pronti. Il Service
cma-serverlo fa già. Un load balancer che raggiunge direttamente i pod deve sondare/cma-server/readyzsu ogni pod e saltare quello che restituisce503. - Non inviare mai di nuovo un
POSTche un server ha già accettato. - Non memorizzare mai nella cache una risposta.
Per verificarlo dall’esterno del cluster, esegui curl -s https://<host>/cma-server/healthz. La risposta è {"status":"ok"}.
Cosa possono raggiungere le sandbox
In cma-values.yaml, egress.mode: publicInternet consente alle sandbox di raggiungere internet pubblico.
Questa tabella lo confronta con gli altri due modi:
egress.mode | Cosa possono raggiungere le sandbox |
|---|---|
closed, il valore predefinito | I tuoi server e il dispatcher, e nessun server DNS |
publicInternet | I tuoi server, il dispatcher, un server DNS e internet pubblico |
gateway | I tuoi server, il dispatcher e, tramite l’“egress gateway” (gateway di uscita), gli host che elenchi. Consulta Attivare il gateway su Kubernetes. |
Altri cluster
Imposta platform in cma-values.yaml su eks per Amazon EKS, su aks per Azure Kubernetes Service (AKS), o su generic per qualsiasi altro cluster. Tutti e tre richiedono il controller Agent Sandbox upstream con le sue estensioni e un plugin di rete che applichi le NetworkPolicy. Richiedono inoltre:
- Amazon EKS: Un gruppo di nodi con
runscdi gVisor registrato come handler containerd denominatorunsc. Applica ai nodi l’etichettacma.anthropic.com/sandbox-node=truee il taintcma.anthropic.com/sandbox-node=true:NoSchedule. Il chart registra la RuntimeClassgvisorsu quell’handler. - AKS: Un pool di nodi con Pod Sandboxing, con la stessa etichetta e lo stesso taint di Amazon EKS. Inserisci il nome del motore di policy di rete del cluster (
cilium,calicooazure) inaks.networkPolicy. Mantieniegress.mode: publicInternet, l’unico modo che il chart accetta su AKS. Testa il chart sul tuo cluster prima che gli agenti svolgano lavoro reale su di esso. - Qualsiasi altro cluster: Una RuntimeClass per gVisor o un altro runtime in sandbox. Inserisci il suo nome in
runtimeClass.name.
La cartella kubernetes/chart/examples/ nell’archivio contiene un file di valori completo per ogni tipo di cluster.
Liberare il volume di una sessione
Con i valori predefiniti del chart, ogni sessione ha un volume da 10 GiB per /workspace. Il volume resta anche dopo che il pod della sessione scompare, quindi il messaggio successivo della sessione ritrova i suoi file.
| Per liberare | Fai questo |
|---|---|
| Il volume di una sessione | Archivia la sessione dopo la fine del suo turno. Il dispatcher di solito elimina il volume entro circa 5 minuti. |
| I volumi delle sessioni che nessuno archivia | Imposta dispatcher.retentionDays in cma-values.yaml. Il dispatcher elimina quindi un volume quando la sua sessione è rimasta inattiva per quel numero di giorni, e il messaggio successivo della sessione inizia con una /workspace vuota. Il valore predefinito del chart, 0, conserva ogni volume. |
I comandi di questa sezione sono per GKE. Su un altro cluster, usa sandboxclaims al posto di sandboxes.
Eliminare una sessione non libera il suo volume. Archivia prima la sessione. Eliminala solo dopo che kubectl -n cma get sandboxes -l anthropic.com/session-id=<session-id> non elenca nulla.
Se hai eliminato una sessione senza archiviarla, libera tu stesso il suo volume:
-
Trova l’ID della sessione nel log del dispatcher. Questo comando stampa una riga per ogni sessione che risulta eliminata e ha ancora un volume, con l’ID dopo
session_id:kubectl -n cma logs deployment/cma-dispatcher --since=6m \ | grep "could not check the claim's session" | grep "403 Forbidden"Il dispatcher scrive queste righe ogni 5 minuti. Se la sessione non è elencata, attendi 5 minuti ed esegui di nuovo il comando.
-
Conferma che la sessione sia eliminata. Con la porta inoltrata e
ANTHROPIC_API_KEYimpostata come in Eseguire una sessione, eseguiant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>. Prosegui solo se la risposta è404 Not FoundconSession not found. Se il comando stampa una sessione, fermati: quella sessione non è eliminata. -
Elimina l’oggetto Kubernetes che possiede il volume. I file della sessione vengono eliminati con esso:
kubectl -n cma delete sandboxes -l anthropic.com/session-id=<session-id>
Rinnovare chiavi e certificati
Una chiave di ambiente è valida per 365 giorni e il certificato del dispatcher è valido per 825 giorni. Rinnova ciascuno prima che scada.
Negli ultimi 30 giorni di validità di una chiave di ambiente, il server registra un avviso a ogni richiesta che usa la chiave. L’avviso inizia con environment key is within 30 days of expiry.
Rinnovare la chiave di ambiente creata dai chart
Per vedere quando scade la chiave, esegui kubectl -n cma describe secret cma-environment.
Esegui questi due comandi almeno una volta negli ultimi 60 giorni di validità della chiave, dalla directory principale dell’archivio della release installata:
helm upgrade cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait
kubectl -n cma rollout restart deployment/cma-dispatcherOgni volta che viene eseguito il comando helm upgrade del chart del server, questo memorizza una nuova chiave nel Secret se la chiave scade entro 60 giorni. Nient’altro rinnova la chiave. Il secondo comando riavvia il dispatcher in modo che legga la nuova chiave.
Rinnovare il certificato del dispatcher
Torna al passaggio “Creare il namespace e il certificato delle sandbox”. Ripeti il suo comando openssl e i due comandi kubectl che lo seguono. Poi riavvia il dispatcher con kubectl -n cma rollout restart deployment/cma-dispatcher.
Sostituire una chiave di ambiente per i tuoi worker
I chart rinnovano solo la propria chiave. Se hai creato tu una chiave, come in Creare un ambiente e la relativa chiave, sostituiscila con la CLI di amministrazione. La CLI si trova nella directory principale dell’archivio della release.
Esegui i comandi nel secondo terminale di Eseguire una sessione, dove ANTHROPIC_API_KEY contiene la chiave API del server. Mantieni il port-forward in esecuzione nel primo terminale. Se raggiungi il tuo server a un altro indirizzo, passa quell’indirizzo come -base-url, e non ti serve alcun port-forward.
Creare una nuova chiave per lo stesso ambiente
Per
-env, passa l’ID dell’ambiente:echo "$ANTHROPIC_API_KEY" | ./cma-server-admin mint-key \ -base-url http://127.0.0.1:8400 -env env_01595EKxaaTTGwwY3kyXdtbs -key-file -Il comando stampa la nuova chiave, e stampa l’ID e la scadenza della chiave sullo standard error.
Spostare i worker sulla nuova chiave
Imposta la nuova chiave come
ANTHROPIC_ENVIRONMENT_KEYper ogni processo che esegue il polling e riavvialo.Revocare la vecchia chiave
Un worker che usa ancora una chiave revocata riceve un errore
401e abbandona la sessione che stava servendo. Per trovare l’ID della vecchia chiave, eseguilist-keyscon gli stessi flag-base-url,-enve-key-file. Quando nessun worker usa più la vecchia chiave, revocala tramite quell’ID:echo "$ANTHROPIC_API_KEY" | ./cma-server-admin revoke-key \ -base-url http://127.0.0.1:8400 -env env_01595EKxaaTTGwwY3kyXdtbs \ -key-id etok_01AbCdEfGhIjKlMnOpQrStUv -key-file -
Disinstallare lo stack
Elimina prima le sandbox. helm uninstall elimina le policy di rete che confinano le sandbox, ma le sandbox che il dispatcher ha creato per le sessioni continuano a essere in esecuzione.
Questi passaggi non toccano il tuo database, ma eliminano i Secret. Per usare di nuovo il database, ti serve la tua copia della chiave di cifratura.
Arrestare il dispatcher ed eliminare le sandbox
kubectl -n cma scale deployment/cma-dispatcher --replicas=0 kubectl -n cma delete sandboxwarmpool cma-sandbox kubectl -n cma delete sandboxclaims --allSu GKE, esegui anche questo comando:
kubectl -n cma delete sandboxes --allAttendere che le sandbox siano scomparse
Ripeti questo comando finché le sandbox, i loro pod e i loro volumi non sono scomparsi:
kubectl -n cma get sandboxes,pods,pvcDisinstallare i chart ed eliminare i namespace
helm uninstall cma --namespace cma helm uninstall cma-server --namespace cma-server kubectl delete namespace cma cma-server
Passaggi successivi
- Aggiorna: Aggiornare Claude Managed Agents self-hosted contiene i comandi
helm upgrade. - Modifica altri valori dei chart: Consulta i commenti in
kubernetes/server/chart/values.yamlper il server e inkubernetes/chart/values.yamlper le sandbox. - Chiama l’API dal tuo codice: Consulta Chiamare l’API su un server self-hosted.
- Lavora in un browser: Consulta Usa la console sul tuo server.
Questa pagina ti è stata utile?