Agent Sandbox で AI コードの実行を分離する

このドキュメントでは、Google Kubernetes Engine(GKE)クラスタに開発環境をデプロイし、Agent Sandbox Python クライアントを使用する手順について説明します。

Agent Sandbox 機能が信頼できない AI 生成コードを分離する方法の概要については、GKE Agent Sandbox についてをご覧ください。

費用

Agent Sandbox は、GKE で追加料金なしで利用できます。作成したリソースには GKE の料金が適用されます。

始める前に

  1. Google Cloud コンソールのプロジェクト セレクタページで、 Google Cloud プロジェクトを選択または作成します。

    プロジェクトの選択または作成に必要なロール

    • プロジェクトを選択する: プロジェクトの選択に特定の IAM ロールは必要ありません。ロールが付与されているプロジェクトであれば、どのプロジェクトでも選択できます。
    • プロジェクトを作成する: プロジェクトを作成するには、resourcemanager.projects.create 権限を含むプロジェクト作成者ロール(roles/resourcemanager.projectCreator)が必要です。詳しくは、ロールを付与する方法をご覧ください。

    プロジェクト セレクタに移動

  2. Google Cloud プロジェクトに対して課金が有効になっていることを確認します

  3. Artifact Registry API と Kubernetes Engine API を有効にします。

    API を有効にするために必要なロール

    API を有効にするには、serviceusage.services.enable 権限を含む Service Usage 管理者 IAM ロール(roles/serviceusage.serviceUsageAdmin)が必要です。詳しくは、ロールを付与する方法をご覧ください。

    API を有効にする

  4. Google Cloud コンソールで Cloud Shell をアクティブにします。

    Cloud Shell をアクティブにする

  5. このガイドを完了するために必要な権限があることを確認します
  6. Agent Sandbox 機能が有効になっている GKE クラスタが必要です。ない場合は、GKE でエージェント Sandbox を有効にするの手順に沿って、新しいクラスタを作成するか、既存のクラスタを更新します。

必要なロール

サンドボックスの作成と管理に必要な権限を取得するには、プロジェクトに対する Kubernetes Engine 管理者 roles/container.admin)IAM ロールを付与するよう管理者に依頼してください。ロールの付与については、プロジェクト、フォルダ、組織に対するアクセス権の管理をご覧ください。

必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

環境変数を定義する

このドキュメントで実行するコマンドを簡略化するために、Cloud Shell で環境変数を設定できます。Cloud Shell で、次のコマンドを実行して環境変数を定義します。

export PROJECT_ID=$(gcloud config get project)
export CLUSTER_NAME="agent-sandbox-cluster"
export LOCATION="us-central1"
export NODE_POOL_NAME="agent-sandbox-node-pool"
export MACHINE_TYPE="e2-standard-2"

これらの環境変数の説明は次のとおりです。

  • PROJECT_ID: 現在の Google Cloud プロジェクトの ID。この変数を定義すると、GKE クラスタなどのすべてのリソースが正しいプロジェクトに作成されます。
  • CLUSTER_NAME: GKE クラスタの名前(例: agent-sandbox-cluster)。
  • LOCATION: GKE クラスタが配置されている Google Cloud リージョンまたはゾーン。Autopilot クラスタを使用している場合はリージョン(us-central1 など)、Standard クラスタを使用している場合はゾーン(us-central1-a など)に設定します。
  • NODE_POOL_NAME: サンドボックス化されたワークロードを実行するノードプールの名前(例: agent-sandbox-node-pool)。
  • MACHINE_TYPE: ノードプール内のノードのマシンタイプ(e2-standard-2 など)。さまざまなマシンシリーズとさまざまなオプションの選択の詳細については、マシン ファミリーのリソースと比較ガイドをご覧ください。

サンドボックス環境をデプロイする

このセクションでは、サンドボックス ブループリント(SandboxTemplate)を作成し、必要なネットワーキング ルーターをデプロイして、サンドボックスの操作に使用する Python クライアントをインストールする方法について説明します。

