---
title: Развёртывание в Kubernetes
url: https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes
description: Установите самостоятельно размещаемый сервер Claude Managed Agents и его песочницы в кластер Kubernetes с помощью двух Helm-чартов из архива выпуска, а затем запустите первый сеанс в поде песочницы.
---

<Note>
  Чтобы запросить доступ к самостоятельно размещаемому Claude Managed Agents, обратитесь к команде, работающей с вашей учётной записью в Anthropic.
</Note>

На этой странице описан путь от пустого кластера Google Kubernetes Engine (GKE) до сеанса, который запускает инструмент в поде песочницы. Для этого используются два Helm-чарта из «release archive» (архива выпуска), которые запускают весь стек в кластере:

* **`cma-server`:** применяет схему базы данных и запускает два сервера за объектом Service в пространстве имён `cma-server`.
* **`cma-sandboxes`:** запускает диспетчер и поды песочниц в пространстве имён `cma`. Диспетчер опрашивает сервер на наличие работы и передаёт каждый сеанс отдельному «sandbox pod» (поду песочницы), в котором воркер запускает инструменты агента для работы с оболочкой и файлами.

Ваша база данных PostgreSQL остаётся вне обоих чартов. В кластере другого типа шаги те же самые, но отличаются требования к кластеру и несколько значений чартов. См. раздел [Другие кластеры](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes#other-clusters).

## Предварительные требования

* **Кластер:** Kubernetes 1.30 или новее, в котором есть:

  * контроллер Agent Sandbox (в GKE — [дополнение Agent Sandbox](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/how-install-agent-sandbox));
  * узлы, на которых работает gVisor (в GKE — [пул узлов GKE Sandbox](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/sandbox-pods));
  * сетевой плагин, который применяет NetworkPolicy (в GKE — Dataplane V2 или Calico).

* **База данных:** PostgreSQL 16 или новее, доступная из кластера.

* **Реестр:** такой, из которого кластер может загружать образы. Образы вы собираете сами.

* **Ключ Claude API:** сервер использует его для вызовов модели. Чтобы использовать другого поставщика, см. [Поставщик инференса](https://platform.claude.com/docs/ru/managed-agents/self-hosted/inference-provider).

* **Права доступа:** права cluster-admin или эквивалентные. При установке создаются пространства имён, объекты Role и ClusterRoleBinding.

* **Инструменты на вашем компьютере:** `helm`, `kubectl`, `docker buildx`, `openssl` и [`ant` CLI](https://platform.claude.com/docs/ru/cli-sdks-libraries/cli/quickstart#installation).

* **Архив выпуска:** чтобы запросить доступ к загрузке, обратитесь к команде, которая ведёт ваш аккаунт в Anthropic. Распакуйте архив. Выполняйте все команды на этой странице из его корневого каталога.

## Установка стека

<Steps>
  <Step title="Сборка и отправка образов">
    Задайте этим переменным свои значения. `PLATFORM` — архитектура ваших узлов. `TAG` — это версия выпуска, которая указана в имени архива после `v`. Оба чарта ожидают образы, у которых эта версия указана в качестве тега.

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

    Затем соберите и отправьте три образа:

    ```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="Создание файла секретов и базы данных">
    Создайте файл со сгенерированным паролем базы данных и заполнителем для вашего ключа Claude API:

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

    Откройте `secrets.env` в редакторе и замените `sk-ant-...` своим ключом Claude API. Затем подключитесь к серверу базы данных как администратор, например с помощью `psql`. Выполните этот SQL, подставив значение `PG_PASSWORD` вместо `...`:

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

  <Step title="Создание пространства имён и объектов Secret для сервера">
    Создайте пространство имён сервера и его объекты Secret:

    ```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"
    ```

    Выведите ключ шифрования командой `echo "$ENCRYPTION_KEY"` и сохраните его копию вне кластера. Этим ключом сервер шифрует учётные данные, которые он хранит, и он понадобится для восстановленной базы данных. Затем удалите `secrets.env`. Пароль базы данных хранится в объекте Secret `cma-server-db`.
  </Step>

  <Step title="Создание пространства имён и сертификата для песочниц">
    Создайте пространство имён песочниц и сертификат, который предъявляет диспетчер и которому доверяют песочницы:

    ```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="Установка сервера">
    Сохраните следующее как `cma-server-values.yaml`, указав ваш реестр и адрес вашей базы данных:

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

    Затем установите чарт:

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

    Установка создаёт окружение `default` и сохраняет его ключ в объекте Secret `cma-environment` в пространстве имён `cma`. Вторая команда выводит одну строку, начинающуюся с `filled Secret cma/cma-environment`. Если первый `helm install` завершился ошибкой, выполните `helm uninstall` для этого релиза, прежде чем устанавливать снова.
  </Step>

  <Step title="Поиск адресов кластера для блокировки">
    Эта установка открывает песочницам доступ к публичному интернету. Конечная точка API кластера обычно имеет публичный адрес, поэтому песочницы тоже могли бы к ней обращаться. Чтобы заблокировать её, на следующем шаге вы укажете её адрес в `egress.clusterCIDRs`.

    Чтобы вывести адрес, выполните `gcloud container clusters describe my-cluster --format 'value(endpoint)'`, указав имя вашего кластера.

    Сам чарт блокирует частные диапазоны `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` и `100.64.0.0/10`. Если в вашем кластере есть диапазон подов, сервисов или узлов вне этих четырёх, также укажите этот диапазон.
  </Step>

  <Step title="Установка песочниц">
    Сохраните следующее как `cma-values.yaml`, указав ваш реестр и адреса из предыдущего шага:

    ```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` открывает путь к вашим серверам. Чтобы сравнить `publicInternet` с двумя другими режимами, см. раздел [К чему могут обращаться песочницы](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes#what-sandboxes-can-reach).

    Если в вашем кластере используется одна из этих конфигураций DNS, добавьте в файл строку:

    * **Cloud DNS for GKE, который используют кластеры Autopilot:** `gke: {dns: cloudDns}`
    * **NodeLocal DNSCache:** `gke: {dns: nodeLocalCache, kubeDnsUpstreamIP: <address>}`. Чтобы вывести адрес, выполните `kubectl -n kube-system get svc kube-dns-upstream -o jsonpath='{.spec.clusterIP}'`.

    Затем установите чарт:

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

## Запуск сеанса

В этих шагах используются имена новой установки. Если в файле значений вашего сервера указано `earlierNames: true`, найдите имена, которые нужно использовать вместо них, в разделе [Kubernetes: имена ваших объектов](https://platform.claude.com/docs/ru/managed-agents/self-hosted/upgrade#object-names).

<Steps>
  <Step title="Перенаправление порта сервера">
    В одном терминале перенаправьте порт сервера на ваш компьютер:

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

  <Step title="Направление CLI на ваш сервер">
    Во втором терминале направьте `ant` CLI на перенаправленный порт и прочитайте ключ API сервера из 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="Создание агента и запрос на выполнение команды">
    Выполните три шага из раздела [Запуск первого сеанса](https://platform.claude.com/docs/ru/managed-agents/self-hosted/quickstart#run-your-first-session) краткого руководства: создайте агента, запустите сеанс и попросите агента выполнить команду. На шаге запуска сеанса замените `compose-sandbox` на `default` — имя окружения, которое создают чарты.
  </Step>

  <Step title="Поиск пода песочницы">
    Агент отвечает именем хоста пода, в котором была выполнена команда. В третьем терминале `kubectl -n cma get pods` показывает под с этим именем рядом с подом диспетчера. По умолчанию под удаляется примерно через 5 минут после завершения хода агента. Если его нет в списке, снова попросите агента выполнить `hostname`.

    Чтобы выйти из чата, нажмите Ctrl+C.
  </Step>
</Steps>

## Размещение TLS перед сервером

Сервер работает по обычному HTTP на порту 8400, а запросы от ваших приложений содержат ключ API сервера. Прежде чем к нему будут подключаться клиенты извне кластера, разместите перед объектом Service `cma-server` балансировщик нагрузки или ingress, который завершает TLS. Он должен:

* Передавать пути запросов без изменений.
* Принимать тела запросов размером до 32 МиБ.
* Передавать ответы без буферизации.
* Устанавливать тайм-аут чтения по умолчанию 2 минуты. Для запросов Git устанавливать тайм-аут чтения 10 минут для путей, соответствующих `^/cma-[a-z]+/git/`.
* Направлять трафик только на готовые серверы. Объект Service `cma-server` уже делает это. Балансировщик нагрузки, который обращается к подам напрямую, должен проверять `/cma-server/readyz` на каждом поде и пропускать под, который возвращает `503`.
* Никогда не отправлять повторно `POST`, который сервер уже принял.
* Никогда не кэшировать ответы.

Чтобы проверить его извне кластера, выполните `curl -s https://<host>/cma-server/healthz`. Ответ: `{"status":"ok"}`.

## К чему могут обращаться песочницы

В `cma-values.yaml` значение `egress.mode: publicInternet` открывает песочницам доступ к публичному интернету.

В этой таблице этот режим сравнивается с двумя другими:

| `egress.mode`                   | К чему могут обращаться песочницы                                                                                                                                                                                                                             |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `closed`, значение по умолчанию | Ваши серверы и диспетчер, но ни один DNS-сервер                                                                                                                                                                                                               |
| `publicInternet`                | Ваши серверы, диспетчер, DNS-сервер и публичный интернет                                                                                                                                                                                                      |
| `gateway`                       | Ваши серверы, диспетчер и — через «egress gateway» (шлюз исходящего трафика) — перечисленные вами хосты. См. [Включение шлюза в Kubernetes](https://platform.claude.com/docs/ru/managed-agents/self-hosted/agent-identity#turn-on-the-gateway-on-kubernetes). |

## Другие кластеры

Задайте в `cma-values.yaml` параметр `platform` со значением `eks` для Amazon EKS, `aks` для Azure Kubernetes Service (AKS) или `generic` для любого другого кластера. Всем трём вариантам нужен контроллер Agent Sandbox из исходного открытого проекта (upstream) с его расширениями и сетевой плагин, который применяет NetworkPolicy. Кроме того, им нужны:

* **Amazon EKS:** группа узлов, в которой `runsc` из gVisor зарегистрирован как обработчик containerd с именем `runsc`. Добавьте узлам метку `cma.anthropic.com/sandbox-node=true` и taint `cma.anthropic.com/sandbox-node=true:NoSchedule`. Чарт регистрирует RuntimeClass `gvisor` для этого обработчика.
* **AKS:** пул узлов с Pod Sandboxing, с той же меткой и тем же taint, что и в Amazon EKS. Укажите имя механизма сетевых политик кластера (`cilium`, `calico` или `azure`) в `aks.networkPolicy`. Оставьте `egress.mode: publicInternet` — это единственный режим, который чарт принимает в AKS. Протестируйте чарт в своём кластере, прежде чем агенты начнут выполнять в нём реальную работу.
* **Любой другой кластер:** RuntimeClass для gVisor или другой изолирующей среды выполнения. Укажите её имя в `runtimeClass.name`.

Каталог `kubernetes/chart/examples/` в архиве содержит полный файл значений для каждого типа кластера.

## Освобождение тома сеанса

При значениях чарта по умолчанию каждый сеанс получает «volume» (том) объёмом 10 ГиБ для `/workspace`. Том сохраняется после удаления пода сеанса, поэтому следующее сообщение сеанса находит его файлы.

| Что освободить                            | Что сделать                                                                                                                                                                                                                                                       |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Том одного сеанса                         | Архивируйте сеанс после завершения его хода. Диспетчер обычно удаляет том примерно в течение 5 минут.                                                                                                                                                             |
| Тома сеансов, которые никто не архивирует | Задайте `dispatcher.retentionDays` в `cma-values.yaml`. Тогда диспетчер удаляет том, как только его сеанс простаивает указанное число дней, и следующее сообщение сеанса начинается с пустого `/workspace`. Значение чарта по умолчанию, `0`, сохраняет все тома. |

Команды в этом разделе предназначены для GKE. В другом кластере используйте `sandboxclaims` вместо `sandboxes`.

Удаление сеанса не освобождает его том. Сначала архивируйте сеанс. Удаляйте его только после того, как `kubectl -n cma get sandboxes -l anthropic.com/session-id=<session-id>` ничего не выведет.

Если вы удалили сеанс, не архивировав его, освободите его том самостоятельно:

1. Найдите идентификатор сеанса в журнале диспетчера. Эта команда выводит строку для каждого сеанса, который, по-видимому, удалён, но всё ещё имеет том; идентификатор указан после `session_id`:

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

   Диспетчер записывает эти строки каждые 5 минут. Если сеанса нет в списке, подождите 5 минут и выполните команду снова.

2. Убедитесь, что сеанс удалён. При перенаправленном порте и заданном `ANTHROPIC_API_KEY`, как в разделе [Запуск сеанса](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes#run-a-session), выполните `ant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>`. Продолжайте, только если ответ — `404 Not Found` с `Session not found`. Если команда выводит сеанс, остановитесь: этот сеанс не удалён.

3. Удалите объект Kubernetes, которому принадлежит том. Вместе с ним удаляются файлы сеанса:

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

## Обновление ключей и сертификатов

Ключ окружения действителен 365 дней, а сертификат диспетчера — 825 дней. Обновляйте каждый из них до истечения срока действия.

В последние 30 дней действия ключа окружения сервер записывает в журнал предупреждение при каждом запросе, использующем этот ключ. Предупреждение начинается с `environment key is within 30 days of expiry`.

### Обновление ключа окружения, созданного чартами

Чтобы узнать, когда истекает срок действия ключа, выполните `kubectl -n cma describe secret cma-environment`.

Выполните эти две команды хотя бы один раз в последние 60 дней действия ключа из корневого каталога архива установленного выпуска:

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

Каждый раз, когда выполняется команда `helm upgrade` для чарта сервера, она сохраняет новый ключ в объекте Secret, если срок действия ключа истекает в течение 60 дней. Больше ничто не обновляет ключ. Вторая команда перезапускает диспетчер, чтобы он прочитал новый ключ.

### Обновление сертификата диспетчера

Вернитесь к шагу «Создание пространства имён и сертификата для песочниц». Повторите его команду `openssl` и две следующие за ней команды `kubectl`. Затем перезапустите диспетчер командой `kubectl -n cma rollout restart deployment/cma-dispatcher`.

### Замена ключа окружения для ваших собственных воркеров

Чарты обновляют только свой собственный ключ. Если вы создали ключ сами, как описано в разделе [Создание окружения и его ключа](https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api#create-an-environment-and-its-key), замените его с помощью административного CLI. CLI находится в корневом каталоге архива выпуска.

Выполняйте команды во втором терминале из раздела [Запуск сеанса](https://platform.claude.com/docs/ru/managed-agents/self-hosted/kubernetes#run-a-session), в котором `ANTHROPIC_API_KEY` содержит ключ API сервера. Не останавливайте перенаправление порта в первом терминале. Если вы обращаетесь к серверу по другому адресу, передайте этот адрес в `-base-url`, и перенаправление порта вам не понадобится.

<Steps>
  <Step title="Создание нового ключа для того же окружения">
    В `-env` передайте идентификатор окружения:

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

    Команда выводит новый ключ, а идентификатор ключа и срок его действия выводит в стандартный поток ошибок.
  </Step>

  <Step title="Перевод воркеров на новый ключ">
    Задайте новый ключ в `ANTHROPIC_ENVIRONMENT_KEY` для каждого процесса, который выполняет опрос, и перезапустите его.
  </Step>

  <Step title="Отзыв старого ключа">
    Воркер, который всё ещё использует отозванный ключ, получает ошибку `401` и прекращает обслуживать свой сеанс. Чтобы найти идентификатор старого ключа, выполните `list-keys` с теми же флагами `-base-url`, `-env` и `-key-file`. Когда старый ключ больше не использует ни один воркер, отзовите его по этому идентификатору:

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

## Удаление стека

Сначала удалите песочницы. `helm uninstall` удаляет сетевые политики, которые ограничивают песочницы, но песочницы, созданные диспетчером для сеансов, продолжают работать.

Эти шаги не затрагивают вашу базу данных, но удаляют объекты Secret. Чтобы снова использовать базу данных, вам понадобится ваша копия ключа шифрования.

<Steps>
  <Step title="Остановка диспетчера и удаление песочниц">
    ```bash
    kubectl -n cma scale deployment/cma-dispatcher --replicas=0
    kubectl -n cma delete sandboxwarmpool cma-sandbox
    kubectl -n cma delete sandboxclaims --all
    ```

    В GKE также выполните эту команду:

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

  <Step title="Ожидание удаления песочниц">
    Повторяйте эту команду, пока песочницы, их поды и их тома не будут удалены:

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

  <Step title="Удаление чартов и пространств имён">
    ```bash
    helm uninstall cma --namespace cma
    helm uninstall cma-server --namespace cma-server
    kubectl delete namespace cma cma-server
    ```
  </Step>
</Steps>

## Следующие шаги

* **Обновление:** команды `helm upgrade` приведены на странице [Обновление самостоятельно размещаемого Claude Managed Agents](https://platform.claude.com/docs/ru/managed-agents/self-hosted/upgrade).
* **Изменение других значений чартов:** см. комментарии в `kubernetes/server/chart/values.yaml` для сервера и в `kubernetes/chart/values.yaml` для песочниц.
* **Вызов API из вашего кода:** см. [Вызов API на самостоятельно размещаемом сервере](https://platform.claude.com/docs/ru/managed-agents/self-hosted/call-the-api).
* **Работа в браузере:** см. [Использование консоли на вашем сервере](https://platform.claude.com/docs/ru/managed-agents/self-hosted/console).
