GKE で Agent Sandbox を有効にする

このドキュメントでは、Google Kubernetes Engine(GKE)クラスタでエージェント サンドボックス機能を有効にする方法について説明します。また、信頼できないコードを安全に実行するためのサンドボックス環境をクラスタに作成する方法についても説明します。

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

費用

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

不要な料金が発生しないように、このドキュメントの完了後に GKE を無効にするか、プロジェクトを削除してください。

始める前に

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

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

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

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

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

  3. Artifact Registry API と Google Kubernetes Engine API を有効にします(有効になっていない場合)。

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

    API を有効にするには、serviceusage.services.enable 権限が必要です。プロジェクトを作成した場合は、オーナーロール(roles/owner)を通じてこの権限がすでに付与されている可能性があります。それ以外の場合は、Service Usage 管理者ロール(roles/serviceusage.serviceUsageAdmin)を通じてこの権限を取得できます。ロールを付与する方法を確認する。

    API を有効にする

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

    Cloud Shell をアクティブにする

  5. クラスタが GKE バージョン 1.36.3-gke.1767000 以降(v1beta1 API をサポート)を実行していることを確認します。

環境変数を定義する

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

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

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

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

Agent Sandbox を有効にする

エージェント サンドボックス機能は、新しいクラスタを作成するとき、または既存のクラスタを更新するときに有効にできます。

新しい GKE クラスタを作成するときに Agent Sandbox を有効にする

フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用することをおすすめします。ワークロードに最適な GKE の運用モードを選択するには、GKE の運用モードを選択するをご覧ください。

Autopilot

Agent Sandbox を有効にして新しい GKE Autopilot クラスタを作成するには、--enable-agent-sandbox フラグを含めます。

gcloud beta container clusters create-auto ${CLUSTER_NAME} \
    --location=${LOCATION} \
    --cluster-version=${CLUSTER_VERSION} \
    --enable-agent-sandbox

Autopilot クラスタの場合は、LOCATION 環境変数がリージョン(us-central1 など)に設定されていることを確認します。

標準

Agent Sandbox を有効にして新しい GKE Standard クラスタを作成するには、クラスタを作成し、gVisor を有効にしてノードプールを追加してから、Agent Sandbox 機能を有効にする必要があります。費用を抑えるには、プールごとに 1 つのノードを持つゾーンクラスタを作成することをおすすめします。

  1. クラスタを作成します。

    gcloud beta container clusters create ${CLUSTER_NAME} \
        --location=${LOCATION} \
        --num-nodes=1 \
        --cluster-version=${CLUSTER_VERSION}
    

    この Standard クラスタでは、LOCATION 環境変数がゾーン(us-central1-a など)に設定されていることを確認します。

  2. gVisor を有効にして、独立したノードプールを作成します。

    gcloud container node-pools create ${NODE_POOL_NAME} \
        --cluster=${CLUSTER_NAME} \
        --machine-type=${MACHINE_TYPE} \
        --location=${LOCATION} \
        --num-nodes=1 \
        --image-type=cos_containerd \
        --sandbox=type=gvisor
    

    LOCATION は、クラスタの作成時に使用したゾーンと同じである必要があります。

  3. クラスタを更新して Agent Sandbox 機能を有効にします。

    gcloud beta container clusters update ${CLUSTER_NAME} \
        --location=${LOCATION} \
        --enable-agent-sandbox
    

既存の GKE クラスタを更新するときにエージェント サンドボックスを有効にする

既存のクラスタでエージェント サンドボックスを有効にするには、クラスタで v1beta1 API をサポートするバージョン 1.36.3-gke.1767000 以降を実行している必要があります。

LOCATION 環境変数が、既存のクラスタが配置されているリージョンまたはゾーンに設定されていることを確認します。

  1. GKE Standard クラスタを使用している場合、Agent Sandbox は gVisor に依存します。Standard クラスタに gVisor 対応のノードプールがない場合は、まず作成する必要があります。

    gcloud container node-pools create ${NODE_POOL_NAME} \
        --cluster=${CLUSTER_NAME} \
        --machine-type=${MACHINE_TYPE} \
        --location=${LOCATION} \
        --image-type=cos_containerd \
        --sandbox=type=gvisor
    
  2. クラスタを更新して Agent Sandbox 機能を有効にします。

    gcloud beta container clusters update ${CLUSTER_NAME} \
        --location=${LOCATION} \
        --enable-agent-sandbox
    

