---
title: Kubernetesにデプロイする
url: https://platform.claude.com/docs/ja/managed-agents/self-hosted/kubernetes
description: リリースアーカイブに含まれる2つのHelmチャートを使用して、セルフホスト型Claude Managed AgentsサーバーとそのサンドボックスをKubernetesクラスターにインストールし、サンドボックスPodで最初のセッションを実行します。
---

<Note>
  セルフホスト型Claude Managed Agentsへのアクセスをリクエストするには、Anthropicのアカウントチームにお問い合わせください。
</Note>

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

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

PostgreSQLデータベースはどちらのチャートにも含まれず、外部に置かれたままです。別の種類のクラスターでも手順は同じですが、クラスターの前提条件といくつかのチャート値が異なります。[その他のクラスター](https://platform.claude.com/docs/ja/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/ja/managed-agents/self-hosted/inference-provider)を参照してください。

* **権限：** cluster-admin権限またはそれに相当する権限。インストールではnamespace、Role、ClusterRoleBindingが作成されます。

* **手元のマシンのツール：** `helm`、`kubectl`、`docker buildx`、`openssl`、および[`ant` CLI](https://platform.claude.com/docs/ja/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
    ```

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

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

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

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

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

    ```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`が作成され、そのキーがnamespace `cma`内のSecret `cma-environment`に保存されます。2番目のコマンドは、`filled Secret cma/cma-environment`で始まる1行を出力します。最初の`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`をブロックします。クラスターにこれら4つの範囲外にあるPod、サービス、またはノードの範囲がある場合は、その範囲も列挙してください。
  </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`を他の2つのモードと比較するには、[サンドボックスが到達できる範囲](https://platform.claude.com/docs/ja/managed-agents/self-hosted/kubernetes#what-sandboxes-can-reach)を参照してください。

    クラスターが次のいずれかの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}'`を実行します。

    次に、チャートをインストールします。

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

## セッションを実行する

これらの手順では、新規インストールの名前を使用します。サーバーのvaluesファイルに`earlierNames: true`がある場合は、代わりに使用する名前を[Kubernetes：オブジェクトの名前](https://platform.claude.com/docs/ja/managed-agents/self-hosted/upgrade#object-names)で確認してください。

<Steps>
  <Step title="サーバーのポートを転送する">
    1つ目のターミナルで、サーバーのポートを手元のマシンに転送します。

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

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

    ```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/ja/managed-agents/self-hosted/quickstart#run-your-first-session)のうち、エージェントを作成する、セッションを開始する、エージェントにコマンドの実行を依頼する、の3つのステップに従います。セッションを開始するステップでは、`compose-sandbox`を、チャートが作成する環境の名前である`default`に置き換えてください。
  </Step>

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

    チャットを終了するには、Ctrl+Cを押します。
  </Step>
</Steps>

## サーバーの前段に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でゲートウェイを有効にする](https://platform.claude.com/docs/ja/managed-agents/self-hosted/agent-identity#turn-on-the-gateway-on-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を示します。

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

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

2. セッションが削除されていることを確認します。[セッションを実行する](https://platform.claude.com/docs/ja/managed-agents/self-hosted/kubernetes#run-a-session)のとおりにポートを転送し、`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オブジェクトを削除します。セッションのファイルも一緒に削除されます。

   ```bash
   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つのコマンドを実行します。

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

### dispatcherの証明書を更新する

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

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

チャートが更新するのは、チャート自身のキーのみです。[環境とそのキーを作成する](https://platform.claude.com/docs/ja/managed-agents/self-hosted/call-the-api#create-an-environment-and-its-key)のようにキーをご自身で作成した場合は、管理CLIを使用して置き換えてください。CLIはリリースアーカイブの最上位にあります。

`ANTHROPIC_API_KEY`にサーバーAPIキーが設定されている、[セッションを実行する](https://platform.claude.com/docs/ja/managed-agents/self-hosted/kubernetes#run-a-session)の2つ目のターミナルでコマンドを実行します。1つ目のターミナルではポートフォワードを実行したままにしてください。別のアドレスでサーバーに接続している場合は、そのアドレスを`-base-url`として渡します。その場合、ポートフォワードは不要です。

<Steps>
  <Step title="同じ環境用の新しいキーを作成する">
    `-env`には環境のIDを渡します。

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

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

  <Step title="ワーカーを新しいキーに移行する">
    ポーリングを行う各プロセスで新しいキーを`ANTHROPIC_ENVIRONMENT_KEY`として設定し、再起動します。
  </Step>

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

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

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

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

<Steps>
  <Step title="dispatcherを停止してサンドボックスを削除する">
    ```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="サンドボックスがなくなるまで待つ">
    サンドボックス、そのPod、およびそのボリュームがなくなるまで、このコマンドを繰り返し実行します。

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

  <Step title="チャートをアンインストールしてnamespaceを削除する">
    ```bash
    helm uninstall cma --namespace cma
    helm uninstall cma-server --namespace cma-server
    kubectl delete namespace cma cma-server
    ```
  </Step>
</Steps>

## 次のステップ

* **アップグレードする：** [セルフホスト型Claude Managed Agentsをアップグレードする](https://platform.claude.com/docs/ja/managed-agents/self-hosted/upgrade)に`helm upgrade`コマンドが記載されています。
* **その他のチャート値を変更する：** サーバーについては`kubernetes/server/chart/values.yaml`、サンドボックスについては`kubernetes/chart/values.yaml`のコメントを参照してください。
* **コードからAPIを呼び出す：** [セルフホスト型サーバーでAPIを呼び出す](https://platform.claude.com/docs/ja/managed-agents/self-hosted/call-the-api)を参照してください。
* **ブラウザで作業する：** [サーバー上でコンソールを使用する](https://platform.claude.com/docs/ja/managed-agents/self-hosted/console)を参照してください。
