Claude Platform Docs
Managed AgentsManaged Agents autoalojado

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 namespace cma-server.
  • cma-sandboxes: Ejecuta un dispatcher y los pods de sandbox en el namespace cma. 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:
  • 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, openssl y la CLI ant.
  • 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

  1. Compilar y subir las imágenes

    Establece estas variables con tus propios valores. PLATFORM es la arquitectura de tus nodos. TAG es el número de versión, que está en el nombre del archivo de la versión, después de la v. 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/amd64

    Luego 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/sandbox
  2. Crear 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.env

    Abre secrets.env en un editor y reemplaza sk-ant-... con tu clave de API de Claude. Luego conéctate a tu servidor de base de datos como administrador, por ejemplo con psql. Ejecuta este SQL, con el valor de PG_PASSWORD en lugar de ...:

    CREATE ROLE cma_server LOGIN PASSWORD '...';
    GRANT cma_server TO CURRENT_USER;
    CREATE DATABASE cma_server OWNER cma_server;
  3. 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 elimina secrets.env. El Secret cma-server-db conserva la contraseña de la base de datos.

  4. 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 -
  5. 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: cma

    Luego 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-default

    La instalación crea el entorno default y guarda su clave en el Secret cma-environment del namespace cma. El segundo comando imprime una línea que empieza por filled Secret cma/cma-environment. Si un primer helm install falla, ejecuta helm uninstall para esa release antes de volver a instalar.

  6. 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.clusterCIDRs en 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/16 y 100.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.

  7. 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: 8400

    egress.cmaServer abre el camino hacia tus servidores. Para comparar publicInternet con 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, ejecuta kubectl -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

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.

  1. 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:8400
  2. Apuntar la CLI a tu servidor

    En una segunda terminal, apunta la CLI ant al puerto reenviado y lee la clave de API del servidor desde el Secret cma-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)
  3. 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-sandbox con default, el nombre del entorno que crean los charts.

  4. 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 pods muestra 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 ejecutar hostname.

    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-server ya lo hace. Un balanceador de carga que llega directamente a los pods debe sondear /cma-server/readyz en cada pod y omitir el que devuelva 503.
  • Nunca reenviar un POST que 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.modeA qué pueden acceder los sandboxes
closed, el valor predeterminadoTus servidores y el dispatcher, y ningún servidor DNS
publicInternetTus servidores, el dispatcher, un servidor DNS e internet pública
gatewayTus 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 runsc de gVisor registrado como un handler de containerd llamado runsc. Etiqueta los nodos con cma.anthropic.com/sandbox-node=true y aplícales el taint cma.anthropic.com/sandbox-node=true:NoSchedule. El chart registra la RuntimeClass gvisor asociada 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, calico o azure) en aks.networkPolicy. Mantén egress.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 liberarHaz esto
El volumen de una sesiónArchiva 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 archivaEstablece 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:

  1. 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.

  2. Confirma que la sesión está eliminada. Con el puerto reenviado y ANTHROPIC_API_KEY establecida como en Ejecutar una sesión, ejecuta ant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>. Continúa solo si la respuesta es 404 Not Found con Session not found. Si el comando imprime una sesión, detente: esa sesión no está eliminada.

  3. 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-dispatcher

Cada 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.

  1. 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.

  2. Pasar tus workers a la clave nueva

    Establece la clave nueva como ANTHROPIC_ENVIRONMENT_KEY en cada proceso que sondea y reinícialo.

  3. Revocar la clave antigua

    Un worker que aún usa una clave revocada recibe un error 401 y abandona la sesión que estaba atendiendo. Para encontrar el ID de la clave antigua, ejecuta list-keys con las mismas opciones -base-url, -env y -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.

  1. 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 --all

    En GKE, ejecuta también este comando:

    kubectl -n cma delete sandboxes --all
  2. Esperar 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,pvc
  3. Desinstalar 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

¿Te resultó útil esta página?