構成を確認する

Agent Sandbox 機能が有効になっているかどうかを確認するには、クラスタの説明を調べます。

gcloud beta container clusters describe ${CLUSTER_NAME} \
    --location=${LOCATION} \
    --format="value(addonsConfig.agentSandboxConfig.enabled)"

Autopilot クラスタを作成した場合は、ロケーションはリージョン(us-central1 など)です。Standard クラスタを作成した場合は、ロケーションはゾーン(us-central1-a など)です。

機能が正常に有効になると、コマンドは True を返します。

Agent Sandbox のデプロイ要件

Sandbox や SandboxTemplate などのワークロードを正常にデプロイするには、YAML マニフェストに特定のセキュリティ設定と構成設定を含める必要があります。GKE は、検証用アドミッション ポリシー(VAP)を使用してこれらの要件を適用します。これらの要件が満たされていない場合、アドミッション コントローラはデプロイを拒否します。

必要な構成

デプロイ マニフェストには、次の設定を含める必要があります。

  • runtimeClassName: gvisor: Pod が gVisor Sandbox で実行されるようにします。
  • automountServiceAccountToken: false: Pod がデフォルトのサービス アカウント トークンを自動的にマウントしないようにします。
  • securityContext.runAsNonRoot: true: コンテナが root ユーザーとして実行されないようにします。
  • securityContext.capabilities.drop: ["ALL"]: コンテナからすべての Linux ケーパビリティを削除します。
  • resources.limits: サービス拒否(DoS)のシナリオを回避するために、CPU とメモリの上限を指定する必要があります。
  • nodeSelector: sandbox.gke.io/runtime: gvisor をターゲットにする必要があります。
  • tolerations: sandbox.gke.io/runtime=gvisor:NoSchedule taint の toleration を含める必要があります。

禁止されている構成

デプロイ マニフェストに次のものを含めてはなりません。

  • hostNetwork: true、hostPID: true、または hostIPC: true。
  • コンテナ セキュリティ コンテキストの privileged: true。
  • HostPath 巻。
  • 機能を追加しました(capabilities.add)。
  • hostPort の設定。
  • カスタム sysctl。
  • サービス アカウント トークンまたは証明書の予測ボリューム。

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

SandboxTemplate を定義し、SandboxWarmPool を使用して事前ウォームアップされたインスタンスを準備しておくことで、サンドボックス環境をデプロイすることをおすすめします。SandboxClaim を使用して、このウォーム ノードプールからインスタンスをリクエストできます。または、サンドボックスを直接作成することもできますが、この方法ではウォームプールはサポートされません。

SandboxTemplate、SandboxWarmPool、SandboxClaim、Sandbox は Kubernetes カスタム リソースです。

SandboxTemplate は、再利用可能なブループリントとして機能します。SandboxWarmPool は、指定された数の事前にウォームアップされた Pod が常に実行され、要求される準備ができていることを保証します。このカスタム リソースを使用すると、起動レイテンシを最小限に抑えることができます。

SandboxTemplate と SandboxWarmPool を作成してサンドボックス環境をデプロイする手順は次のとおりです。

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

    apiVersion: extensions.agents.x-k8s.io/v1beta1
    kind: SandboxTemplate
    metadata:
      name: python-runtime-template
      namespace: default
    spec:
      podTemplate:
        metadata:
          labels:
            sandbox-type: python-runtime
        spec:
          runtimeClassName: gvisor # Required
          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: runtime
            image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0
            ports:
            - containerPort: 8888
            resources:
              requests:
                cpu: "250m"
                memory: "512Mi"
              limits:
                cpu: "500m"
                memory: "1Gi" # Required
            securityContext:
              capabilities:
                drop: ["ALL"] # Required
          restartPolicy: OnFailure
    
  2. SandboxTemplate マニフェストを適用します。

    kubectl apply -f sandbox-template.yaml
    
  3. 次の内容で sandbox-warmpool.yaml という名前のファイルを作成します。

    apiVersion: extensions.agents.x-k8s.io/v1beta1
    kind: SandboxWarmPool
    metadata:
      name: python-runtime-warmpool
      namespace: default
      labels:
        app: python-runtime-warmpool
    spec:
      replicas: 2
      sandboxTemplateRef:
        # This must match the name of the SandboxTemplate.
        name: python-runtime-template
    
  4. SandboxWarmPool マニフェストを適用します。

    kubectl apply -f sandbox-warmpool.yaml
    

