Claude Platform Docs
Managed AgentsManaged Agents auto-hospedado

Implantar no Kubernetes

Instale o servidor do Claude Managed Agents auto-hospedado e seus sandboxes em um cluster Kubernetes com os dois Helm charts do arquivo compactado da versão e, em seguida, execute uma primeira sessão em um pod de sandbox.

Esta página leva um cluster vazio do Google Kubernetes Engine (GKE) até uma sessão que executa uma ferramenta em um pod de sandbox. Ela usa os dois Helm charts do arquivo compactado da versão, que executam toda a stack no cluster:

  • cma-server: Aplica o esquema do banco de dados e executa dois servidores atrás de um Service, no namespace cma-server.
  • cma-sandboxes: Executa um “dispatcher” (despachante) e os pods de sandbox no namespace cma. O dispatcher consulta o servidor em busca de trabalho e dá a cada sessão seu próprio pod de sandbox, onde um worker executa as ferramentas de shell e de arquivos do agente.

Seu banco de dados PostgreSQL fica fora de ambos. Em outro tipo de cluster, as etapas são as mesmas, mas os pré-requisitos do cluster e alguns valores dos charts são diferentes. Consulte Outros clusters.

Pré-requisitos

  • Um cluster: Kubernetes 1.30 ou posterior, com:
  • Um banco de dados: PostgreSQL 16 ou posterior que o cluster consiga acessar.
  • Um registry: Um do qual o cluster consiga fazer pull. Você mesmo cria as imagens.
  • Uma chave de API do Claude: O servidor a usa para chamadas ao modelo. Para usar outro provedor, consulte Provedor de inferência.
  • Permissões: Direitos de cluster-admin ou equivalentes. A instalação cria namespaces, Roles e um ClusterRoleBinding.
  • Ferramentas na sua máquina: helm, kubectl, docker buildx, openssl e a CLI ant.
  • O arquivo compactado da versão: Para solicitar acesso ao download, entre em contato com a equipe responsável pela sua conta na Anthropic. Extraia o arquivo compactado. Execute todos os comandos desta página a partir do diretório de nível superior dele.

Instalar a stack

  1. Criar e enviar as imagens

    Defina estas variáveis com os seus próprios valores. PLATFORM é a arquitetura dos seus nós. TAG é o número da versão, que está no nome do arquivo compactado da versão, depois do v. Ambos os charts esperam imagens que tenham esse número de versão como tag.

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

    Em seguida, crie e envie as três imagens:

    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. Criar um arquivo de segredos e o banco de dados

    Crie um arquivo com uma senha de banco de dados gerada e um espaço reservado para sua chave de API do Claude:

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

    Abra o secrets.env em um editor e substitua sk-ant-... pela sua chave de API do Claude. Em seguida, conecte-se ao seu servidor de banco de dados como administrador, por exemplo com o psql. Execute este SQL usando o valor de PG_PASSWORD no lugar de ...:

    CREATE ROLE cma_server LOGIN PASSWORD '...';
    GRANT cma_server TO CURRENT_USER;
    CREATE DATABASE cma_server OWNER cma_server;
  3. Criar o namespace e os Secrets do servidor

    Crie o namespace do servidor e seus 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"

    Exiba a chave de criptografia com echo "$ENCRYPTION_KEY" e guarde uma cópia fora do cluster. O servidor usa essa chave para criptografar as credenciais que ele armazena, e um banco de dados restaurado precisa dela. Em seguida, exclua o secrets.env. O Secret cma-server-db guarda a senha do banco de dados.

  4. Criar o namespace e o certificado dos sandboxes

    Crie o namespace dos sandboxes e um certificado que o dispatcher fornece e no qual os sandboxes confiam:

    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 o servidor

    Salve isto como cma-server-values.yaml, com seu registry e o endereço do seu banco de dados:

    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

    Em seguida, instale o 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

    A instalação cria o ambiente default e armazena sua chave no Secret cma-environment no namespace cma. O segundo comando exibe uma linha que começa com filled Secret cma/cma-environment. Se um primeiro helm install falhar, execute helm uninstall para essa release antes de instalar novamente.

  6. Encontrar os endereços do cluster a bloquear

    Esta instalação permite que os sandboxes acessem a internet pública. O endpoint da API de um cluster geralmente tem um endereço público, então os sandboxes também poderiam acessá-lo. Para bloqueá-lo, você lista o endereço dele em egress.clusterCIDRs na próxima etapa.

    Para exibir o endereço, execute gcloud container clusters describe my-cluster --format 'value(endpoint)' com o nome do seu cluster.

    O próprio chart bloqueia os intervalos privados 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 e 100.64.0.0/10. Se o seu cluster tiver um intervalo de pods, serviços ou nós fora desses quatro, liste esse intervalo também.

  7. Instalar os sandboxes

    Salve isto como cma-values.yaml, com seu registry e os endereços da etapa 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 o caminho até seus servidores. Para comparar publicInternet com os dois outros modos, consulte O que os sandboxes podem acessar.

    Se o seu cluster usa uma destas configurações de DNS, adicione uma linha ao arquivo:

    • Cloud DNS para GKE, que os clusters Autopilot usam: gke: {dns: cloudDns}
    • NodeLocal DNSCache: gke: {dns: nodeLocalCache, kubeDnsUpstreamIP: <address>}. Para exibir o endereço, execute kubectl -n kube-system get svc kube-dns-upstream -o jsonpath='{.spec.clusterIP}'.

    Em seguida, instale o chart:

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

