Claude Platform Docs
Managed Agentsセルフホスト型Managed Agents

Kubernetesにデプロイする

リリースアーカイブに含まれる2つのHelmチャートを使用して、セルフホスト型Claude Managed AgentsサーバーとそのサンドボックスをKubernetesクラスターにインストールし、サンドボックスPodで最初のセッションを実行します。

このページでは、空のGoogle Kubernetes Engine(GKE)クラスターから始めて、サンドボックスPodでツールを実行するセッションまでを進めます。リリースアーカイブに含まれる2つのHelmチャートを使用します。これらのチャートは、スタック全体をクラスター上で実行します。

  • cma-server: データベーススキーマを適用し、namespace cma-server内のServiceの背後で2つのサーバーを実行します。
  • cma-sandboxes: namespace cma内で、dispatcher(ディスパッチャー)とサンドボックスPodを実行します。dispatcherはサーバーに作業をポーリングし、各セッションに専用のサンドボックスPodを割り当てます。そのPodでは、ワーカーがエージェントのシェルツールとファイルツールを実行します。

PostgreSQLデータベースはどちらのチャートにも含まれず、外部に置かれたままです。別の種類のクラスターでも手順は同じですが、クラスターの前提条件といくつかのチャート値が異なります。その他のクラスターを参照してください。

前提条件

  • クラスター: 次のものを備えたKubernetes 1.30以降。
  • データベース: クラスターから到達可能なPostgreSQL 16以降。
  • レジストリ: クラスターがプルできるレジストリ。イメージはご自身でビルドします。
  • Claude APIキー: サーバーはモデル呼び出しにこれを使用します。別のプロバイダーを使用する場合は、推論プロバイダーを参照してください。
  • 権限: cluster-admin権限またはそれに相当する権限。インストールではnamespace、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

    次に、3つのイメージをビルドしてプッシュします。

    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を使用)。...をPG_PASSWORDの値に置き換えて、次のSQLを実行します。

    CREATE ROLE cma_server LOGIN PASSWORD '...';
    GRANT cma_server TO CURRENT_USER;
    CREATE DATABASE cma_server OWNER cma_server;
  3. サーバーのnamespaceとSecretを作成する

    サーバーのnamespaceとその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を削除してください。データベースのパスワードはcma-server-db Secretに保持されます。

  4. サンドボックスのnamespaceと証明書を作成する

    サンドボックスのnamespaceと、dispatcherが提供しサンドボックスが信頼する証明書を作成します。

    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が作成され、そのキーがnamespace cma内のSecret cma-environmentに保存されます。2番目のコマンドは、filled Secret cma/cma-environmentで始まる1行を出力します。最初の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をブロックします。クラスターにこれら4つの範囲外にあるPod、サービス、またはノードの範囲がある場合は、その範囲も列挙してください。

  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を他の2つのモードと比較するには、サンドボックスが到達できる範囲を参照してください。

    クラスターが次のいずれかのDNS構成を使用している場合は、ファイルに1行追加します。

    • Autopilotクラスターが使用するCloud DNS for GKE: 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

セッションを実行する

これらの手順では、新規インストールの名前を使用します。サーバーのvaluesファイルにearlierNames: trueがある場合は、代わりに使用する名前をKubernetes:オブジェクトの名前で確認してください。

  1. サーバーのポートを転送する

    1つ目のターミナルで、サーバーのポートを手元のマシンに転送します。

    kubectl -n cma-server port-forward svc/cma-server 8400:8400
  2. CLIをサーバーに向ける

    2つ目のターミナルで、ant CLIを転送先のポートに向け、cma-server-keys SecretからサーバーAPIキーを読み取ります。

    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. エージェントを作成してコマンドの実行を依頼する

    クイックスタートの最初のセッションを実行するのうち、エージェントを作成する、セッションを開始する、エージェントにコマンドの実行を依頼する、の3つのステップに従います。セッションを開始するステップでは、compose-sandboxを、チャートが作成する環境の名前であるdefaultに置き換えてください。

  4. サンドボックスPodを見つける

    エージェントは、コマンドを実行したPodのホスト名を返します。3つ目のターミナルでkubectl -n cma get podsを実行すると、dispatcherのPodの隣にその名前のPodが表示されます。デフォルトでは、このPodはエージェントのターンが終了してから約5分後に削除されます。一覧にない場合は、エージェントにもう一度hostnameを実行するよう依頼してください。

    チャットを終了するには、Ctrl+Cを押します。

