Claude Platform Docs
Managed AgentsManaged Agents auto-hébergé

Déployer sur Kubernetes

Installez le serveur Claude Managed Agents auto-hébergé et ses sandboxes sur un cluster Kubernetes avec les deux charts Helm de l’archive de la version, puis exécutez une première session dans un pod de sandbox.

Cette page vous mène d’un cluster Google Kubernetes Engine (GKE) vide à une session qui exécute un outil dans un pod de sandbox. Elle utilise les deux charts Helm de l’archive de la version, qui exécutent toute la pile sur le cluster :

  • cma-server : Applique le schéma de base de données et exécute deux serveurs derrière un Service, dans l’espace de noms cma-server.
  • cma-sandboxes : Exécute un dispatcher et les pods de sandbox dans l’espace de noms cma. Le dispatcher interroge le serveur pour obtenir du travail et attribue à chaque session son propre pod de sandbox, dans lequel un worker exécute les outils de shell et de fichiers de l’agent.

Votre base de données PostgreSQL reste en dehors des deux. Sur un autre type de cluster, les étapes sont les mêmes, mais les prérequis du cluster et quelques valeurs des charts diffèrent. Consultez Autres clusters.

Prérequis

  • Un cluster : Kubernetes 1.30 ou version ultérieure, avec :
  • Une base de données : PostgreSQL 16 ou version ultérieure, accessible depuis le cluster.
  • Un registre : Un registre depuis lequel le cluster peut extraire des images. Vous construisez les images vous-même.
  • Une clé API Claude : Le serveur l’utilise pour les appels au modèle. Pour utiliser un autre fournisseur, consultez Fournisseur d’inférence.
  • Autorisations : Des droits cluster-admin ou l’équivalent. L’installation crée des espaces de noms, des Roles et un ClusterRoleBinding.
  • Outils sur votre machine : helm, kubectl, docker buildx, openssl et la CLI ant.
  • L’archive de la version : Pour demander l’accès au téléchargement, contactez l’équipe chargée de votre compte Anthropic. Extrayez l’archive. Exécutez chaque commande de cette page depuis son répertoire de premier niveau.

Installer la pile

  1. Construire et publier les images

    Définissez ces variables avec vos propres valeurs. PLATFORM est l’architecture de vos nœuds. TAG est le numéro de la version, qui figure dans le nom de l’archive après le v. Les deux charts attendent des images dont le tag est ce numéro de version.

    REGISTRY=us-docker.pkg.dev/my-project/cma
    TAG=1.2.3
    PLATFORM=linux/amd64

    Ensuite, construisez et publiez les trois images :

    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. Créer un fichier de secrets et la base de données

    Créez un fichier contenant un mot de passe de base de données généré et un espace réservé pour votre clé API Claude :

    cat > secrets.env <<EOF
    PG_PASSWORD=$(openssl rand -hex 32)
    UPSTREAM_KEY=sk-ant-...
    EOF
    chmod 600 secrets.env

    Ouvrez secrets.env dans un éditeur et remplacez sk-ant-... par votre clé API Claude. Ensuite, connectez-vous à votre serveur de base de données en tant qu’administrateur, par exemple avec psql. Exécutez ce SQL, avec la valeur de PG_PASSWORD à la place de ... :

    CREATE ROLE cma_server LOGIN PASSWORD '...';
    GRANT cma_server TO CURRENT_USER;
    CREATE DATABASE cma_server OWNER cma_server;
  3. Créer l’espace de noms et les Secrets du serveur

    Créez l’espace de noms du serveur et ses 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"

    Affichez la clé de chiffrement avec echo "$ENCRYPTION_KEY" et conservez-en une copie en dehors du cluster. Le serveur utilise cette clé pour chiffrer les identifiants qu’il stocke, et une base de données restaurée en a besoin. Supprimez ensuite secrets.env. Le Secret cma-server-db conserve le mot de passe de la base de données.

  4. Créer l’espace de noms et le certificat des sandboxes

    Créez l’espace de noms des sandboxes, ainsi qu’un certificat que le dispatcher sert et auquel les sandboxes font confiance :

    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. Installer le serveur

    Enregistrez ceci sous le nom cma-server-values.yaml, avec votre registre et l’adresse de votre base de données :

    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

    Installez ensuite le 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

    L’installation crée l’environnement default et stocke sa clé dans le Secret cma-environment de l’espace de noms cma. La deuxième commande affiche une ligne qui commence par filled Secret cma/cma-environment. Si un premier helm install échoue, exécutez helm uninstall pour cette release avant de réinstaller.

  6. Trouver les adresses du cluster à bloquer

    Cette installation permet aux sandboxes d’accéder à l’internet public. Le point de terminaison de l’API d’un cluster possède généralement une adresse publique, de sorte que les sandboxes pourraient également l’atteindre. Pour le bloquer, vous indiquez son adresse sous egress.clusterCIDRs à l’étape suivante.

    Pour afficher l’adresse, exécutez gcloud container clusters describe my-cluster --format 'value(endpoint)' avec le nom de votre cluster.

    Le chart lui-même bloque les plages privées 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 et 100.64.0.0/10. Si votre cluster possède une plage de pods, de services ou de nœuds en dehors de ces quatre plages, indiquez également cette plage.

  7. Installer les sandboxes

    Enregistrez ceci sous le nom cma-values.yaml, avec votre registre et les adresses de l’étape précédente :

    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 ouvre le chemin vers vos serveurs. Pour comparer publicInternet aux deux autres modes, consultez Ce que les sandboxes peuvent atteindre.

    Si votre cluster utilise l’une de ces configurations DNS, ajoutez une ligne au fichier :

    • Cloud DNS pour GKE, qu’utilisent les clusters Autopilot : gke: {dns: cloudDns}
    • NodeLocal DNSCache : gke: {dns: nodeLocalCache, kubeDnsUpstreamIP: <address>}. Pour afficher l’adresse, exécutez kubectl -n kube-system get svc kube-dns-upstream -o jsonpath='{.spec.clusterIP}'.

    Installez ensuite le chart :

    helm install cma kubernetes/chart --namespace cma -f cma-values.yaml --wait

