使用 Agent Sandbox 隔離 AI 程式碼執行作業

您可以部署開發人員環境,在 Google Kubernetes Engine (GKE) 叢集上使用 Agent Sandbox Python 用戶端。這項設定可將不受信任的程式碼隔離在沙箱 Python 環境中,協助您安全地執行及測試 AI 生成的程式碼。這種隔離措施對於保護系統免於 AI 生成程式碼中的潛在安全漏洞、提高開發速度,以及確保安全部署至關重要。如要瞭解 Agent Sandbox 功能如何隔離不受信任的 AI 生成程式碼,請參閱「關於 GKE Agent Sandbox」。

費用

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

事前準備

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

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

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

    前往專案選取器

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

  3. 啟用 Artifact Registry 和 Kubernetes Engine API。

    啟用 API 時所需的角色

    如要啟用 API,您需要具備服務使用情形管理員 IAM 角色 (roles/serviceusage.serviceUsageAdmin),其中包含 serviceusage.services.enable 權限。瞭解如何授予角色

    啟用 API

  4. 在 Google Cloud 控制台中啟用 Cloud Shell。

    啟用 Cloud Shell

  5. 確認您具備完成本指南所需的權限
  6. 您必須擁有已啟用 Agent Sandbox 功能的 GKE 叢集。如果沒有,請按照「在 GKE 上啟用 Agent 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 程式庫可讓您透過程式建立、使用及刪除沙箱。

用戶端會使用 Sandbox Router 做為所有流量的中央進入點。在本文件所述的範例中,用戶端會使用 kubectl port-forward 指令建立連往這個路由器通道,因此您不需要公開任何 IP 位址。請注意,使用 kubectl port-forward 並非安全解決方案,因此應僅限於開發環境。

建立 SandboxTemplateSandboxWarmPool

現在,請建立 SandboxTemplateSandboxWarmPool 資源,定義沙箱的設定。SandboxTemplate 可做為可重複使用的藍圖,Agent Sandbox 控制器會使用這個藍圖建立一致的預先設定沙箱環境。SandboxWarmPool 資源可確保指定數量的預先暖機 Pod 隨時都在執行中,且隨時可供使用。預先暖機的沙箱是已初始化的執行中 Pod。這項預先初始化作業可讓您在不到一秒內建立新的沙箱,並避免啟動一般沙箱時發生啟動延遲:

  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. 套用 SandboxTemplateSandboxWarmPool 資訊清單:

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

部署沙箱路由器

您將用來建立沙箱環境並與之互動的 Python 用戶端,會使用名為「沙箱路由器」的元件與沙箱通訊。

在本範例中,您會使用用戶端的開發人員模式進行測試。這個模式適用於本機開發,並使用 kubectl port-forward 指令,在本機與叢集中執行的 Sandbox Router 服務之間建立直接通道。這種通道方法不需要公開 IP 位址或複雜的輸入設定,可簡化從本機環境與沙箱互動的程序。

請按照下列步驟部署 Sandbox Router:

  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. 確認沙箱路由器部署作業正常運作:

    kubectl get deployment sandbox-router-deployment
    

    等待部署作業在 READY 欄中顯示 2/2 或 1/1。

安裝 Python 用戶端