Executar uma sessão

Estas etapas usam os nomes de uma nova instalação. Se o seu arquivo de valores do servidor tiver earlierNames: true, encontre os nomes a usar em vez destes em Kubernetes: os nomes dos seus objetos.

  1. Encaminhar a porta do servidor

    Em um terminal, encaminhe a porta do servidor para a sua máquina:

    kubectl -n cma-server port-forward svc/cma-server 8400:8400
  2. Apontar a CLI para o seu servidor

    Em um segundo terminal, aponte a CLI ant para a porta encaminhada e leia a chave de API do servidor do 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. Criar um agente e pedir que ele execute um comando

    Siga três etapas de Execute sua primeira sessão do início rápido: Crie um agente, Inicie uma sessão e Peça ao agente para executar um comando. Em Inicie uma sessão, substitua compose-sandbox por default, o nome do ambiente que os charts criam.

  4. Encontrar o pod de sandbox

    O agente responde com o hostname do pod que executou o comando. Em um terceiro terminal, kubectl -n cma get pods lista um pod com esse nome ao lado do pod do dispatcher. Por padrão, o pod é removido cerca de 5 minutos depois que o turno do agente termina. Se ele não estiver na lista, peça ao agente para executar hostname novamente.

    Para sair do chat, pressione Ctrl+C.

Colocar TLS na frente do servidor

O servidor usa HTTP simples na porta 8400, e as requisições das suas aplicações carregam a chave de API do servidor. Antes que clientes de fora do cluster se conectem, coloque um “load balancer” (balanceador de carga) ou um ingress que termine o TLS na frente do Service cma-server. Ele deve:

  • Repassar os caminhos das requisições sem alterações.
  • Aceitar corpos de requisição de até 32 MiB.
  • Repassar as respostas sem buffer.
  • Definir um tempo limite de leitura padrão de 2 minutos. Para requisições Git, definir um tempo limite de leitura de 10 minutos para caminhos que correspondam a ^/cma-[a-z]+/git/.
  • Enviar tráfego apenas para servidores que estejam prontos. O Service cma-server já faz isso. Um balanceador de carga que acessa os pods diretamente deve verificar /cma-server/readyz em cada pod e ignorar aquele que retornar 503.
  • Nunca reenviar um POST que um servidor já aceitou.
  • Nunca armazenar uma resposta em cache.

Para verificar a partir de fora do cluster, execute curl -s https://<host>/cma-server/healthz. A resposta é {"status":"ok"}.

O que os sandboxes podem acessar

Em cma-values.yaml, egress.mode: publicInternet permite que os sandboxes acessem a internet pública.

Esta tabela o compara com os dois outros modos:

egress.modeO que os sandboxes podem acessar
closed, o padrãoSeus servidores e o dispatcher, e nenhum servidor DNS
publicInternetSeus servidores, o dispatcher, um servidor DNS e a internet pública
gatewaySeus servidores, o dispatcher e, por meio do gateway de egress, os hosts que você listar. Consulte Ativar o gateway no Kubernetes.

Outros clusters

Defina platform em cma-values.yaml como eks para o Amazon EKS, como aks para o Azure Kubernetes Service (AKS), ou como generic para qualquer outro cluster. Os três precisam do controlador Agent Sandbox upstream com suas extensões e de um plugin de rede que aplique NetworkPolicy. Eles também precisam de:

  • Amazon EKS: Um grupo de nós com o runsc do gVisor registrado como um handler do containerd chamado runsc. Aplique o rótulo cma.anthropic.com/sandbox-node=true aos nós e o taint cma.anthropic.com/sandbox-node=true:NoSchedule. O chart registra a RuntimeClass gvisor para esse handler.
  • AKS: Um pool de nós com Pod Sandboxing, com o mesmo rótulo e o mesmo taint do Amazon EKS. Coloque o nome do mecanismo de política de rede do cluster (cilium, calico ou azure) em aks.networkPolicy. Mantenha egress.mode: publicInternet, o único modo que o chart aceita no AKS. Teste o chart no seu cluster antes que os agentes façam trabalho real nele.
  • Qualquer outro cluster: Uma RuntimeClass para gVisor ou outro runtime em sandbox. Coloque o nome dela em runtimeClass.name.

A pasta kubernetes/chart/examples/ no arquivo compactado da versão tem um arquivo de valores completo para cada tipo de cluster.

Liberar o volume de uma sessão