SandboxClaim を作成する

SandboxClaim はウォームプールからサンドボックスをリクエストします。ウォームプールを作成したため、作成されたサンドボックスは新しい Pod を起動するのではなく、プールから実行中の Pod を採用します。

SandboxClaim を作成してウォームプールからサンドボックスをリクエストするには、次の操作を行います。

  1. 次の内容で sandbox-claim.yaml という名前のファイルを作成します。

    apiVersion: extensions.agents.x-k8s.io/v1beta1
    kind: SandboxClaim
    metadata:
      name: sandbox-claim
      namespace: default
    spec:
      warmPoolRef:
        # This must match the name of the SandboxWarmPool.
        name: python-runtime-warmpool
    
  2. SandboxClaim マニフェストを適用します。

    kubectl apply -f sandbox-claim.yaml
    
  3. サンドボックス、請求、ウォームプールが準備できていることを確認します。

    kubectl get sandboxwarmpool,sandboxclaim,sandbox,pod
    

代替方法: サンドボックスを直接作成する

ウォームプールの高速起動時間が必要ない場合は、テンプレートを使用せずにサンドボックスを直接デプロイできます。

Sandbox を直接作成してサンドボックス環境をデプロイする手順は次のとおりです。

  1. 次の内容で sandbox.yaml という名前のファイルを作成します。

    apiVersion: agents.x-k8s.io/v1beta1
    kind: Sandbox
    metadata:
      name: sandbox-example-2
    spec:
      replicas: 1
      podTemplate:
        metadata:
          labels:
            sandbox: sandbox-example
        spec:
          runtimeClassName: gvisor
          restartPolicy: OnFailure
          automountServiceAccountToken: false # Required
          securityContext:
            runAsNonRoot: true # Required
            runAsUser: 1000 # Required if image defaults to root (e.g. busybox)
          nodeSelector:
            sandbox.gke.io/runtime: gvisor
          tolerations:
          - key: "sandbox.gke.io/runtime"
            value: "gvisor"
            effect: "NoSchedule" # Required
          containers:
          - name: my-container
            image: busybox
            command: ["/bin/sh", "-c"]
            args: ["sleep 3600000; echo 'Container finished successfully'; exit 0"]
            securityContext:
              capabilities:
                drop: ["ALL"] # Required
              allowPrivilegeEscalation: false
            resources:
              limits:
                cpu: "100m"
                memory: "128Mi" # Required
    
  2. Sandbox マニフェストを適用します。

    kubectl apply -f sandbox.yaml
    
  3. サンドボックスが実行されていることを確認します。

    kubectl get sandbox
    

Agent Sandbox を v1alpha1 から v1beta1 に移行する

v1alpha1 カスタム リソースを使用して以前のバージョンの Agent Sandbox でクラスタをデプロイした場合は、ワークロードのダウンタイムをほぼゼロにして GKE バージョン 1.36.3-gke.1767000 以降にアップグレードできます。

注: この移行手順は、マネージド GKE Agent Sandbox 機能(--enable-agent-sandbox)を使用するクラスタに適用されます。オープンソース マニフェストを使用して Agent Sandbox をデプロイした場合は、アップストリーム移行ガイドを参照してください。

v1alpha1 と v1beta1 の主な API の違い