Exécuter une session

Ces étapes utilisent les noms d’une nouvelle installation. Si votre fichier de valeurs du serveur contient earlierNames: true, trouvez les noms à utiliser à la place dans Kubernetes : les noms de vos objets.

  1. Rediriger le port du serveur

    Dans un premier terminal, redirigez le port du serveur vers votre machine :

    kubectl -n cma-server port-forward svc/cma-server 8400:8400
  2. Diriger la CLI vers votre serveur

    Dans un deuxième terminal, dirigez la CLI ant vers le port redirigé et lisez la clé API du serveur depuis le 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. Créer un agent et lui demander d’exécuter une commande

    Suivez trois étapes de la section Exécuter votre première session du guide de démarrage rapide : Créer un agent, Démarrer une session et Demander à l’agent d’exécuter une commande. Dans Démarrer une session, remplacez compose-sandbox par default, le nom de l’environnement que les charts créent.

  4. Trouver le pod de sandbox

    L’agent répond avec le nom d’hôte du pod qui a exécuté la commande. Dans un troisième terminal, kubectl -n cma get pods répertorie un pod portant ce nom à côté de celui du dispatcher. Par défaut, le pod disparaît environ 5 minutes après la fin du tour de l’agent. S’il ne figure pas dans la liste, demandez à l’agent d’exécuter à nouveau hostname.

    Pour quitter la discussion, appuyez sur Ctrl+C.

Placer TLS devant le serveur

Le serveur communique en HTTP en clair sur le port 8400, et les requêtes de vos applications transportent la clé API du serveur. Avant que des clients extérieurs au cluster ne se connectent, placez un « load balancer » (équilibreur de charge) ou un ingress qui termine TLS devant le Service cma-server. Il doit :

  • Transmettre les chemins de requête sans les modifier.
  • Accepter des corps de requête jusqu’à 32 MiB.
  • Transmettre les réponses sans mise en mémoire tampon.
  • Définir un délai d’expiration de lecture par défaut de 2 minutes. Pour les requêtes Git, définir un délai d’expiration de lecture de 10 minutes pour les chemins correspondant à ^/cma-[a-z]+/git/.
  • Envoyer le trafic uniquement aux serveurs prêts. Le Service cma-server le fait déjà. Un équilibreur de charge qui atteint directement les pods doit sonder /cma-server/readyz sur chaque pod et ignorer ceux qui renvoient 503.
  • Ne jamais renvoyer un POST qu’un serveur a déjà accepté.
  • Ne jamais mettre une réponse en cache.