Pelos padrões do chart, cada sessão tem um volume de 10 GiB para /workspace. O volume permanece depois que o pod da sessão é removido, para que a próxima mensagem da sessão encontre seus arquivos.

Para liberarFaça isto
O volume de uma sessãoArquive a sessão depois que o turno dela terminar. O dispatcher geralmente exclui o volume em cerca de 5 minutos.
Os volumes de sessões que ninguém arquivaDefina dispatcher.retentionDays em cma-values.yaml. O dispatcher então exclui um volume quando a sessão dele fica ociosa por esse número de dias, e a próxima mensagem da sessão começa com um /workspace vazio. O padrão do chart, 0, mantém todos os volumes.

Os comandos desta seção são para o GKE. Em outro cluster, use sandboxclaims no lugar de sandboxes.

Excluir uma sessão não libera o volume dela. Arquive a sessão primeiro. Exclua-a somente depois que kubectl -n cma get sandboxes -l anthropic.com/session-id=<session-id> não listar nada.

Se você excluiu uma sessão sem arquivá-la, libere o volume dela você mesmo:

  1. Encontre o ID da sessão no log do dispatcher. Este comando exibe uma linha para cada sessão que parece ter sido excluída e ainda tem um volume, com o ID depois de session_id:

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

    O dispatcher escreve essas linhas a cada 5 minutos. Se a sessão não estiver listada, aguarde 5 minutos e execute o comando novamente.

  2. Confirme que a sessão foi excluída. Com a porta encaminhada e ANTHROPIC_API_KEY definida como em Executar uma sessão, execute ant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>. Continue somente se a resposta for 404 Not Found com Session not found. Se o comando exibir uma sessão, pare: essa sessão não foi excluída.

  3. Exclua o objeto do Kubernetes que é dono do volume. Os arquivos da sessão são removidos junto com ele:

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

Renovar chaves e certificados

Uma chave de ambiente é válida por 365 dias, e o certificado do dispatcher é válido por 825 dias. Renove cada um antes que expire.

Nos últimos 30 dias de validade de uma chave de ambiente, o servidor registra um aviso em cada requisição que usa a chave. O aviso começa com environment key is within 30 days of expiry.

Renovar a chave de ambiente que os charts criaram

Para ver quando a chave expira, execute kubectl -n cma describe secret cma-environment.

Execute estes dois comandos pelo menos uma vez nos últimos 60 dias de validade da chave, a partir do diretório de nível superior do arquivo compactado da versão 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 o comando helm upgrade do chart do servidor é executado, ele armazena uma nova chave no Secret se a chave expirar em até 60 dias. Nada mais renova a chave. O segundo comando reinicia o dispatcher para que ele leia a nova chave.

Renovar o certificado do dispatcher

Volte à etapa “Criar o namespace e o certificado dos sandboxes”. Repita o comando openssl dela e os dois comandos kubectl que vêm depois dele. Em seguida, reinicie o dispatcher com kubectl -n cma rollout restart deployment/cma-dispatcher.

Substituir uma chave de ambiente para seus próprios workers

Os charts renovam apenas a própria chave. Se você mesmo criou uma chave, como em Criar um ambiente e a chave dele, substitua-a com a CLI de administração. A CLI fica no nível superior do arquivo compactado da versão.

Execute os comandos no segundo terminal de Executar uma sessão, em que ANTHROPIC_API_KEY contém a chave de API do servidor. Mantenha o encaminhamento de porta em execução no primeiro terminal. Se você acessa seu servidor em outro endereço, passe esse endereço como -base-url, e você não precisa de encaminhamento de porta.

  1. Criar uma nova chave para o mesmo ambiente

    Em -env, passe o ID do ambiente:

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

    O comando exibe a nova chave, e exibe o ID e a expiração da chave na saída de erro padrão.

  2. Mover seus workers para a nova chave

    Defina a nova chave como ANTHROPIC_ENVIRONMENT_KEY para cada processo que faz consultas e reinicie-o.

  3. Revogar a chave antiga

    Um worker que ainda usa uma chave revogada recebe um erro 401 e abandona a sessão que estava atendendo. Para encontrar o ID da chave antiga, execute list-keys com as mesmas flags -base-url, -env e -key-file. Quando nenhum worker usar mais a chave antiga, revogue-a por esse 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 a stack

Exclua os sandboxes primeiro. O helm uninstall exclui as políticas de rede que confinam os sandboxes, mas os sandboxes que o dispatcher criou para as sessões continuam em execução.

Estas etapas não afetam seu banco de dados, mas excluem os Secrets. Para usar o banco de dados novamente, você precisa da sua cópia da chave de criptografia.

  1. Parar o dispatcher e excluir os sandboxes

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

    No GKE, execute também este comando:

    kubectl -n cma delete sandboxes --all
  2. Aguardar até que os sandboxes sejam removidos

    Repita este comando até que os sandboxes, seus pods e seus volumes sejam removidos:

    kubectl -n cma get sandboxes,pods,pvc
  3. Desinstalar os charts e excluir os namespaces

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

Próximos passos

Esta página foi útil?