現在已部署 Sandbox Router 等叢集內元件,最後一個準備步驟是在本機安裝 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 目錄中,建立名為 test_sandbox.py 的 Python 指令碼,並加入以下內容:

    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 自動調度管理工具) 負責建立及管理沙箱資源。如要在正式環境中使用 Agent Sandbox,請注意下列事項:

  • 驗證:您的控制器應用程式必須向叢集 API 伺服器驗證,才能執行沙箱。驗證設定方式取決於控制器應用程式的執行位置,如下所示:

    • 如果控制器應用程式在同一個叢集中以 Pod 形式執行,請使用 Kubernetes RBACGKE 適用的工作負載身分聯盟搭配 IAM 政策,授予 Pod 的 Kubernetes ServiceAccount 監控沙箱或探索網路端點所需的權限。
    • 如果控制器應用程式在叢集外部執行,請使用工作負載身分聯盟或 IAM 服務帳戶,為應用程式提供身分,以便在允許政策中參照。
  • 轉送:來自控制器應用程式中 Python 用戶端的要求,必須送達叢集中的 Sandbox 路由器。在實際工作環境中,請使用下列其中一種方法建立網路連線:

    • 如果控制器應用程式在同一個叢集中執行,請使用 SandboxDirectConnectionConfig 函式,指定 Sandbox Router 服務使用的網址和通訊埠。
    • 如果控制器應用程式在叢集外部執行,請使用 GKE Gateway API 建立內部或外部負載平衡器。在用戶端程式碼中,使用 SandboxGatewayConnectionConfig 函式參照 Gateway。

    如要進一步瞭解這些轉送方法,請參閱 GitHub 上的使用範例路由器的閘道部署步驟

  • 沙箱資源存取權 Google Cloud :如果沙箱程式碼需要將要求傳送至 Google Cloud API (例如 Cloud Storage),請使用 IAM 政策搭配 GKE 適用的工作負載身分聯盟,授予沙箱 Pod 使用的 Kubernetes ServiceAccount 存取權。由於預設網路政策會封鎖對 Google Cloud 中繼資料伺服器169.254.169.254的存取權,因此您必須自訂網路政策,允許這類流量。

  • 網路政策限制:根據預設,Agent Sandbox 會強制執行嚴格的預設安全網路狀態 (networkPolicyManagement: Managed)。在這種狀態下,適用下列限制:

    • 除了指定的 Sandbox 路由器,系統會封鎖來自所有來源的連入流量。
    • 連出至公開網際網路的流量會獲准,但連出至私人 LAN 範圍 (RFC 1918)、內部叢集 DNS (CoreDNS) 和 Cloud 供應商中繼資料伺服器 (169.254.0.0/16) 的流量會遭到明確封鎖。

    如要使用 Workload Identity Federation for GKE 或存取其他私人資源,您必須在 SandboxTemplate 中定義自訂網路政策。如需詳細設定資訊和可自訂的範本 (例如無網路連線的沙箱或 Workload Identity Federation for GKE 整合),請參閱「代理程式沙箱網路政策管理」。

沙盒安全政策

為確保預設安全環境,GKE Agent Sandbox 外掛程式會使用 Kubernetes 驗證許可政策 (VAP),對 SandboxSandboxTemplate 資源強制執行安全限制。系統會自動套用這些政策。

外掛程式將安全防護措施分為兩層政策模式,以提升彈性。以下各節將說明這些政策:嚴格管理的 Core 政策和可自訂的強化政策。

核心安全政策 (sandbox-core-policy)

核心安全政策會強制執行隔離要求,有助於保護沙箱的完整性。這項政策包含多項規則,例如必須使用 gVisor、網路隔離 (例如停用 hostNetwork),以及檔案系統隔離 (例如封鎖 hostPath)。由於 GKE 是透過 addonmanager.kubernetes.io/mode: Reconcile 設定管理這項政策,因此您無法修改或覆寫這些核心規則。

強化安全性政策 (sandbox-hardening-policy)

強化安全政策提供額外的安全最佳做法和管理選項。這項設定會強制執行限制,例如捨棄所有功能、禁止新增功能,以及要求容器以非根身分執行,並設有資源限制。GKE 會透過 addonmanager.kubernetes.io/mode: EnsureExists 設定,以 EnsureExists 模式部署這項政策。這項設定表示 GKE 會在缺少政策時建立政策,但您可以視需要修改或刪除政策或其繫結。

修改或移除強化限制

由於強化政策是以 EnsureExists 模式部署,因此 GKE 會在政策遺失時建立政策,但不會覆寫您的修改內容。如果工作負載需要豁免這些強化規則,您可以修改政策來移除特定限制,或完全刪除政策繫結。

如要修改強化政策並移除特定限制 (例如允許容器以根身分執行,或省略資源限制),請編輯 ValidatingAdmissionPolicy 資源:

kubectl edit validatingadmissionpolicy sandbox-hardening-policy