サンドボックスを作成して操作するには、Agentic Sandbox Python クライアントを使用することをおすすめします。このクライアントは、サンドボックスの作成からクリーンアップまでのライフサイクル全体を簡素化するインターフェースを提供します。これは、サンドボックスの作成、使用、削除をプログラムで行うために使用できる Python ライブラリです。

クライアントは、すべてのトラフィックの中央エントリ ポイントとしてサンドボックス ルーターを使用します。このドキュメントで説明する例では、クライアントは kubectl port-forward コマンドを使用してこのルーターへのトンネルを作成するため、パブリック IP アドレスを公開する必要はありません。kubectl port-forward の使用は安全なソリューションではなく、開発環境での使用に限定する必要があります。

SandboxTemplateSandboxWarmPool を作成する

SandboxTemplate リソースと SandboxWarmPool リソースを作成して、サンドボックスの構成を定義します。SandboxTemplate は、Agent Sandbox コントローラが使用して、一貫性のある事前構成済みのサンドボックス環境を作成する再利用可能なブループリントとして機能します。SandboxWarmPool リソースは、指定された数の事前にウォームアップされた Pod が常に実行され、要求される準備ができていることを保証します。事前にウォームアップされたサンドボックスは、すでに初期化されている実行中の Pod です。この事前初期化により、新しいサンドボックスを 1 秒以内に作成できるようになり、通常のサンドボックスの起動時のレイテンシを回避できます。

  1. Cloud Shell で、次の内容を含むファイルを sandbox-template-and-pool.yaml という名前で作成します。

    apiVersion: extensions.agents.x-k8s.io/v1alpha1
    kind: SandboxTemplate
    metadata:
      name: python-runtime-template
      namespace: default
    spec:
      podTemplate:
        metadata:
          labels:
            sandbox: python-sandbox-example
        spec:
          runtimeClassName: gvisor
          automountServiceAccountToken: false # Required
          securityContext:
            runAsNonRoot: true # Required
          nodeSelector:
            sandbox.gke.io/runtime: gvisor # Required
          tolerations:
          - key: "sandbox.gke.io/runtime"
            value: "gvisor"
            effect: "NoSchedule" # Required
          containers:
          - name: python-runtime
            image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0
            ports:
            - containerPort: 8888
            readinessProbe:
              httpGet:
                path: "/"
                port: 8888
              initialDelaySeconds: 0
              periodSeconds: 1
            resources:
              requests:
                cpu: "250m"
                memory: "512Mi"
              limits:
                cpu: "500m"
                memory: "1Gi" # Required
            securityContext:
              capabilities:
                drop: ["ALL"] # Required
          restartPolicy: "OnFailure"
    ---
    apiVersion: extensions.agents.x-k8s.io/v1alpha1
    kind: SandboxWarmPool
    metadata:
      name: python-sandbox-warmpool
      namespace: default
    spec:
      replicas: 2
      sandboxTemplateRef:
        name: python-runtime-template
    
  2. SandboxTemplate マニフェストと SandboxWarmPool マニフェストを適用します。

    kubectl apply -f sandbox-template-and-pool.yaml
    

サンドボックス ルーターをデプロイする

サンドボックス環境の作成と操作に使用する Python クライアントは、サンドボックス ルーターと呼ばれるコンポーネントを使用してサンドボックスと通信します。

この例では、テストにクライアントのデベロッパー モードを使用します。このモードはローカル開発を目的としており、kubectl port-forward コマンドを使用して、ローカルマシンから、クラスタで実行されているサンドボックス ルーター サービスへの直接トンネルを確立します。このトンネリング アプローチでは、パブリック IP アドレスや複雑な上り(内向き)設定が不要になり、ローカル環境からのサンドボックスの操作が簡素化されます。

