すべてのプロダクト
Search
ドキュメントセンター

Container Compute Service:マルチテナンシー管理

最終更新日:Oct 14, 2026

複数のテナントが同じ Agent Sandbox クラスターを共有する場合、各テナントはチームを介して独立した Kubernetes 名前空間にマッピングされ、アクセス資格情報として独自の API キーを保持します。 管理者とテナントは、HTTP インターフェースを介して API キーを作成、クエリ、および失効させることができます。

概要

ack-sandbox-manager は、API キーとチームを管理するための E2B 互換の HTTP インターフェースセットを提供します。クラスター管理者とテナントは、これらのインターフェースを使用して、プログラムで API キーを作成し、チームをクエリし、未使用のキーを失効させることができます。

これらのインターフェースには、対応する E2B SDK や Kubernetes カスタムリソース定義 (CRD) はありません。HTTP 経由で直接呼び出す必要があります。

チーム

チームとは、API キーの認可境界です。Agent Sandbox では、チームは Kubernetes 名前空間に直接マッピングされる名前によって一意に識別されます。

  • 組み込みの admin チームはクラスターレベルであり、管理者によって管理されます。その admin API キーは、ack-sandbox-manager の起動時に初期化されます。

  • その他のチーム名は、既存の Kubernetes Namespace に対応する必要があります。テナントがチーム foo の API キーを作成する場合、Namespace foo が既に存在している必要があります。存在しない場合、リクエストはエラーを返します。

Namespace の一意性は、すでに十分な分離境界を提供しています。そのため、チームの一意の識別子 (UUID) は表示用のメタデータとしてのみ保持され、認証やリソース検索には使用されません。

API キー

API キーは、チームが保持する長期的なアクセス認証情報です。クライアントが ack-sandbox-manager のインターフェースを呼び出す際は、X-API-KEY リクエストヘッダーにキーを含める必要があります。API キーは次の内容を決定します:

  • 呼び出し元が所属するチーム。

  • 呼び出し元が通常テナントかクラスター管理者か、つまり呼び出し元が admin チームに所属しているか。

  • 呼び出し元がアクセスできる Sandbox の範囲。通常テナントは自身の API キーで作成した Sandbox のみにアクセスできますが、管理者はすべての Sandbox にアクセスできます。

認可モデル

役割

現在のチームのキーのリスト表示

チームのリスト表示

現在のチームのキーの作成

別のチームのキーの作成

現在のチームのキーの削除

admin API キーの削除

管理者 (admin チーム)

サポート

サポート (すべてのチーム)

サポート

サポート

サポート

サポート対象外 (拒否)

通常テナント

サポート

サポート (呼び出し元のチームのみ)

サポート

サポート対象外

サポート

サポート対象外

重要

組み込みの admin API キーは、いかなる状況でも削除できません。これにより、クラスターの管理性が保護されます。

前提条件

  • 対象のクラスターの アドオン管理 に移動し、ack-sandbox-manager がインストールされ、v0.6.0 以降にアップグレードされていることを確認します。その後、アドオンの 設定 ページで次の設定を構成します:

    • [E2B_API_KEY 認証を有効にするかどうか] を選択して、API キー認証を有効化します。

    • [adminApiKey] (管理者 API キー) を設定します。

