使用 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 角色,您可以选择已获授角色的任何项目。
    • 创建项目:如需创建项目,您需要拥有 Project Creator 角色 (roles/resourcemanager.projectCreator),该角色包含 resourcemanager.projects.create 权限。了解如何授予 角色

    转到“项目选择器”

  2. 验证您的 Google Cloud 项目是否已启用结算功能。

  3. 启用 Artifact Registry 和 Kubernetes Engine API。

    启用 API 所需的角色

    如需启用 API,您需要拥有 Service Usage Admin 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 Admin (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:当前项目的 ID。 Google Cloud 定义此变量有助于确保所有资源(例如 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

现在,您可以通过创建 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 命令在本地机器与集群中运行的沙盒路由器服务之间建立直接隧道。这种隧道方法无需使用公共 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. 验证沙盒路由器部署是否正常运行:

    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 目录中,创建一个名为 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!”消息,这是沙盒的输出。

恭喜!您已成功在安全沙盒内运行 shell 命令。使用 sandbox.run() 方法,您可以执行任何 shell 命令,Agent Sandbox 会在安全屏障内运行该命令,以保护集群的节点和其他工作负载免受不受信任的代码的影响。这为 AI 智能体或任何自动化工作流提供了一种安全可靠的任务执行方式。

运行脚本时,SandboxClient 会为您处理所有步骤。它会创建 SandboxClaim 资源来启动沙盒,等待沙盒准备就绪,然后使用 sandbox.run() 方法在安全容器内执行 bash shell 命令。然后,客户端会捕获并输出来自该命令的 stdout。程序运行后,沙盒会自动删除。

创建 SandboxClaim 资源后,系统会从预热池中向 Sandbox 对象分配一个可用的 Pod,并将声明标记为就绪。然后,SandboxWarmPool 会自动补充自身,以维持配置的副本数。

如需验证特定沙盒是否已声明或可用,请检查沙盒 Pod 元数据中的 ownerReferences - 如果 kind 字段的值为 Sandbox,则表示该 Pod 正在使用中。如果 kind 字段的值为 SandboxWarmPool,则表示该 Pod 处于空闲状态,等待声明。

在生产环境中运行沙盒

在本文档中,您将使用 Cloud Shell 从集群外部与沙盒交互。Python 客户端使用您的用户凭据向集群进行身份验证并管理沙盒资源,并使用 kubectl port-forward 命令与沙盒建立连接。这些步骤非常适合开发场景。

在生产场景中,控制器应用(例如 AI 编排器)负责创建和管理沙盒资源。如需在生产环境中使用 Agent Sandbox,请考虑以下事项:

  • 身份验证:您的控制器应用必须向 集群 API 服务器进行身份验证,才能运行沙盒。如何配置身份验证取决于控制器应用的运行位置,如下所示:

    • 如果控制器应用作为 Pod 在同一集群中运行,请使用 Kubernetes RBACWorkload Identity Federation for GKE 以及 IAM 政策,向 Pod 的 Kubernetes ServiceAccount 授予观看沙盒或发现 网络端点所需的权限。
    • 如果控制器应用在集群外部运行,请使用 工作负载身份联合 或 IAM 服务账号为应用提供身份 您可以在允许政策中引用该身份。
  • 路由:控制器应用中的 Python 客户端发出的请求 必须到达集群中的沙盒路由器。在生产环境中,请使用以下方法之一来建立网络连接:

    • 如果控制器应用在同一集群中运行,请使用 SandboxDirectConnectionConfig 函数来定位沙盒路由器服务使用的网址和端口。
    • 如果控制器应用在集群外部运行,请使用 the GKE Gateway API 创建内部或外部负载均衡器。在客户端代码中,使用 SandboxGatewayConnectionConfig 函数引用您的网关。

    如需详细了解这些路由方法,请参阅 GitHub 上的使用示例 以及 路由器的网关部署步骤

  • 沙盒对 Google Cloud 资源的访问权限:如果您的沙盒代码需要向 API(例如 Cloud Storage)发送请求,请使用 IAM 政策以及Workload Identity Federation for GKE,向沙盒 Pod 使用的 Kubernetes ServiceAccount 授予该访问权限所需的权限。 Google Cloud

清理资源

为避免系统向您的 Google Cloud 账号收取费用,您应删除创建的 GKE 集群:

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

后续步骤