サーバーの前段にTLSを配置する

サーバーはポート8400で平文のHTTPを使用し、アプリケーションからのリクエストにはサーバーAPIキーが含まれます。クラスター外のクライアントが接続する前に、cma-server Serviceの前段にTLSを終端するロードバランサーまたはingressを配置してください。これは次の要件を満たす必要があります。

  • リクエストパスを変更せずにそのまま渡す。
  • 最大32 MiBのリクエストボディを受け付ける。
  • レスポンスをバッファリングせずに渡す。
  • デフォルトの読み取りタイムアウトを2分に設定する。Gitリクエストについては、^/cma-[a-z]+/git/に一致するパスの読み取りタイムアウトを10分に設定してください。
  • 準備が整ったサーバーにのみトラフィックを送信する。cma-server Serviceはすでにこれを行っています。Podに直接到達するロードバランサーは、各Podで/cma-server/readyzをプローブし、503を返すPodをスキップする必要があります。
  • サーバーがすでに受け付けたPOSTを再送しない。
  • レスポンスをキャッシュしない。

クラスターの外から確認するには、curl -s https://<host>/cma-server/healthzを実行します。レスポンスは{"status":"ok"}です。

サンドボックスが到達できる範囲

cma-values.yamlでは、egress.mode: publicInternetにより、サンドボックスがパブリックインターネットに到達できます。

次の表で、他の2つのモードと比較します。

egress.modeサンドボックスが到達できる範囲
closed(デフォルト)サーバーとdispatcherのみ(DNSサーバーには到達できません)
publicInternetサーバー、dispatcher、DNSサーバー、およびパブリックインターネット
gatewayサーバー、dispatcher、および「egress gateway」(エグレスゲートウェイ)経由で指定したホスト。Kubernetesでゲートウェイを有効にするを参照してください。

その他のクラスター

cma-values.yamlのplatformを、Amazon EKSの場合はeksに、Azure Kubernetes Service(AKS)の場合はaksに、その他のクラスターの場合はgenericに設定します。3つすべてに、拡張機能を備えたアップストリームのAgent SandboxコントローラーとNetworkPolicyを適用するネットワークプラグインが必要です。さらに次のものも必要です。

  • Amazon EKS: gVisorのrunscがrunscという名前のcontainerdハンドラーとして登録されたノードグループ。ノードにはcma.anthropic.com/sandbox-node=trueのラベルを付け、cma.anthropic.com/sandbox-node=true:NoScheduleのtaintを付けます。チャートは、そのハンドラーに対してgvisor RuntimeClassを登録します。
  • AKS: Pod Sandboxingを備え、Amazon EKSと同じラベルとtaintが付いたノードプール。クラスターのネットワークポリシーエンジンの名前(cilium、calico、またはazure)をaks.networkPolicyに設定します。egress.mode: publicInternetはそのままにしてください。これは、AKSでチャートが受け付ける唯一のモードです。エージェントに実際の作業を行わせる前に、ご自身のクラスターでチャートをテストしてください。
  • その他のクラスター: gVisorまたは別のサンドボックス化されたランタイム用のRuntimeClass。その名前をruntimeClass.nameに設定します。

アーカイブ内のkubernetes/chart/examples/フォルダには、クラスターの種類ごとに完全なvaluesファイルが用意されています。

セッションのボリュームを解放する

チャートのデフォルトでは、各セッションには/workspace用の10 GiBのボリュームがあります。ボリュームはセッションのPodがなくなった後も残るため、セッションの次のメッセージではそのファイルを参照できます。

解放する対象実行すること
1つのセッションのボリュームターンが終了した後にセッションをアーカイブします。dispatcherは通常、約5分以内にボリュームを削除します。
誰もアーカイブしないセッションのボリュームcma-values.yamlでdispatcher.retentionDaysを設定します。これにより、dispatcherはセッションがその日数アイドル状態になった時点でボリュームを削除し、セッションの次のメッセージは空の/workspaceで開始されます。チャートのデフォルトである0では、すべてのボリュームが保持されます。

このセクションのコマンドはGKE用です。別のクラスターでは、sandboxesの代わりにsandboxclaimsを使用してください。