サンドボックス ルーターをデプロイする手順は次のとおりです。

  1. Cloud Shell で、次の内容を含むファイルを sandbox-router.yaml という名前で作成します。

    # A ClusterIP Service to provide a stable endpoint for the router pods.
    apiVersion: v1
    kind: Service
    metadata:
      name: sandbox-router-svc
      namespace: default
    spec:
      type: ClusterIP
      selector:
        app: sandbox-router
      ports:
      - name: http
        protocol: TCP
        port: 8080 # The port the service will listen on
        targetPort: 8080 # The port the router container listens on (from the sandbox_router/Dockerfile)
    ---
    # The Deployment to manage and run the router pods.
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sandbox-router-deployment
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sandbox-router
      template:
        metadata:
          labels:
            app: sandbox-router
        spec:
          # Ensure pods are spread across different zones for HA
          topologySpreadConstraints:
            - maxSkew: 1
              topologyKey: topology.kubernetes.io/zone
              whenUnsatisfiable: ScheduleAnyway
              labelSelector:
                matchLabels:
                  app: sandbox-router
          containers:
          - name: router
            image: us-central1-docker.pkg.dev/k8s-staging-images/agent-sandbox/sandbox-router:latest-main
            ports:
            - containerPort: 8080
            readinessProbe:
              httpGet:
                path: /healthz
                port: 8080
              initialDelaySeconds: 5
              periodSeconds: 5
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8080
              initialDelaySeconds: 10
              periodSeconds: 10
            resources:
              requests:
                cpu: "100m"
                memory: "512Mi"
              limits:
                cpu: "1000m"
                memory: "1Gi"
          securityContext:
            runAsUser: 1000
            runAsGroup: 1000
    
  2. マニフェストを適用して、ルーターをクラスタにデプロイします。

    kubectl apply -f sandbox-router.yaml
    
  3. Sandbox Router のデプロイが正しく実行されていることを確認します。

    kubectl get deployment sandbox-router-deployment
    

    デプロイの READY 列に 2/2 または 1/1 が表示されるまで待ちます。

Python クライアントをインストールする

サンドボックス ルーターなどのクラスタ内コンポーネントがデプロイされたので、最後の準備手順として、ローカルマシンに Agentic Sandbox Python クライアントをインストールします。このクライアントは、サンドボックスをプログラムで作成、使用、削除できる Python ライブラリです。次のセクションで、環境のテストに使用します。

  1. Python 仮想環境を作成してアクティブにします。

    python3 -m venv .venv
    source .venv/bin/activate
    
  2. クライアント パッケージをインストールします。

    pip install k8s-agent-sandbox
    

サンドボックスをテストする

すべての設定コンポーネントが整ったので、Agentic Sandbox Python クライアントを使用してサンドボックスを作成し、操作できるようになりました。

  1. agent-sandbox ディレクトリに、次の内容の Python スクリプトを test_sandbox.py という名前で作成します。

    from k8s_agent_sandbox import SandboxClient
    from k8s_agent_sandbox.models import SandboxLocalTunnelConnectionConfig
    
    # Automatically tunnels to svc/sandbox-router-svc
    client = SandboxClient(
        connection_config=SandboxLocalTunnelConnectionConfig()
    )
    
    sandbox = client.create_sandbox(template="python-runtime-template", namespace="default")
    try:
        print(sandbox.commands.run("echo 'Hello from the sandboxed environment!'").stdout)
    except Exception as e:
        print(f"An error occurred: {e}")
    
  2. ターミナルから(仮想環境がアクティブな状態で)、テスト スクリプトを実行します。

    python3 test_sandbox.py
    

サンドボックスから出力される「Hello from the sandboxed environment!」というメッセージが表示されます。

これで完了です。安全なサンドボックス内でシェルコマンドが正常に実行されました。sandbox.run() メソッドを使用すると、任意のシェルコマンドを実行できます。Agent Sandbox は、クラスタのノードや他のワークロードを信頼できないコードから保護する安全なバリア内でコマンドを実行します。これにより、AI エージェントや自動化されたワークフローがタスクを実行するための安全で信頼性の高い方法が提供されます。

