Claude Platform Docs
Управляемые агентыСамостоятельно размещаемый Managed Agents

Развёртывание в Kubernetes

Установите самостоятельно размещаемый сервер Claude Managed Agents и его песочницы в кластер Kubernetes с помощью двух Helm-чартов из архива выпуска, а затем запустите первый сеанс в поде песочницы.

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

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

Ваша база данных PostgreSQL остаётся вне обоих чартов. В кластере другого типа шаги те же самые, но отличаются требования к кластеру и несколько значений чартов. См. раздел Другие кластеры.

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

  • Кластер: Kubernetes 1.30 или новее, в котором есть:
  • База данных: PostgreSQL 16 или новее, доступная из кластера.
  • Реестр: такой, из которого кластер может загружать образы. Образы вы собираете сами.
  • Ключ Claude API: сервер использует его для вызовов модели. Чтобы использовать другого поставщика, см. Поставщик инференса.
  • Права доступа: права cluster-admin или эквивалентные. При установке создаются пространства имён, объекты Role и ClusterRoleBinding.
  • Инструменты на вашем компьютере: helm, kubectl, docker buildx, openssl и ant CLI.
  • Архив выпуска: чтобы запросить доступ к загрузке, обратитесь к команде, которая ведёт ваш аккаунт в Anthropic. Распакуйте архив. Выполняйте все команды на этой странице из его корневого каталога.

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

  1. Сборка и отправка образов

    Задайте этим переменным свои значения. PLATFORM — архитектура ваших узлов. TAG — это версия выпуска, которая указана в имени архива после v. Оба чарта ожидают образы, у которых эта версия указана в качестве тега.

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

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

    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. Создание файла секретов и базы данных

    Создайте файл со сгенерированным паролем базы данных и заполнителем для вашего ключа Claude API:

    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 вместо ...:

    CREATE ROLE cma_server LOGIN PASSWORD '...';
    GRANT cma_server TO CURRENT_USER;
    CREATE DATABASE cma_server OWNER cma_server;
  3. Создание пространства имён и объектов Secret для сервера

    Создайте пространство имён сервера и его объекты Secret:

    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.

  4. Создание пространства имён и сертификата для песочниц

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

    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. Установка сервера

    Сохраните следующее как cma-server-values.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

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

    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 для этого релиза, прежде чем устанавливать снова.

  6. Поиск адресов кластера для блокировки

    Эта установка открывает песочницам доступ к публичному интернету. Конечная точка 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. Если в вашем кластере есть диапазон подов, сервисов или узлов вне этих четырёх, также укажите этот диапазон.

  7. Установка песочниц

    Сохраните следующее как cma-values.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 с двумя другими режимами, см. раздел К чему могут обращаться песочницы.

    Если в вашем кластере используется одна из этих конфигураций 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}'.

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

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

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

В этих шагах используются имена новой установки. Если в файле значений вашего сервера указано earlierNames: true, найдите имена, которые нужно использовать вместо них, в разделе Kubernetes: имена ваших объектов.

  1. Перенаправление порта сервера

    В одном терминале перенаправьте порт сервера на ваш компьютер:

    kubectl -n cma-server port-forward svc/cma-server 8400:8400
  2. Направление CLI на ваш сервер

    Во втором терминале направьте ant CLI на перенаправленный порт и прочитайте ключ API сервера из 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. Создание агента и запрос на выполнение команды

    Выполните три шага из раздела Запуск первого сеанса краткого руководства: создайте агента, запустите сеанс и попросите агента выполнить команду. На шаге запуска сеанса замените compose-sandbox на default — имя окружения, которое создают чарты.

  4. Поиск пода песочницы

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

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

Размещение 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.

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

Задайте в 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:

    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, как в разделе Запуск сеанса, выполните ant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>. Продолжайте, только если ответ — 404 Not Found с Session not found. Если команда выводит сеанс, остановитесь: этот сеанс не удалён.

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

    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 дней действия ключа из корневого каталога архива установленного выпуска:

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.

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

Чарты обновляют только свой собственный ключ. Если вы создали ключ сами, как описано в разделе Создание окружения и его ключа, замените его с помощью административного CLI. CLI находится в корневом каталоге архива выпуска.

Выполняйте команды во втором терминале из раздела Запуск сеанса, в котором ANTHROPIC_API_KEY содержит ключ API сервера. Не останавливайте перенаправление порта в первом терминале. Если вы обращаетесь к серверу по другому адресу, передайте этот адрес в -base-url, и перенаправление порта вам не понадобится.

  1. Создание нового ключа для того же окружения

    В -env передайте идентификатор окружения:

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

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

  2. Перевод воркеров на новый ключ

    Задайте новый ключ в ANTHROPIC_ENVIRONMENT_KEY для каждого процесса, который выполняет опрос, и перезапустите его.

  3. Отзыв старого ключа

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

    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 -

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

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

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

  1. Остановка диспетчера и удаление песочниц

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

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

    kubectl -n cma delete sandboxes --all
  2. Ожидание удаления песочниц

    Повторяйте эту команду, пока песочницы, их поды и их тома не будут удалены:

    kubectl -n cma get sandboxes,pods,pvc
  3. Удаление чартов и пространств имён

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

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

Эта страница была полезной?