Implementar en Kubernetes
Instala el servidor de Claude Managed Agents autoalojado y sus sandboxes en un clúster de Kubernetes con los dos charts de Helm del archivo de la versión y, después, ejecuta una primera sesión en un pod de sandbox.
Esta página lleva un clúster vacío de Google Kubernetes Engine (GKE) hasta una sesión que ejecuta una herramienta en un pod de sandbox. Usa los dos charts de Helm del archivo de la versión, que ejecutan todo el stack en el clúster:
cma-server: Aplica el esquema de la base de datos y ejecuta dos servidores detrás de un Service, en el namespacecma-server.cma-sandboxes: Ejecuta un dispatcher y los pods de sandbox en el namespacecma. El dispatcher sondea el servidor en busca de trabajo y asigna a cada sesión su propio pod de sandbox, donde un worker ejecuta las herramientas de shell y de archivos del agente.
Tu base de datos PostgreSQL queda fuera de ambos. En otro tipo de clúster, los pasos son los mismos, pero los requisitos previos del clúster y algunos valores de los charts cambian. Consulta Otros clústeres.
Requisitos previos
- Un clúster: Kubernetes 1.30 o posterior, con:
- El controlador Agent Sandbox (en GKE, el complemento Agent Sandbox)
- Nodos que ejecuten gVisor (en GKE, un grupo de nodos de GKE Sandbox)
- Un plugin de red que aplique NetworkPolicy (en GKE, Dataplane V2 o Calico)
- Una base de datos: PostgreSQL 16 o posterior, accesible desde el clúster.
- Un registro: Uno del que el clúster pueda descargar imágenes. Tú mismo compilas las imágenes.
- Una clave de API de Claude: El servidor la usa para las llamadas al modelo. Para usar otro proveedor, consulta Proveedor de inferencia.
- Permisos: Derechos de cluster-admin o equivalentes. La instalación crea namespaces, Roles y un ClusterRoleBinding.
- Herramientas en tu máquina:
helm,kubectl,docker buildx,openssly la CLIant. - El archivo de la versión: Para solicitar acceso a la descarga, comunícate con el equipo de tu cuenta de Anthropic. Extrae el archivo. Ejecuta todos los comandos de esta página desde su directorio raíz.
Instalar el stack
Compilar y subir las imágenes
Establece estas variables con tus propios valores.
PLATFORMes la arquitectura de tus nodos.TAGes el número de versión, que está en el nombre del archivo de la versión, después de lav. Ambos charts esperan imágenes que tengan esta versión como etiqueta.REGISTRY=us-docker.pkg.dev/my-project/cma TAG=1.2.3 PLATFORM=linux/amd64Luego compila y sube las tres imágenes:
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/sandboxCrear un archivo de secretos y la base de datos
Crea un archivo con una contraseña de base de datos generada y un marcador de posición para tu clave de API de Claude:
cat > secrets.env <<EOF PG_PASSWORD=$(openssl rand -hex 32) UPSTREAM_KEY=sk-ant-... EOF chmod 600 secrets.envAbre
secrets.enven un editor y reemplazask-ant-...con tu clave de API de Claude. Luego conéctate a tu servidor de base de datos como administrador, por ejemplo conpsql. Ejecuta este SQL, con el valor dePG_PASSWORDen lugar de...:CREATE ROLE cma_server LOGIN PASSWORD '...'; GRANT cma_server TO CURRENT_USER; CREATE DATABASE cma_server OWNER cma_server;Crear el namespace y los Secrets del servidor
Crea el namespace del servidor y sus Secrets:
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"Imprime la clave de cifrado con
echo "$ENCRYPTION_KEY"y guarda una copia fuera del clúster. El servidor usa esta clave para cifrar las credenciales que almacena, y una base de datos restaurada la necesita. Luego eliminasecrets.env. El Secretcma-server-dbconserva la contraseña de la base de datos.Crear el namespace y el certificado de los sandboxes
Crea el namespace de los sandboxes y un certificado que el dispatcher sirve y en el que confían los sandboxes:
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 -Instalar el servidor
Guarda esto como
cma-server-values.yaml, con tu registro y la dirección de tu base de datos: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: cmaLuego instala el 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-defaultLa instalación crea el entorno
defaulty guarda su clave en el Secretcma-environmentdel namespacecma. El segundo comando imprime una línea que empieza porfilled Secret cma/cma-environment. Si un primerhelm installfalla, ejecutahelm uninstallpara esa release antes de volver a instalar.Buscar las direcciones del clúster que hay que bloquear
Esta instalación permite que los sandboxes accedan a internet pública. El endpoint de la API de un clúster suele tener una dirección pública, así que los sandboxes también podrían acceder a él. Para bloquearlo, enumeras su dirección en
egress.clusterCIDRsen el paso siguiente.Para mostrar la dirección, ejecuta
gcloud container clusters describe my-cluster --format 'value(endpoint)'con el nombre de tu clúster.El propio chart bloquea los rangos privados
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16y100.64.0.0/10. Si tu clúster tiene un rango de pods, servicios o nodos fuera de esos cuatro, enumera también ese rango.Instalar los sandboxes
Guarda esto como
cma-values.yaml, con tu registro y las direcciones del paso anterior: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.cmaServerabre el camino hacia tus servidores. Para compararpublicInternetcon los otros dos modos, consulta A qué pueden acceder los sandboxes.Si tu clúster usa una de estas configuraciones de DNS, agrega una línea al archivo:
- Cloud DNS para GKE, que es lo que usan los clústeres Autopilot:
gke: {dns: cloudDns} - NodeLocal DNSCache:
gke: {dns: nodeLocalCache, kubeDnsUpstreamIP: <address>}. Para mostrar la dirección, ejecutakubectl -n kube-system get svc kube-dns-upstream -o jsonpath='{.spec.clusterIP}'.
Luego instala el chart:
helm install cma kubernetes/chart --namespace cma -f cma-values.yaml --wait- Cloud DNS para GKE, que es lo que usan los clústeres Autopilot:
Ejecutar una sesión
Estos pasos usan los nombres de una instalación nueva. Si tu archivo de valores del servidor tiene earlierNames: true, encuentra los nombres que debes usar en su lugar en Kubernetes: los nombres de tus objetos.
Reenviar el puerto del servidor
En una terminal, reenvía el puerto del servidor a tu máquina:
kubectl -n cma-server port-forward svc/cma-server 8400:8400Apuntar la CLI a tu servidor
En una segunda terminal, apunta la CLI
antal puerto reenviado y lee la clave de API del servidor desde el 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)Crear un agente y pedirle que ejecute un comando
Sigue tres pasos de Ejecutar tu primera sesión de la guía de inicio rápido: Crear un agente, Iniciar una sesión y Pedirle al agente que ejecute un comando. En Iniciar una sesión, reemplaza
compose-sandboxcondefault, el nombre del entorno que crean los charts.Encontrar el pod de sandbox
El agente responde con el nombre de host del pod que ejecutó el comando. En una tercera terminal,
kubectl -n cma get podsmuestra un pod con ese nombre junto al del dispatcher. De forma predeterminada, el pod desaparece unos 5 minutos después de que termine el turno del agente. Si no aparece en la lista, pídele al agente que vuelva a ejecutarhostname.Para salir del chat, presiona Ctrl+C.
Poner TLS delante del servidor
El servidor usa HTTP sin cifrar en el puerto 8400, y las solicitudes de tus aplicaciones llevan la clave de API del servidor. Antes de que se conecten clientes desde fuera del clúster, coloca delante del Service cma-server un balanceador de carga o un ingress que termine TLS. Debe:
- Pasar las rutas de las solicitudes sin modificarlas.
- Aceptar cuerpos de solicitud de hasta 32 MiB.
- Pasar las respuestas sin búfer.
- Establecer un tiempo de espera de lectura predeterminado de 2 minutos. Para las solicitudes de Git, establecer un tiempo de espera de lectura de 10 minutos para las rutas que coincidan con
^/cma-[a-z]+/git/. - Enviar tráfico solo a servidores que estén listos. El Service
cma-serverya lo hace. Un balanceador de carga que llega directamente a los pods debe sondear/cma-server/readyzen cada pod y omitir el que devuelva503. - Nunca reenviar un
POSTque un servidor ya haya aceptado. - Nunca almacenar en caché una respuesta.
Para comprobarlo desde fuera del clúster, ejecuta curl -s https://<host>/cma-server/healthz. La respuesta es {"status":"ok"}.
A qué pueden acceder los sandboxes
En cma-values.yaml, egress.mode: publicInternet permite que los sandboxes accedan a internet pública.
Esta tabla lo compara con los otros dos modos:
egress.mode | A qué pueden acceder los sandboxes |
|---|---|
closed, el valor predeterminado | Tus servidores y el dispatcher, y ningún servidor DNS |
publicInternet | Tus servidores, el dispatcher, un servidor DNS e internet pública |
gateway | Tus servidores, el dispatcher y, a través del gateway de salida, los hosts que enumeres. Consulta Activa el gateway en Kubernetes. |
Otros clústeres
Establece platform en cma-values.yaml en eks para Amazon EKS, en aks para Azure Kubernetes Service (AKS), o en generic para cualquier otro clúster. Los tres necesitan el controlador Agent Sandbox original con sus extensiones y un plugin de red que aplique NetworkPolicy. También necesitan:
- Amazon EKS: Un grupo de nodos con
runscde gVisor registrado como un handler de containerd llamadorunsc. Etiqueta los nodos concma.anthropic.com/sandbox-node=truey aplícales el taintcma.anthropic.com/sandbox-node=true:NoSchedule. El chart registra la RuntimeClassgvisorasociada a ese handler. - AKS: Un grupo de nodos con Pod Sandboxing, con la misma etiqueta y el mismo taint que en Amazon EKS. Pon el nombre del motor de políticas de red del clúster (
cilium,calicooazure) enaks.networkPolicy. Manténegress.mode: publicInternet, el único modo que el chart acepta en AKS. Prueba el chart en tu clúster antes de que los agentes hagan trabajo real en él. - Cualquier otro clúster: Una RuntimeClass para gVisor u otro entorno de ejecución aislado. Pon su nombre en
runtimeClass.name.
La carpeta kubernetes/chart/examples/ del archivo de la versión contiene un archivo de valores completo para cada tipo de clúster.
Liberar el volumen de una sesión
Con los valores predeterminados del chart, cada sesión tiene un volumen de 10 GiB para /workspace. El volumen permanece después de que el pod de la sesión desaparece, así que el siguiente mensaje de la sesión encuentra sus archivos.
| Para liberar | Haz esto |
|---|---|
| El volumen de una sesión | Archiva la sesión después de que termine su turno. El dispatcher suele eliminar el volumen en unos 5 minutos. |
| Los volúmenes de las sesiones que nadie archiva | Establece dispatcher.retentionDays en cma-values.yaml. El dispatcher elimina entonces un volumen cuando su sesión ha estado inactiva durante esa cantidad de días, y el siguiente mensaje de la sesión empieza con un /workspace vacío. El valor predeterminado del chart, 0, conserva todos los volúmenes. |
Los comandos de esta sección son para GKE. En otro clúster, usa sandboxclaims en lugar de sandboxes.
Eliminar una sesión no libera su volumen. Archiva primero la sesión. Elimínala solo después de que kubectl -n cma get sandboxes -l anthropic.com/session-id=<session-id> no muestre nada.
Si eliminaste una sesión sin archivarla, libera tú mismo su volumen:
-
Encuentra el ID de la sesión en el registro del dispatcher. Este comando imprime una línea por cada sesión que parece estar eliminada y aún tiene un volumen, con el ID después de
session_id:kubectl -n cma logs deployment/cma-dispatcher --since=6m \ | grep "could not check the claim's session" | grep "403 Forbidden"El dispatcher escribe estas líneas cada 5 minutos. Si la sesión no aparece en la lista, espera 5 minutos y vuelve a ejecutar el comando.
-
Confirma que la sesión está eliminada. Con el puerto reenviado y
ANTHROPIC_API_KEYestablecida como en Ejecutar una sesión, ejecutaant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>. Continúa solo si la respuesta es404 Not FoundconSession not found. Si el comando imprime una sesión, detente: esa sesión no está eliminada. -
Elimina el objeto de Kubernetes al que pertenece el volumen. Los archivos de la sesión se eliminan con él:
kubectl -n cma delete sandboxes -l anthropic.com/session-id=<session-id>
Renovar claves y certificados
Una clave de entorno es válida durante 365 días, y el certificado del dispatcher es válido durante 825 días. Renueva cada uno antes de que caduque.
En los últimos 30 días de una clave de entorno, el servidor registra una advertencia en cada solicitud que usa la clave. La advertencia empieza por environment key is within 30 days of expiry.
Renovar la clave del entorno que crearon los charts
Para ver cuándo caduca la clave, ejecuta kubectl -n cma describe secret cma-environment.
Ejecuta estos dos comandos al menos una vez durante los últimos 60 días de validez de la clave, desde el directorio raíz del archivo de la versión instalada:
helm upgrade cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait
kubectl -n cma rollout restart deployment/cma-dispatcherCada vez que se ejecuta el comando helm upgrade del chart del servidor, este guarda una clave nueva en el Secret si la clave caduca en un plazo de 60 días. Nada más renueva la clave. El segundo comando reinicia el dispatcher para que lea la clave nueva.
Renovar el certificado del dispatcher
Vuelve al paso “Crear el namespace y el certificado de los sandboxes”. Repite su comando openssl y los dos comandos kubectl que lo siguen. Luego reinicia el dispatcher con kubectl -n cma rollout restart deployment/cma-dispatcher.
Reemplazar una clave de entorno para tus propios workers
Los charts solo renuevan su propia clave. Si creaste una clave tú mismo, como en Crear un entorno y su clave, reemplázala con la CLI de administración. La CLI está en el nivel superior del archivo de la versión.
Ejecuta los comandos en la segunda terminal de Ejecutar una sesión, donde ANTHROPIC_API_KEY contiene la clave de API del servidor. Mantén el reenvío de puertos en ejecución en la primera terminal. Si accedes a tu servidor en otra dirección, pasa esa dirección como -base-url, y no necesitas reenvío de puertos.
Crear una clave nueva para el mismo entorno
En
-env, pasa el ID del entorno:echo "$ANTHROPIC_API_KEY" | ./cma-server-admin mint-key \ -base-url http://127.0.0.1:8400 -env env_01595EKxaaTTGwwY3kyXdtbs -key-file -El comando imprime la clave nueva, e imprime el ID y la fecha de caducidad de la clave en la salida de error estándar.
Pasar tus workers a la clave nueva
Establece la clave nueva como
ANTHROPIC_ENVIRONMENT_KEYen cada proceso que sondea y reinícialo.Revocar la clave antigua
Un worker que aún usa una clave revocada recibe un error
401y abandona la sesión que estaba atendiendo. Para encontrar el ID de la clave antigua, ejecutalist-keyscon las mismas opciones-base-url,-envy-key-file. Cuando ningún worker use ya la clave antigua, revócala por ese 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 -
Desinstalar el stack
Elimina primero los sandboxes. helm uninstall elimina las políticas de red que confinan a los sandboxes, pero los sandboxes que el dispatcher creó para las sesiones siguen ejecutándose.
Estos pasos no afectan a tu base de datos, pero eliminan los Secrets. Para volver a usar la base de datos, necesitas tu copia de la clave de cifrado.
Detener el dispatcher y eliminar los sandboxes
kubectl -n cma scale deployment/cma-dispatcher --replicas=0 kubectl -n cma delete sandboxwarmpool cma-sandbox kubectl -n cma delete sandboxclaims --allEn GKE, ejecuta también este comando:
kubectl -n cma delete sandboxes --allEsperar hasta que los sandboxes desaparezcan
Repite este comando hasta que los sandboxes, sus pods y sus volúmenes hayan desaparecido:
kubectl -n cma get sandboxes,pods,pvcDesinstalar los charts y eliminar los namespaces
helm uninstall cma --namespace cma helm uninstall cma-server --namespace cma-server kubectl delete namespace cma cma-server
Próximos pasos
- Actualizar: Actualizar Claude Managed Agents autoalojado contiene los comandos
helm upgrade. - Cambiar otros valores de los charts: Consulta los comentarios de
kubernetes/server/chart/values.yamlpara el servidor y dekubernetes/chart/values.yamlpara los sandboxes. - Llamar a la API desde tu código: Consulta Llamar a la API en un servidor autoalojado.
- Trabajar en un navegador: Consulta Usa la consola en tu servidor.
¿Te resultó útil esta página?