スクリプトの実行時に、SandboxClient によってすべての手順が処理されます。SandboxClaim リソースを作成してサンドボックスを起動し、サンドボックスの準備が整うまで待機してから、sandbox.run() メソッドを使用して安全なコンテナ内で bash シェルコマンドを実行します。クライアントは、そのコマンドから stdout をキャプチャして出力します。サンドボックスは、プログラムの実行後に自動的に削除されます。

SandboxClaim リソースが作成されると、使用可能な Pod がウォームプールから Sandbox オブジェクトに割り当てられ、クレームが準備完了とマークされます。その後、SandboxWarmPool は構成されたレプリカ数を維持するために自動的に補充されます。

特定のサンドボックスが要求されているか、使用可能かどうかを確認するには、サンドボックス Pod のメタデータの ownerReferences を確認します。kind フィールドの値が Sandbox の場合、Pod は使用中です。kind フィールドの値が SandboxWarmPool の場合、Pod はアイドル状態で、要求されるのを待っています。

本番環境でサンドボックスを実行する

このドキュメントでは、Cloud Shell を使用してクラスタの外部からサンドボックスを操作します。Python クライアントは、ユーザー認証情報を使用してクラスタに対する認証を行い、サンドボックス リソースを管理します。また、kubectl port-forward コマンドを使用してサンドボックスとの接続を確立します。これらの手順は、開発シナリオに適しています。

本番環境のシナリオでは、コントローラ アプリケーション(AI オーケストレータなど)がサンドボックス リソースの作成と管理を行います。本番環境でエージェント サンドボックスを使用するには、次の点を考慮してください。

  • 認証: コントローラ アプリケーションは、サンドボックスを実行するためにクラスタ API サーバーに対して認証する必要があります。認証の構成方法は、コントローラ アプリケーションの実行場所によって異なります。

    • コントローラ アプリケーションが同じクラスタ内の Pod として実行されている場合は、Kubernetes RBAC または Workload Identity Federation for GKE と IAM ポリシーを使用して、Pod の Kubernetes ServiceAccount にサンドボックスのモニタリングやネットワーク エンドポイントの検出に必要な権限を付与します。
    • コントローラ アプリケーションがクラスタの外部で実行されている場合は、Workload Identity 連携または IAM サービス アカウントを使用して、許可ポリシーで参照できる ID をアプリケーションに付与します。
  • ルーティング: コントローラ アプリケーションの Python クライアントからのリクエストは、クラスタ内のサンドボックス ルーターに到達する必要があります。本番環境では、次のいずれかの方法でネットワーク接続を確立します。

    • コントローラ アプリケーションが同じクラスタで実行されている場合は、SandboxDirectConnectionConfig 関数を使用して、Sandbox Router サービスが使用する URL とポートをターゲットにします。
    • コントローラ アプリケーションがクラスタの外部で実行されている場合は、GKE Gateway API を使用して内部ロードバランサまたは外部ロードバランサを作成します。クライアント コードで、SandboxGatewayConnectionConfig 関数を使用して Gateway を参照します。

    これらのルーティング方法の詳細については、GitHub の使用例ルーターのゲートウェイ デプロイ手順をご覧ください。

  • Google Cloud リソースへのサンドボックス アクセス: サンドボックス コードが Cloud Storage などの Google Cloud API にリクエストを送信する必要がある場合は、Workload Identity Federation for GKE を使用して IAM ポリシーを作成し、サンドボックス Pod が使用する Kubernetes ServiceAccount に、そのアクセスに必要な権限を付与します。

リソースのクリーンアップ

Google Cloud アカウントに課金されないようにするには、作成した GKE クラスタを削除する必要があります。

gcloud container clusters delete $CLUSTER_NAME --location=$LOCATION --quiet

次のステップ