セッションを削除しても、そのボリュームは解放されません。最初にセッションをアーカイブしてください。kubectl -n cma get sandboxes -l anthropic.com/session-id=<session-id>で何も表示されなくなってから、セッションを削除してください。

アーカイブせずにセッションを削除した場合は、そのボリュームをご自身で解放してください。

  1. dispatcherのログでセッションのIDを見つけます。このコマンドは、削除されたと思われるのにボリュームが残っている各セッションについて1行を出力し、session_idの後にIDを示します。

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

    dispatcherはこれらの行を5分ごとに書き込みます。セッションが表示されない場合は、5分待ってからコマンドを再度実行してください。

  2. セッションが削除されていることを確認します。セッションを実行するのとおりにポートを転送し、ANTHROPIC_API_KEYを設定した状態で、ant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>を実行します。応答がSession not foundを伴う404 Not Foundである場合にのみ先に進んでください。コマンドがセッションを出力した場合は中止してください。そのセッションは削除されていません。

  3. ボリュームを所有するKubernetesオブジェクトを削除します。セッションのファイルも一緒に削除されます。

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

キーと証明書を更新する

環境キーの有効期間は365日、dispatcherの証明書の有効期間は825日です。それぞれ有効期限が切れる前に更新してください。

環境キーの有効期間の最後の30日間は、そのキーを使用する各リクエストで、サーバーが警告をログに記録します。この警告はenvironment key is within 30 days of expiryで始まります。

チャートが作成した環境キーを更新する

キーの有効期限を確認するには、kubectl -n cma describe secret cma-environmentを実行します。

キーの有効期間の最後の60日間に少なくとも1回、インストールされているリリースのアーカイブの最上位ディレクトリから次の2つのコマンドを実行します。

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コマンドは、実行されるたびに、キーの有効期限が60日以内であれば新しいキーをSecretに保存します。これ以外にキーを更新するものはありません。2つ目のコマンドは、dispatcherが新しいキーを読み込むように再起動します。

dispatcherの証明書を更新する

ステップ「サンドボックスのnamespaceと証明書を作成する」に戻ります。そのopensslコマンドとそれに続く2つのkubectlコマンドを再度実行します。その後、kubectl -n cma rollout restart deployment/cma-dispatcherでdispatcherを再起動します。

独自のワーカー用の環境キーを置き換える

チャートが更新するのは、チャート自身のキーのみです。環境とそのキーを作成するのようにキーをご自身で作成した場合は、管理CLIを使用して置き換えてください。CLIはリリースアーカイブの最上位にあります。

ANTHROPIC_API_KEYにサーバーAPIキーが設定されている、セッションを実行するの2つ目のターミナルでコマンドを実行します。1つ目のターミナルではポートフォワードを実行したままにしてください。別のアドレスでサーバーに接続している場合は、そのアドレスを-base-urlとして渡します。その場合、ポートフォワードは不要です。

  1. 同じ環境用の新しいキーを作成する

    -envには環境のIDを渡します。

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

    このコマンドは新しいキーを出力し、キーのIDと有効期限を標準エラーに出力します。

  2. ワーカーを新しいキーに移行する

    ポーリングを行う各プロセスで新しいキーをANTHROPIC_ENVIRONMENT_KEYとして設定し、再起動します。

  3. 古いキーを失効させる

    失効したキーをまだ使用しているワーカーは401エラーを受け取り、処理中のセッションを放棄します。古いキーのIDを確認するには、同じ-base-url、-env、-key-fileフラグを指定してlist-keysを実行します。古いキーを使用しているワーカーがなくなったら、その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 -

スタックをアンインストールする

最初にサンドボックスを削除してください。helm uninstallはサンドボックスを制限するネットワークポリシーを削除しますが、dispatcherがセッション用に作成したサンドボックスは実行され続けます。

これらの手順はデータベースには影響しませんが、Secretは削除されます。データベースを再び使用するには、保管しておいた暗号化キーのコピーが必要です。

  1. dispatcherを停止してサンドボックスを削除する

    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. サンドボックスがなくなるまで待つ

    サンドボックス、そのPod、およびそのボリュームがなくなるまで、このコマンドを繰り返し実行します。

    kubectl -n cma get sandboxes,pods,pvc
  3. チャートをアンインストールしてnamespaceを削除する

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

次のステップ

このページは役に立ちましたか?