コンセプト v1alpha1 の動作 v1beta1 の動作 移行の影響
SandboxClaim ターゲット ウォーム プール(コールド スタート)なしで SandboxTemplate への直接参照を許可しました。 SandboxWarmPool(spec.warmPoolRef.name)への参照が必要です。 コールド スタート クレームは、シャドー ウォームプール(replicas: 0)にマッピングする必要があります。
サンドボックスのオペレーティング モード レプリカまたは状態フィールドから推測されます。 spec.operatingMode フィールドの明示的な値(Running、Suspended など)。 変換 Webhook は、このフィールドを自動的にマッピングして設定します。
CustomResourceDefinition ストレージ バージョン etcd(storage: true)に保存されている v1alpha1。 etcd(storage: true)に保存されている v1beta1。 Webhook が動的に変換します。アップグレード後の手順で etcd オブジェクトが再永続化されます。
コンバージョン Webhook なし /convert で有効(ポート 9447)。 v1alpha1 と v1beta1 の間の双方向変換。

移行ツールを使用して移行する

シャドー ウォームプールを自動的に作成してストレージを再永続化するには、Agent Sandbox リポジトリの正規移行スクリプトを使用します。

スクリプトをダウンロードして準備します。

curl -LO https://raw.githubusercontent.com/kubernetes-sigs/agent-sandbox/v0.5.6/helm/files/migrate.sh
chmod +x migrate.sh

移行の詳細な手順

ワークロードのダウンタイムをほぼゼロにして既存のクラスタを移行するには、次の 3 つのフェーズを順番に完了します。

フェーズ 1: アップグレード前のブートストラップ フェーズ

  1. 既存のリソースをバックアップする: 宣言型エージェント サンドボックス リソース(sandboxtemplates、sandboxwarmpools、sandboxclaims)の YAML バックアップを保存します。

    kubectl get sandboxtemplates,sandboxwarmpools,sandboxclaims \
        --all-namespaces -o yaml > agent-sandbox-v1alpha1-backup.yaml
    
  2. テンプレートのセキュリティ コンプライアンスを確認する: 既存の SandboxTemplate リソースが Agent Sandbox のデプロイ要件を満たしていることを確認します。フェーズ 3 のストレージ移行中、アドミッション コントローラは、これらのセキュリティ ポリシーに準拠していないテンプレートの更新を拒否します。

  3. 作成されるシャドー プールをプレビューします。

    ./migrate.sh --phase=bootstrap --dry-run
    
  4. ブートストラップ フェーズを実行します。

    ./migrate.sh --phase=bootstrap
    
  5. 作成されたシャドー プールを確認します。

    kubectl get sandboxwarmpools --all-namespaces \
        -o custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name,REPLICAS:.spec.replicas,SHADOW:.metadata.annotations.agents\.x-k8s\.io/migration-shadow"
    

フェーズ 2: GKE コントロール プレーンをアップグレードする

GKE コントロール プレーンをバージョン 1.36.3-gke.1767000 以降にアップグレードします。

gcloud container clusters upgrade ${CLUSTER_NAME} \
    --location=${LOCATION} \
    --master \
    --cluster-version=1.36.3-gke.1767000

コントロール プレーンのロールアウト中は、次の点に注意してください。

  • Pod の再起動やダウンタイムが発生しない。
  • 新しいコントローラと /convert Webhook エンドポイントがコントロール プレーンにデプロイされます。

フェーズ 3: アップグレード後のストレージ移行

コントロール プレーンのアップグレードが完了したら、認証情報を更新し、ストレージ移行フェーズを実行して、保存されている etcd オブジェクトを書き換えます。

./migrate.sh --phase=migrate

移行後の検証チェックリスト

