---
title: Implantar no Kubernetes
url: https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/kubernetes
description: 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.
---

<Note>
  Para solicitar acesso ao Claude Managed Agents auto-hospedado, entre em contato com a equipe da sua conta na Anthropic.
</Note>

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](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/kubernetes#other-clusters).

## Pré-requisitos

* **Um cluster:** Kubernetes 1.30 ou posterior, com:

  * O controlador Agent Sandbox (no GKE, o [complemento Agent Sandbox](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/how-install-agent-sandbox))
  * Nós que executam gVisor (no GKE, um [“node pool” (pool de nós) do GKE Sandbox](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/sandbox-pods))
  * Um plugin de rede que aplique NetworkPolicy (no GKE, Dataplane V2 ou Calico)

* **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](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/inference-provider).

* **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`](https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/cli/quickstart#installation).

* **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

<Steps>
  <Step title="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.

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

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

    ```bash
    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
    ```
  </Step>

  <Step title="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:

    ```bash
    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 `...`:

    ```sql
    CREATE ROLE cma_server LOGIN PASSWORD '...';
    GRANT cma_server TO CURRENT_USER;
    CREATE DATABASE cma_server OWNER cma_server;
    ```
  </Step>

  <Step title="Criar o namespace e os Secrets do servidor">
    Crie o namespace do servidor e seus Secrets:

    ```bash
    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.
  </Step>

  <Step title="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:

    ```bash
    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 -
    ```
  </Step>

  <Step title="Instalar o servidor">
    Salve isto como `cma-server-values.yaml`, com seu registry e o endereço do seu banco de dados:

    ```yaml
    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:

    ```bash
    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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="Instalar os sandboxes">
    Salve isto como `cma-values.yaml`, com seu registry e os endereços da etapa anterior:

    ```yaml
    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](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/kubernetes#what-sandboxes-can-reach).

    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:

    ```bash
    helm install cma kubernetes/chart --namespace cma -f cma-values.yaml --wait
    ```
  </Step>
</Steps>

## 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](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/upgrade#object-names).

<Steps>
  <Step title="Encaminhar a porta do servidor">
    Em um terminal, encaminhe a porta do servidor para a sua máquina:

    ```bash
    kubectl -n cma-server port-forward svc/cma-server 8400:8400
    ```
  </Step>

  <Step title="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`:

    ```bash
    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)
    ```
  </Step>

  <Step title="Criar um agente e pedir que ele execute um comando">
    Siga três etapas de [Execute sua primeira sessão](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/quickstart#run-your-first-session) 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.
  </Step>

  <Step title="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.
  </Step>
</Steps>

## 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.mode`      | O que os sandboxes podem acessar                                                                                                                                                                                                                         |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `closed`, o padrão | Seus servidores e o dispatcher, e nenhum servidor DNS                                                                                                                                                                                                    |
| `publicInternet`   | Seus servidores, o dispatcher, um servidor DNS e a internet pública                                                                                                                                                                                      |
| `gateway`          | Seus servidores, o dispatcher e, por meio do gateway de egress, os hosts que você listar. Consulte [Ativar o gateway no Kubernetes](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/agent-identity#turn-on-the-gateway-on-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 liberar                              | Faça isto                                                                                                                                                                                                                                                               |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| O volume de uma sessão                    | Arquive 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 arquiva | Defina `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`:

   ```bash
   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](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/kubernetes#run-a-session), 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:

   ```bash
   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:

```bash
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](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/call-the-api#create-an-environment-and-its-key), 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](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/kubernetes#run-a-session), 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.

<Steps>
  <Step title="Criar uma nova chave para o mesmo ambiente">
    Em `-env`, passe o ID do ambiente:

    ```bash
    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.
  </Step>

  <Step title="Mover seus workers para a nova chave">
    Defina a nova chave como `ANTHROPIC_ENVIRONMENT_KEY` para cada processo que faz consultas e reinicie-o.
  </Step>

  <Step title="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:

    ```bash
    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 -
    ```
  </Step>
</Steps>

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

<Steps>
  <Step title="Parar o dispatcher e excluir os sandboxes">
    ```bash
    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:

    ```bash
    kubectl -n cma delete sandboxes --all
    ```
  </Step>

  <Step title="Aguardar até que os sandboxes sejam removidos">
    Repita este comando até que os sandboxes, seus pods e seus volumes sejam removidos:

    ```bash
    kubectl -n cma get sandboxes,pods,pvc
    ```
  </Step>

  <Step title="Desinstalar os charts e excluir os namespaces">
    ```bash
    helm uninstall cma --namespace cma
    helm uninstall cma-server --namespace cma-server
    kubectl delete namespace cma cma-server
    ```
  </Step>
</Steps>

## Próximos passos

* **Atualizar:** [Atualizar o Claude Managed Agents auto-hospedado](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/upgrade) contém os comandos `helm upgrade`.
* **Alterar outros valores dos charts:** Consulte os comentários em `kubernetes/server/chart/values.yaml` para o servidor e em `kubernetes/chart/values.yaml` para os sandboxes.
* **Chamar a API a partir do seu código:** Consulte [Chamar a API em um servidor auto-hospedado](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/call-the-api).
* **Trabalhar em um navegador:** Consulte [Use o console no seu servidor](https://platform.claude.com/docs/pt-BR/managed-agents/self-hosted/console).
