在 GKE 上啟用 Agent Sandbox

本文件說明如何在 Google Kubernetes Engine (GKE) 叢集啟用 Agent Sandbox 功能。本文也會說明如何在叢集上建立沙箱環境,安全地執行不信任的程式碼。

如要瞭解 Agent Sandbox 功能如何隔離不受信任的 AI 生成程式碼,請參閱「關於 GKE Agent Sandbox」。

費用

在 GKE 中,Agent Sandbox 免費提供。您建立的資源適用 GKE 定價。

為避免產生不必要的費用,請在完成本文內容後停用 GKE 或刪除專案。

事前準備

  1. 在 Google Cloud 控制台的專案選擇器頁面中,選取或建立 Google Cloud 專案。

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
    • 建立專案:如要建立專案,您必須具備專案建立者角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色。

    前往專案選取器

  2. 確認 Google Cloud 專案已啟用計費功能。

  3. 如果尚未啟用 Artifact Registry 和 Google Kubernetes Engine API,請啟用這些 API。

    啟用 API 時所需的角色

    如要啟用 API,您必須具備 serviceusage.services.enable 權限。如果您建立了專案,可能已透過「擁有者」角色 (roles/owner) 取得這項權限。否則,您可以透過「服務使用管理員」角色 (roles/serviceusage.serviceUsageAdmin) 取得這項權限。瞭解如何授予角色。

    啟用 API

  4. 在 Google Cloud 控制台中啟用 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:目前 Google Cloud 專案的 ID。定義這個變數有助於確保所有資源 (例如 GKE 叢集) 都在正確的專案中建立。
  • CLUSTER_NAME:GKE 叢集的名稱,例如 agent-sandbox-cluster。
  • LOCATION:建立 GKE 叢集的 Google Cloud 區域或可用區。如果您建立 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

您可以在建立新叢集時啟用 Agent Sandbox 功能,也可以更新現有叢集。

建立新的 GKE 叢集時啟用 Agent Sandbox

建議使用 Autopilot 叢集,享有全代管 Kubernetes 體驗。如要選擇最適合工作負載的 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. 建立叢集:

    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 叢集時啟用 Agent Sandbox

如要在現有叢集啟用 Agent Sandbox,叢集必須執行 1.36.3-gke.1767000 以上版本,才能支援 v1beta1 API。

確認 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 沙箱中執行。
  • automountServiceAccountToken: false:防止 Pod 自動掛接預設服務帳戶權杖。
  • securityContext.runAsNonRoot: true:確保容器不會以超級使用者身分執行。
  • securityContext.capabilities.drop: ["ALL"]:從容器中捨棄所有 Linux 功能。
  • resources.limits:您必須指定 CPU 和記憶體限制,以免發生阻斷攻擊 (DoS) 的情況。
  • nodeSelector:必須以 sandbox.gke.io/runtime: gvisor 為目標。
  • tolerations:必須包含 sandbox.gke.io/runtime=gvisor:NoSchedule 汙染的容忍度。

禁止的設定

部署資訊清單不得包含下列任何項目:

  • 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 儲存空間版本 v1alpha1 儲存在 etcd (storage: true)。 儲存在 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

逐步遷移執行手冊

如要遷移現有叢集,並盡量減少工作負載停機時間,請依序完成下列三個階段:

第 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 網頁掛鉤端點會部署在控制層。

第 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 個 CustomResourceDefinitions 都會顯示:
storedVersions=["v1beta1"]
廣告連播連續性 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 適用於 0 個警告

如果 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 狀態:

    • 如果冷啟動v1alpha1聲明已升級,但未執行 ./migrate.sh --phase=bootstrap,請手動建立缺少的陰影暖集區:

      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符合所有代理程式沙箱部署需求,並視需要重新套用範本。

  • 轉換或控制器錯誤:執行 kubectl get leases -n gke-managed-agentsandbox,確認控制層領導者選舉租約是否有效。如果問題持續發生,請與 Cloud Customer Care 團隊聯絡。

停用 Agent Sandbox

如要停用 Agent Sandbox 功能,請使用 gcloud beta container clusters update 指令,並加上 --no-enable-agent-sandbox 旗標。

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

如果您建立的是 Autopilot 叢集,位置就是區域 (例如 us-central1)。如果您建立的是 Standard 叢集,位置就是可用區 (例如 us-central1-a)。

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取費用,請刪除您建立的 GKE 叢集。

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

如果您建立的是 Autopilot 叢集,位置就是區域 (例如 us-central1)。如果您建立的是 Standard 叢集,位置就是可用區 (例如 us-central1-a)。

後續步驟