商品アイテムのチェックをオン コマンド 期待される結果
CustomResourceDefinition のストレージ バージョン kubectl get crd sandboxes.agents.x-k8s.io sandboxclaims.extensions.agents.x-k8s.io sandboxtemplates.extensions.agents.x-k8s.io sandboxwarmpools.extensions.agents.x-k8s.io -o jsonpath='{range .items[*]}{.metadata.name}{": storedVersions="}{.status.storedVersions}{"\n"}{end}' 4 つの CustomResourceDefinition がすべて表示されます。
storedVersions=["v1beta1"]
Pod の連続性 kubectl get pods -n default -o wide Status: 1/1 Running
Restarts: 0
(アクティブなサンドボックスが実行されているクラスタに適用)
請求のバインド kubectl get sandboxclaims -n default -o yaml spec.warmPoolRef.name: shadow-pool-...
status.conditions: Ready=True(テンプレートが入学要件に準拠している必要があります)
v1alpha1 の互換性 kubectl get sandboxes.v1alpha1.agents.x-k8s.io 非推奨の警告を表示してリソースを返します
v1beta1 ネイティブ CRUD kubectl apply -f sandbox-claim.yaml 警告なしで適用

移行フェーズの完了後も CustomResourceDefinition の .status.storedVersions に ["v1alpha1", "v1beta1"] が表示されるのは、Kubernetes の想定される動作です。移行スクリプトは、既存のすべてのレコードを etcd の v1beta1 に書き換えますが、Kubernetes は非推奨のバージョンを status.storedVersions リストから自動的に削除しません。

すべてのリソースが移行されたことを確認したら、必要に応じて、保存されたバージョンから v1alpha1 を削除できます。

for crd in \
    sandboxes.agents.x-k8s.io \
    sandboxclaims.extensions.agents.x-k8s.io \
    sandboxtemplates.extensions.agents.x-k8s.io \
    sandboxwarmpools.extensions.agents.x-k8s.io; do
  kubectl patch crd "${crd}" --subresource=status --type=merge \
    -p '{"status":{"storedVersions":["v1beta1"]}}'
done

移行に関する問題のトラブルシューティング

コントロール プレーンのアップグレード後またはストレージ移行の実行後に問題が発生した場合は、コントロール プレーンのダウングレードを試みるのではなく、問題を解決してください。

  • 申し立てが WarmPoolNotFound で止まっている:

    • ./migrate.sh --phase=bootstrap を実行せずにコールド スタート v1alpha1 クレームがアップグレードされた場合は、不足しているシャドー ウォーム プールを手動で作成します。

      apiVersion: extensions.agents.x-k8s.io/v1beta1
      kind: SandboxWarmPool
      metadata:
        name: shadow-pool-TEMPLATE_NAME
        namespace: NAMESPACE
        annotations:
          agents.x-k8s.io/migration-shadow: "true"
      spec:
        replicas: 0
        sandboxTemplateRef:
          name: TEMPLATE_NAME
      
    • 存在しない特定のウォームプールを指定するクレームがある場合は、その名前で欠落している SandboxWarmPool リソースを作成するか、クレームの spec.warmPoolRef.name を更新して既存のウォームプールを参照します。

  • 申し立て条件 Ready=False: kubectl describe sandboxclaim を実行して、申し立てのイベントを調べます。参照されている SandboxTemplate が Agent Sandbox のデプロイ要件をすべて満たしていることを確認し、必要に応じてテンプレートを再適用します。

  • 変換エラーまたはコントローラ エラー: kubectl get leases -n gke-managed-agentsandbox を実行して、コントロール プレーン リーダー選出リースがアクティブであることを確認します。問題が解決しない場合は、Cloud カスタマーケアにお問い合わせください。

Agent Sandbox を無効にする

エージェント サンドボックス機能を無効にするには、--no-enable-agent-sandbox フラグを指定して gcloud beta container clusters update コマンドを使用します。

gcloud beta container clusters update ${CLUSTER_NAME} \
    --location=${LOCATION} \
    --no-enable-agent-sandbox

Autopilot クラスタを作成した場合は、ロケーションはリージョン(us-central1 など)です。Standard クラスタを作成した場合は、ロケーションはゾーン(us-central1-a など)です。

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

Cloud de Confiance by S3NS アカウントに課金されないようにするには、作成した GKE クラスタを削除します。

gcloud container clusters delete $CLUSTER_NAME \
    --location=${LOCATION} \
    --quiet

Autopilot クラスタを作成した場合は、ロケーションはリージョン(us-central1 など)です。Standard クラスタを作成した場合は、ロケーションはゾーン(us-central1-a など)です。

次のステップ