Pour le vérifier depuis l’extérieur du cluster, exécutez curl -s https://<host>/cma-server/healthz. La réponse est {"status":"ok"}.

Ce que les sandboxes peuvent atteindre

Dans cma-values.yaml, egress.mode: publicInternet permet aux sandboxes d’accéder à l’internet public.

Ce tableau le compare aux deux autres modes :

egress.modeCe que les sandboxes peuvent atteindre
closed, la valeur par défautVos serveurs et le dispatcher, et aucun serveur DNS
publicInternetVos serveurs, le dispatcher, un serveur DNS et l’internet public
gatewayVos serveurs, le dispatcher et, via la « egress gateway » (passerelle de sortie), les hôtes que vous indiquez. Consultez Activer la passerelle sur Kubernetes.

Autres clusters

Définissez platform dans cma-values.yaml sur eks pour Amazon EKS, sur aks pour Azure Kubernetes Service (AKS), ou sur generic pour tout autre cluster. Les trois nécessitent le contrôleur Agent Sandbox en amont avec ses extensions, ainsi qu’un plugin réseau qui applique NetworkPolicy. Ils nécessitent également :

  • Amazon EKS : Un groupe de nœuds avec runsc de gVisor enregistré comme gestionnaire containerd nommé runsc. Ajoutez aux nœuds le label cma.anthropic.com/sandbox-node=true et le taint cma.anthropic.com/sandbox-node=true:NoSchedule. Le chart enregistre la RuntimeClass gvisor pour ce gestionnaire.
  • AKS : Un pool de nœuds avec Pod Sandboxing, avec le même label et le même taint que sur Amazon EKS. Indiquez le nom du moteur de règles réseau du cluster (cilium, calico ou azure) dans aks.networkPolicy. Conservez egress.mode: publicInternet, le seul mode que le chart accepte sur AKS. Testez le chart sur votre cluster avant que des agents n’y effectuent un travail réel.
  • Tout autre cluster : Une RuntimeClass pour gVisor ou un autre environnement d’exécution isolé. Indiquez son nom dans runtimeClass.name.

Le dossier kubernetes/chart/examples/ de l’archive contient un fichier de valeurs complet pour chaque type de cluster.

Libérer le volume d’une session

Avec les valeurs par défaut du chart, chaque session dispose d’un volume de 10 GiB pour /workspace. Le volume subsiste après la disparition du pod de la session, de sorte que le message suivant de la session retrouve ses fichiers.

Pour libérerProcédez ainsi
Le volume d’une sessionArchivez la session une fois son tour terminé. Le dispatcher supprime généralement le volume dans un délai d’environ 5 minutes.
Les volumes des sessions que personne n’archiveDéfinissez dispatcher.retentionDays dans cma-values.yaml. Le dispatcher supprime alors un volume dès que sa session est restée inactive pendant ce nombre de jours, et le message suivant de la session commence avec un /workspace vide. La valeur par défaut du chart, 0, conserve tous les volumes.

Les commandes de cette section concernent GKE. Sur un autre cluster, utilisez sandboxclaims à la place de sandboxes.

La suppression d’une session ne libère pas son volume. Archivez d’abord la session. Ne la supprimez qu’une fois que kubectl -n cma get sandboxes -l anthropic.com/session-id=<session-id> ne répertorie plus rien.

Si vous avez supprimé une session sans l’archiver, libérez vous-même son volume :

  1. Trouvez l’ID de la session dans le journal du dispatcher. Cette commande affiche une ligne pour chaque session qui semble supprimée et possède encore un volume, avec l’ID après session_id :

    kubectl -n cma logs deployment/cma-dispatcher --since=6m \
      | grep "could not check the claim's session" | grep "403 Forbidden"

    Le dispatcher écrit ces lignes toutes les 5 minutes. Si la session ne figure pas dans la liste, attendez 5 minutes et exécutez à nouveau la commande.

  2. Confirmez que la session est supprimée. Avec le port redirigé et ANTHROPIC_API_KEY défini comme dans Exécuter une session, exécutez ant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>. Ne poursuivez que si la réponse est 404 Not Found avec Session not found. Si la commande affiche une session, arrêtez-vous : cette session n’est pas supprimée.

  3. Supprimez l’objet Kubernetes qui possède le volume. Les fichiers de la session sont supprimés avec lui :

    kubectl -n cma delete sandboxes -l anthropic.com/session-id=<session-id>