エンドツーエンドの例

  1. kubectl を使用して ACK クラスターに接続します。

  2. JSON プロセッサー jq をインストールします。

  3. 次のスクリプトは、管理者がリソース環境とテナント認証情報を初期化してから、テナントがチームキーのライフサイクル全体を独立して管理するまでの、完全なエンドツーエンドのプロセスを示しています:

    #!/usr/bin/env bash
    set -euo pipefail
    
    ADMIN_KEY="${ADMIN_KEY:?required}"
    # 2 つのプロトコルがサポートされています。この例では、ネイティブ E2B プロトコルエンドポイントを使用します: https://api.your.domain.com
    # Agent Sandbox プライベートプロトコルを使用するには、BASE_URL を https://your.domain.com/kruise/api に置き換えます。
    BASE_URL="${BASE_URL:-https://api.your.domain.com}"
    TEAM_NAMESPACE="team-a"
    
    # 1. クラスター内で、管理者がチームの Namespace を作成します
    kubectl create ns "${TEAM_NAMESPACE}"
    
    # 2. 管理者が team-a のテナントキーを作成し、返されたプレーンテキストキーを記録します
    TENANT_KEY=$(curl -fsS -X POST \
      -H "X-API-KEY: ${ADMIN_KEY}" \
      -H "Content-Type: application/json" \
      -d "{\"name\":\"ci-runner\",\"teamName\":\"${TEAM_NAMESPACE}\"}" \
      "${BASE_URL}/api-keys" | jq -r '.key')
    
    # 3. テナントが自身のチームと既存のキーをリスト表示します
    curl -fsS -H "X-API-KEY: ${TENANT_KEY}" "${BASE_URL}/teams"
    curl -fsS -H "X-API-KEY: ${TENANT_KEY}" "${BASE_URL}/api-keys"
    
    # 4. テナントが teamName フィールドなしで、自身のチームのサブキーを作成します
    SUB_KEY_ID=$(curl -fsS -X POST \
      -H "X-API-KEY: ${TENANT_KEY}" \
      -H "Content-Type: application/json" \
      -d '{"name":"my-sub-key"}' \
      "${BASE_URL}/api-keys" | jq -r '.id')
    
    # 5. テナントが自身のチームのサブキーを削除します
    curl -fsS -X DELETE \
      -H "X-API-KEY: ${TENANT_KEY}" \
      "${BASE_URL}/api-keys/${SUB_KEY_ID}"

API リファレンス

チームのリスト表示

現在のユーザーに表示可能なチームを取得します。通常テナントは自身が所属するチームのみを表示でき、管理者はすべてのチームを表示できます。

リクエストの例:

curl -fsS \
  -H "X-API-KEY: ${E2B_API_KEY}" \
  "https://api.your.domain.com/teams"
import os
import requests

resp = requests.get(
    "https://api.your.domain.com/teams",
    headers={"X-API-KEY": os.environ["E2B_API_KEY"]},
    timeout=10,
)
try:
    resp.raise_for_status()
except requests.HTTPError:
    print(resp.text)
    raise
print(resp.json())

想定される出力:

[
  {
    "teamID": "550e8400-e29b-41d4-a716-446655449999",
    "name": "admin",
    "apiKey": "",
    "isDefault": true
  }
]

レスポンスボディは JSON 配列です。次の表は、各項目のフィールドを説明しています:

フィールド

タイプ

説明

teamID

string

チームの UUID。表示のみに使用されます。

name

string

チーム名。Kubernetes Namespace と同じです。

apiKey

string

このフィールドは常に空の文字列を返します。E2B SDK スキーマとの互換性のためにのみ保持されています。プレーンテキストキーを取得するには、POST /api-keys を使用してキーを作成し、返された値を直ちに保存してください。

isDefault

boolean

これが呼び出し元のデフォルトチームかどうか。

API キーのリスト表示

現在の呼び出し元のチームに属するすべての API キーを取得します。

リクエストの例:

curl -fsS \
  -H "X-API-KEY: ${E2B_API_KEY}" \
  "https://api.your.domain.com/api-keys"
import os
import requests

resp = requests.get(
    "https://api.your.domain.com/api-keys",
    headers={"X-API-KEY": os.environ["E2B_API_KEY"]},
    timeout=10,
)
try:
    resp.raise_for_status()
except requests.HTTPError:
    print(resp.text)
    raise
for key in resp.json():
    print(key["id"], key["name"], key["mask"])

レスポンスフィールド:

フィールド

タイプ

説明

id

string

API キーの UUID。キーを削除する際に使用されます。

name

string

API キーの人間が判読可能な名前。

createdAt

string

API キーが作成された時刻。

createdBy.id

string

API キーを作成した呼び出し元の UUID。

lastUsed

string

API キーが最後に使用された時刻。キーが一度も使用されていない場合、値は null です。

API キーの作成

