本文档介绍了如何在 Google Kubernetes Engine (GKE) 集群上的隔离沙盒中运行 AI 生成的代码。您可以在集群上创建一个沙盒模板和一个就绪沙盒池。然后,您运行一个 Python 脚本,该脚本会从池中请求一个沙盒,并在沙盒中运行一个命令。该脚本使用 Agent Sandbox Python 客户端,这是一个用于创建和管理沙盒的库。
在沙盒中运行不受信任的代码有助于保护系统免受 AI 生成的代码中潜在漏洞的影响,提高开发速度,并提高部署的安全性。如需简要了解 GKE 上的 Agent Sandbox 如何隔离不受信任的 AI 生成的代码,请参阅 GKE 上的 Agent Sandbox 简介。
费用
GKE 上的 Agent Sandbox 是一款开源软件,您可以免费使用。GKE 价格适用于您创建的资源,包括 Agent Sandbox 控制器使用的计算资源。
准备工作
-
在 Google Cloud 控制台的项目选择器页面上,选择或创建 Google Cloud 项目。
选择或创建项目所需的角色
- 选择项目:选择项目不需要特定的 IAM 角色,您可以选择已获授角色的任何项目。
-
创建项目:如需创建项目,您需要拥有 Project Creator 角色 (
roles/resourcemanager.projectCreator),该角色包含resourcemanager.projects.create权限。了解如何授予角色。
启用 Kubernetes Engine API(如果尚未启用)。
启用 API 所需的角色
如需启用 API,您需要拥有
serviceusage.services.enable权限。如果您创建了项目,则可能已经通过 Owner 角色 (roles/owner) 拥有此权限。否则,您可以通过 Service Usage Admin 角色 (roles/serviceusage.serviceUsageAdmin) 获得此权限。了解如何授予角色。-
在 Google Cloud 控制台中,激活 Cloud Shell。
- 验证您是否拥有完成本文档所需的权限。
- 确保您有一个已安装 Agent Sandbox 控制器并部署了沙盒路由器的 GKE 集群。如果没有,请仅完成在 GKE 上安装 Agent Sandbox 的以下部分,然后返回本文档:
您无需完成该文档的其他部分,例如部署沙盒化环境。
在本文档的后面部分,您将创建自己的
SandboxTemplate和SandboxWarmPool资源。
所需的角色
如需获得创建和管理沙盒所需的权限,请让您的管理员为您授予项目的 Kubernetes Engine Admin (roles/container.admin) IAM 角色。如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
定义环境变量
为了简化您在本文档中运行的命令,您可以在 Cloud Shell 中设置环境变量。在 Cloud Shell 中,运行以下命令来定义以下有用的环境变量:
export CLUSTER_NAME="agent-sandbox-cluster"
export LOCATION="us-central1"
以下是这些环境变量的说明:
CLUSTER_NAME:GKE 集群的名称,例如agent-sandbox-cluster。LOCATION:GKE 集群所在的 Google Cloud 区域或可用区。如果您使用 Autopilot 集群,请将其设置为区域(例如us-central1)。如果您使用 Standard 集群,请将其设置为可用区(例如us-central1-a)。
部署沙盒化环境
本部分介绍了如何创建沙盒蓝图(SandboxTemplate 资源)、验证网络路由器,以及安装用于与沙盒交互的 Python 客户端。
建议使用 Agentic Sandbox Python 客户端来创建沙盒并与之交互。 此客户端提供了一个接口,可简化沙盒的整个生命周期(从创建到清理)。这是一个 Python 库,可用于以程序化方式创建、使用和删除沙盒。
客户端使用沙盒路由器作为所有流量的中央入口点。在本文档所述的示例中,客户端使用命令 kubectl port-forward 创建通往此路由器的隧道,这样您就不需要公开任何公共 IP 地址。请注意,使用 kubectl port-forward 并不是一种安全的解决方案,应仅在开发环境中使用。
创建 SandboxTemplate 和 SandboxWarmPool 资源
现在,您可以通过创建 SandboxTemplate 资源和 SandboxWarmPool 资源来定义沙盒的配置。SandboxTemplate 资源充当可重用的蓝图,供 Agent Sandbox 控制器用于创建一致的预配置沙盒环境。SandboxWarmPool 资源有助于确保指定数量的预热 Pod 始终处于运行状态,并随时可供声明。预热沙盒是一个已初始化的运行中 Pod。通过这种预初始化,可以在不到一秒的时间内创建新沙盒,并避免启动常规沙盒的启动延迟:
在 Cloud Shell 中,创建一个名为
sandbox-template-and-pool.yaml的文件,其中包含以下内容:apiVersion: extensions.agents.x-k8s.io/v1beta1 kind: SandboxTemplate metadata: name: python-sandbox-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/v1beta1 kind: SandboxWarmPool metadata: name: python-sandbox-warmpool namespace: default spec: replicas: 2 sandboxTemplateRef: name: python-sandbox-template应用
SandboxTemplate和SandboxWarmPool清单:kubectl apply -f sandbox-template-and-pool.yaml等待预热池的沙盒准备就绪:
kubectl wait sandboxwarmpool python-sandbox-warmpool \ --for=jsonpath='{.status.readyReplicas}'=2 \ --timeout=600s在本文档的后面部分,Python 客户端会创建一个
SandboxClaim资源。如果客户端在池的沙盒准备就绪之前创建声明,控制器可能会为该声明创建新的沙盒,而不是从池中分配一个沙盒。在 Autopilot 集群中,沙盒可能需要几分钟才能准备就绪,因为 GKE 可能需要为其创建节点。
验证沙盒路由器
您将用于创建沙盒环境并与之交互的 Python 客户端使用名为“沙盒路由器”的组件与沙盒进行通信。
在此示例中,您将使用客户端的开发者模式进行测试。此模式适用于本地开发,并使用 kubectl port-forward 命令在本地机器与集群中运行的沙盒路由器服务之间建立直接隧道。这种隧道方法无需使用公共 IP 地址或复杂的入站流量设置,并简化了从本地环境与沙盒的交互。
验证沙盒路由器是否在 agent-sandbox-system 命名空间中运行:
kubectl get deployment sandbox-router --namespace=agent-sandbox-system
当路由器运行时,READY 列会显示所有副本都已就绪,例如 2/2。如果该命令返回 NotFound 错误,请按照部署沙盒路由器中的步骤部署路由器。
安装 Python 客户端
现在,沙盒路由器等集群内组件已部署完毕,最后一步准备工作是在本地机器上安装 Agentic Sandbox Python 客户端。请注意,此客户端是一个 Python 库,可让您以程序化方式创建、使用和删除沙盒。您将在下一部分中使用它来测试环境:
创建并激活 Python 虚拟环境:
python3 -m venv .venv source .venv/bin/activate安装客户端软件包。使用与 Agent Sandbox 控制器相同的版本:
pip install k8s-agent-sandbox==1.0.6
测试沙盒
在所有设置组件就绪后,您现在可以使用 Agentic Sandbox Python 客户端创建沙盒并与之交互。
创建一个名为
test_sandbox.py且包含以下内容的 Python 脚本:from k8s_agent_sandbox import SandboxClient from k8s_agent_sandbox.models import SandboxLocalTunnelConnectionConfig # Tunnels to svc/sandbox-router-svc in the agent-sandbox-system namespace. # cleanup=True deletes the sandbox when the script exits. client = SandboxClient( connection_config=SandboxLocalTunnelConnectionConfig(), cleanup=True, ) sandbox = client.create_sandbox(warmpool="python-sandbox-warmpool", namespace="default") try: print(sandbox.commands.run("echo 'Hello from the sandboxed environment!'").stdout) except Exception as e: print(f"An error occurred: {e}")在终端中(虚拟环境仍处于活跃状态),运行测试脚本:
python3 test_sandbox.py
您应该会看到“Hello from the sandboxed environment!”消息,这是沙盒的输出。
恭喜!您已在安全沙盒中成功运行 shell 命令。使用 sandbox.commands.run() 方法,您可以执行任何 shell 命令,而 GKE 上的 Agent Sandbox 会在安全屏障内运行该命令,从而保护集群的节点和其他工作负载免受不受信任的代码的影响。这为 AI 智能体或任何自动化工作流提供了一种安全可靠的任务执行方式。
运行脚本时,SandboxClient 会为您处理所有步骤。它会创建 SandboxClaim 资源来启动沙盒,等待沙盒准备就绪,然后使用 sandbox.commands.run() 方法在安全容器内执行 bash shell 命令。然后,客户端会捕获并输出来自该命令的 stdout。由于脚本将 cleanup 参数设置为 True,因此客户端会在程序退出时删除沙盒。
创建 SandboxClaim 资源后,系统会将温池中的可用沙盒分配给声明,并将声明标记为就绪。然后,SandboxWarmPool 资源会自动补充自身,以维持配置的副本数量。
如需验证特定沙盒是否已被认领或可用,请检查 Sandbox 资源的元数据中的 ownerReferences。如果 kind 字段的值为 SandboxClaim,则表示沙盒正在使用中。如果 kind 字段的值为 SandboxWarmPool,则表示沙盒处于空闲状态,正在等待被认领。
在生产环境中运行沙盒
在本文档中,您将使用 Cloud Shell 从集群外部与沙盒进行交互。Python 客户端会使用您的用户凭证向集群进行身份验证并管理沙盒资源,并使用 kubectl port-forward 命令与沙盒建立连接。这些步骤非常适合开发场景。
在生产场景中,控制器应用(例如 AI 编排器)负责创建和管理沙盒资源。如需在生产环境中使用 GKE 上的 Agent Sandbox,请考虑以下事项:
身份验证:您的控制器应用必须向集群 API 服务器进行身份验证,才能运行沙盒。如何配置身份验证取决于控制器应用的运行位置,如下所示:
- 如果控制器应用作为 Pod 在同一集群中运行,请使用 Kubernetes RBAC 或Workload Identity Federation for GKE 搭配 IAM 政策,向 Pod 的 Kubernetes ServiceAccount 授予监视沙盒或发现网络端点所需的权限。
- 如果控制器应用在集群外部运行,请使用工作负载身份联合或 IAM 服务账号为应用提供可在允许政策中引用的身份。
路由:来自控制器应用中 Python 客户端的请求必须到达集群中的沙盒路由器。在生产环境中,使用以下方法之一建立网络连接:
- 如果控制器应用在同一集群中运行,请使用
SandboxDirectConnectionConfig函数定位到沙盒路由器服务使用的网址和端口。 - 如果控制器应用在集群外部运行,请使用 GKE Gateway API 创建内部或外部负载均衡器。在客户端代码中,使用
SandboxGatewayConnectionConfig函数引用网关。
如需详细了解这些路由方法,请参阅 GitHub 上的使用示例和路由器的 Gateway 部署步骤。
- 如果控制器应用在同一集群中运行,请使用
沙盒对 Google Cloud 资源的访问权限:如果您的沙盒代码需要向 Google Cloud API(例如 Cloud Storage)发送请求,请使用具有Workload Identity Federation for GKE的 IAM 政策,为沙盒 Pod 使用的 Kubernetes ServiceAccount 授予该访问权限所需的权限。由于默认网络政策会阻止对 Google Cloud 元数据服务器 (
169.254.169.254) 的访问,因此您必须自定义网络政策以允许此流量。网络政策限制:默认情况下,GKE 上的 Agent Sandbox 会强制执行严格的默认安全网络状态 (
networkPolicyManagement: Managed)。在此状态下,适用以下限制:- 除了指定的沙盒路由器(
agent-sandbox-system命名空间中具有app: sandbox-router标签的 Pod)之外,所有来源的入站流量都会被屏蔽。 - 允许出站流量流向公共互联网,但明确禁止出站流量流向专用 LAN 范围 (RFC 1918)、内部集群 DNS (CoreDNS) 和云提供商元数据服务器 (
169.254.0.0/16)。
如需使用 Workload Identity Federation for GKE 或访问其他私有资源,您必须在
SandboxTemplate资源中定义自定义网络政策。如需了解详细的配置详情和可自定义的模板(例如经过网闸隔离的沙盒或 Workload Identity Federation for GKE 集成),请参阅 Agent Sandbox 网络政策管理。- 除了指定的沙盒路由器(
沙盒安全政策
默认情况下,GKE 上的 Agent Sandbox 不会将安全政策应用于沙盒。为帮助强制执行沙盒的隔离设置,请应用 Agent Sandbox GitHub 代码库中推荐的 secure-sandbox-policy Kubernetes 验证准入政策 (VAP)。如需查看相关说明,请参阅应用建议的安全政策。
该政策会强制执行隔离要求,例如要求使用 gVisor、停用 hostNetwork 以及屏蔽 hostPath 卷。该政策还强制执行强化要求,例如丢弃所有功能、阻止添加新功能,以及要求容器以非根用户身份运行并设置资源限制。如需查看完整的要求列表,请参阅 GKE 上的 Agent Sandbox 部署要求。
修改或移除政策限制条件
由于您自行应用该政策,因此可以对其进行更改以适应您的工作负载。如果您的工作负载需要豁免某些规则,您可以修改政策以移除特定限制条件,或完全删除政策绑定。移除限制条件会降低政策提供的隔离性,因此请仅移除工作负载所需的限制条件。
如需修改政策并移除特定限制条件(例如,允许容器以 root 身份运行或省略资源限制),请修改 ValidatingAdmissionPolicy 资源:
kubectl edit validatingadmissionpolicy secure-sandbox-policy
在打开的文本编辑器中,找到 validations 部分,然后移除或修改会阻止工作负载的限制条件表达式。
或者,如果您想停止在集群中强制执行该政策,请删除政策绑定:
kubectl delete validatingadmissionpolicybinding secure-sandbox-binding
已知问题
本部分介绍了在 GKE 上使用 Agent Sandbox 时的已知问题,以及如何解决或规避这些问题。
使用服务网格时,安全政策会屏蔽功能
如果您应用了推荐的安全政策,并尝试部署与服务网格边车(例如 Envoy 或 Istio)集成的沙盒,则该政策可能会阻止创建沙盒,并显示如下错误:
sandbox create error: sandboxes.agents.x-k8s.io "claude-cli-claim-managed" is forbidden:
ValidatingAdmissionPolicy 'secure-sandbox-policy' with binding 'secure-sandbox-binding'
denied request: Security Violation: Capabilities.add must be empty. You cannot add capabilities.
- 原因:服务网格边车通常使用 init 容器,例如
istio-init或proxy-init。这些 init 容器需要NET_ADMIN或NET_RAW等功能来配置iptables规则,以实现透明的出站流量路由。secure-sandbox-policyValidatingAdmissionPolicy 会阻止所有容器类型中的所有功能添加。 - 解决方法:由于您在集群中管理此政策,因此可以修改
ValidatingAdmissionPolicy以允许特定受信任的初始化容器请求NET_ADMIN和NET_RAW功能。如需了解如何修改或移除政策限制条件,请参阅修改或移除政策限制条件。例如,您可以更新政策的验证表达式或变量,以使受信任的容器名称免受功能规则的约束。
通过 IPv6 连接到 Google API 时出现出站流量延迟或超时
沙盒内的工作负载在尝试连接到外部资源或 Google API(例如 Vertex AI 或 Cloud Storage)时,可能会遇到连接超时或高延迟(长达两分钟)的情况。
- 原因:如果您的 GKE 集群启用了双栈 IPv6,则 Google API 的 DNS 解析会同时返回 IPv4 (A) 和 IPv6 (AAAA) 地址。运行时引擎(例如 Node.js)中的某些算法会尝试先通过 IPv6 进行连接。如果您的 GKE VPC 没有有效的 IPv6 出站流量路由(例如 Cloud NAT 或 IPv6 互联网网关),则 TCP 连接会停止响应,直到 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 快照在 GKE 环境中保存和恢复 Agent Sandbox。
- 如需详细了解 Agent Sandbox 开源项目,请访问 GitHub。
- 了解如何在 GKE 上将开源 Kata Containers 与 Agent Sandbox 搭配使用。 Kata Containers 不是 Google Cloud 产品。如果您安装并使用此软件,则需要负责管理和问题排查。Google 的支持服务和 SLA 不适用于 Kata Containers。
- 如需了解为工作负载提供安全隔离的基础技术,请参阅 GKE Sandbox。
- 如需详细了解如何增强集群和工作负载的安全性,请参阅 GKE 安全概览。