Renouveler les clés et les certificats

Une clé d’environnement est valide pendant 365 jours, et le certificat du dispatcher est valide pendant 825 jours. Renouvelez chacun d’eux avant son expiration.

Au cours des 30 derniers jours de validité d’une clé d’environnement, le serveur journalise un avertissement pour chaque requête qui utilise la clé. L’avertissement commence par environment key is within 30 days of expiry.

Renouveler la clé d’environnement créée par les charts

Pour savoir quand la clé expire, exécutez kubectl -n cma describe secret cma-environment.

Exécutez ces deux commandes au moins une fois au cours des 60 derniers jours de validité de la clé, depuis le répertoire de premier niveau de l’archive de la version installée :

helm upgrade cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait
kubectl -n cma rollout restart deployment/cma-dispatcher

Chaque fois que la commande helm upgrade du chart du serveur s’exécute, elle stocke une nouvelle clé dans le Secret si la clé expire dans les 60 jours. Rien d’autre ne renouvelle la clé. La seconde commande redémarre le dispatcher pour qu’il lise la nouvelle clé.

Renouveler le certificat du dispatcher

Revenez à l’étape « Créer l’espace de noms et le certificat des sandboxes ». Répétez sa commande openssl et les deux commandes kubectl qui la suivent. Redémarrez ensuite le dispatcher avec kubectl -n cma rollout restart deployment/cma-dispatcher.

Remplacer une clé d’environnement pour vos propres workers

Les charts ne renouvellent que leur propre clé. Si vous avez créé une clé vous-même, comme dans Créer un environnement et sa clé, remplacez-la avec la CLI d’administration. La CLI se trouve au premier niveau de l’archive de la version.

Exécutez les commandes dans le deuxième terminal de Exécuter une session, dans lequel ANTHROPIC_API_KEY contient la clé API du serveur. Laissez la redirection de port s’exécuter dans le premier terminal. Si vous accédez à votre serveur à une autre adresse, transmettez cette adresse avec -base-url, et vous n’avez pas besoin de redirection de port.

  1. Créer une nouvelle clé pour le même environnement

    Pour -env, transmettez l’ID de l’environnement :

    echo "$ANTHROPIC_API_KEY" | ./cma-server-admin mint-key \
      -base-url http://127.0.0.1:8400 -env env_01595EKxaaTTGwwY3kyXdtbs -key-file -

    La commande affiche la nouvelle clé, et elle affiche l’ID et la date d’expiration de la clé sur la sortie d’erreur standard.

  2. Faire passer vos workers à la nouvelle clé

    Définissez la nouvelle clé comme ANTHROPIC_ENVIRONMENT_KEY pour chaque processus qui interroge le serveur, puis redémarrez-le.

  3. Révoquer l’ancienne clé

    Un worker qui utilise encore une clé révoquée reçoit une erreur 401 et abandonne la session qu’il servait. Pour trouver l’ID de l’ancienne clé, exécutez list-keys avec les mêmes options -base-url, -env et -key-file. Lorsqu’aucun worker n’utilise plus l’ancienne clé, révoquez-la à l’aide de cet 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 -

Désinstaller la pile

Supprimez d’abord les sandboxes. helm uninstall supprime les règles réseau qui confinent les sandboxes, mais les sandboxes que le dispatcher a créées pour les sessions continuent de s’exécuter.

Ces étapes ne touchent pas à votre base de données, mais elles suppriment les Secrets. Pour réutiliser la base de données, vous avez besoin de votre copie de la clé de chiffrement.

  1. Arrêter le dispatcher et supprimer les sandboxes

    kubectl -n cma scale deployment/cma-dispatcher --replicas=0
    kubectl -n cma delete sandboxwarmpool cma-sandbox
    kubectl -n cma delete sandboxclaims --all

    Sur GKE, exécutez également cette commande :

    kubectl -n cma delete sandboxes --all
  2. Attendre la disparition des sandboxes

    Répétez cette commande jusqu’à ce que les sandboxes, leurs pods et leurs volumes aient disparu :

    kubectl -n cma get sandboxes,pods,pvc
  3. Désinstaller les charts et supprimer les espaces de noms

    helm uninstall cma --namespace cma
    helm uninstall cma-server --namespace cma-server
    kubectl delete namespace cma cma-server

Étapes suivantes

Cette page vous a-t-elle été utile ?