新しい API キーを作成します。レスポンスボディの key フィールドには、新しく生成されたプレーンテキストキーが含まれます。プレーンテキスト key フィールドは、キーの作成時に一度だけ返され、その後はどのインターフェースを通じても取得できません。直ちに保存してください。

説明

例を実行する前に、team-a Namespace が既に存在することを確認してください。呼び出し元が通常テナントの場合は、リクエストボディから teamName フィールドを削除してください。

リクエストの例:

curl -fsS -X POST \
  -H "X-API-KEY: ${E2B_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"name": "ci-runner", "teamName": "team-a"}' \
  "https://api.your.domain.com/api-keys"
import os
import requests

resp = requests.post(
    "https://api.your.domain.com/api-keys",
    headers={
        "X-API-KEY": os.environ["E2B_API_KEY"],
        "Content-Type": "application/json",
    },
    json={"name": "ci-runner", "teamName": "team-a"},
    timeout=10,
)
try:
    resp.raise_for_status()
except requests.HTTPError:
    print(resp.text)
    raise
created = resp.json()
# created["key"] を直ちに永続化してください。再度取得することはできません。
print(created["id"], created["key"])

リクエストボディのフィールド:

フィールド

タイプ

必須

説明

name

string

はい

API キーの人間が判読可能な名前。

teamName

string

いいえ

対象チームの名前。デフォルトは呼び出し元自身のチームです。管理者のみが別のチームを指定でき、そのチームは既存の Kubernetes Namespace に対応している必要があります。通常テナントは、このフィールドを省略する必要があります。

レスポンスフィールド:

フィールド

タイプ

説明

id

string

新しい API キーの UUID。後で削除する際に使用されます。

key

string

プレーンテキストキー。一度だけ返されるため、直ちに保存する必要があります。

name

string

API キー名。リクエストボディの値と同じです。

team.id

string

API キーを実際に所有するチームの UUID。

team.name

string

API キーを実際に所有するチームの名前、つまり対応する Kubernetes Namespace です。これは呼び出し元の意図を確認するために使用されます。

API キーの削除

UUID で指定された API キーを削除します。通常テナントは、現在のチームのキーのみを削除できます。管理者は、admin API キーを除く任意のキーを削除できます。組み込みの admin API キーを削除しようとすると、403 Forbidden が返されます。

リクエストの例:

API_KEY_ID="<uuid-from-list-api-keys>"
curl -fsS -X DELETE \
  -H "X-API-KEY: ${E2B_API_KEY}" \
  "https://api.your.domain.com/api-keys/${API_KEY_ID}"
import os
import requests

api_key_id = "<uuid-from-list-api-keys>"
resp = requests.delete(
    f"https://api.your.domain.com/api-keys/{api_key_id}",
    headers={"X-API-KEY": os.environ["E2B_API_KEY"]},
    timeout=10,
)
# 成功したリクエストは 204 No Content を返します。
try:
    resp.raise_for_status()
except requests.HTTPError:
    print(resp.text)
    raise
無効な UUID と存在しない UUID はどちらも 404 Not Found を返します。インターフェースはこれら 2 つのケースを区別しません。

エラーコード

HTTP ステータスコード

シナリオ

400

リクエストボディが無効 (JSON 解析に失敗)、または対象の Namespace が存在しません。

401

X-API-KEY リクエストヘッダーが欠落している、または API キーが無効です。

403

管理者以外のユーザーが別のチームに対して書き込み操作を実行しようとした、または admin API キーを削除しようとしました。

404

指定された UUID の API キーが存在しない、またはパスパラメーターが有効な UUID 文字列ではありません。

500

内部サーバーエラーが発生します。たとえば、必須フィールドが欠落している、Kubernetes API が利用できない、または永続ストレージに到達できない場合などです。

エラーレスポンスボディは JSON であり、問題の特定に役立つ code、message、request_id フィールドが含まれています:

{
  "code": 403,
  "message": "You are not allowed to create an API key for another team",
  "request_id": "c42c84d8-8420-4194-b48d-5bc5c8fe4ed6"
}