在開啟的文字編輯器中,找出 validations 區段,然後移除或修改會封鎖工作負載的限制運算式。

或者,如要完全停用叢集的強化政策,請刪除政策繫結:

kubectl delete validatingadmissionpolicybinding sandbox-hardening-binding

已知問題

本節說明在 GKE 中使用 Agent Sandbox 時的已知問題,以及如何解決或規避這些問題。

使用服務網格時,安全性政策會封鎖功能

如果您嘗試部署與服務網格補充程式 (例如 Envoy 或 Istio) 整合的沙箱,強化安全政策可能會封鎖沙箱建立作業,並顯示類似下列的錯誤:

sandbox create error: sandboxes.agents.x-k8s.io "claude-cli-claim-managed" is forbidden:
ValidatingAdmissionPolicy 'sandbox-hardening-policy' with binding 'sandbox-hardening-binding'
denied request: Security Violation: Capabilities.add must be empty. You cannot add capabilities.
  • 原因:服務網格 Sidecar 通常會使用 init 容器,例如 istio-initproxy-init。這些 init 容器需要 NET_ADMINNET_RAW 等功能,才能設定透明輸出路徑的 iptables 規則。根據預設,GKE sandbox-hardening-policy 會封鎖所有容器類型中的所有功能新增項目。
  • 解決方法:由於 GKE 安全強化政策是以 EnsureExists 模式部署,您可以修改 ValidatingAdmissionPolicy,允許特定受信任的 init 容器要求 NET_ADMINNET_RAW 功能。如要瞭解如何修改或移除這些強化限制,請參閱「修改或移除強化限制」。舉例來說,您可以更新政策的驗證運算式或變數,從功能規則中排除信任的容器名稱。

透過 IPv6 連線至 Google API 時,發生資料輸出延遲或逾時

沙箱中的工作負載嘗試連線至外部資源或 Google API (例如 Vertex AI 或 Cloud Storage) 時,可能會發生連線逾時或高延遲 (最多兩分鐘) 的情況。

  • 原因:如果 GKE 叢集已啟用雙重堆疊 IPv6,Google API 的 DNS 解析會同時傳回 IPv4 (A) 和 IPv6 (AAAA) 位址。執行階段引擎 (例如 Node.js) 中的部分演算法會嘗試先透過 IPv6 連線。如果 GKE 虛擬私有雲沒有有效的 IPv6 輸出路徑 (例如 IPv6 的 Cloud NAT 或網際網路閘道),TCP 連線會停止回應 (詳情請參閱 https://developers.google.com/style/word-list#hang),直到 TCP SYN 超時到期為止。接著,TCP 連線會改用 IPv4。
  • 解決方法:如要解決這個問題,請採取下列任一做法:

    • 設定 IPv6 輸出:如要允許輸出 IPv6 流量返回叢集,請在 VPC 網路中設定有效的 IPv6 Cloud NAT 或網際網路閘道。
    • 在工作負載中偏好使用 IPv4:如要偏好使用 IPv4 DNS 解析,請設定工作負載的執行階段。舉例來說,在 Node.js 應用程式中,您可以在 SandboxTemplate 定義中設定下列環境變數:

      env:
      - name: NODE_OPTIONS
        value: "--dns-result-order=ipv4first --no-network-family-autoselection"
      

清除所用資源

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

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

後續步驟

  • 瞭解如何使用 Pod 快照儲存及還原 Agent Sandbox 環境
  • 如要進一步瞭解 Agent Sandbox 開放原始碼專案,請前往 GitHub
  • 瞭解如何搭配使用開放原始碼 Kata Containers 與 Agent Sandbox。Kata Containers 並非 Google Cloud 產品,如果您安裝及使用這項軟體,則須負責管理及排解問題。Google 的支援服務和服務水準協議不適用於 Kata Containers。
  • 如要瞭解為工作負載提供安全隔離的基礎技術,請參閱 GKE Sandbox
  • 如要進一步瞭解如何提升叢集和工作負載的安全性,請參閱 GKE 安全性總覽