用 GKE Agent Sandbox 承载多租户 AI 代码:SeaVerse 如何兼顾隔离、延迟与成本

2026-09-17 32 预计阅读时间: 1 分钟
来源: cloud.google.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:13 分钟

让用户输入一句提示词,几秒后得到一个可运行、可预览、可分享的小游戏或交互应用,看起来只是一次 AI 生成。对平台工程团队来说,背后却是一条完整的执行链:生成代码、启动环境、运行测试、收集日志、保存状态,再把结果交给下一次编辑或 remix。

SeaVerse 面临的核心问题并不是“如何启动更多容器”,而是如何安全地运行大量动态、多租户、潜在不可信的工作负载。它最终采用 GKE 与 GKE Agent Sandbox,在保留 Kubernetes 调度和运维模型的同时获得更强的运行时隔离,并通过更灵活的资源匹配将基础设施成本最多降低 60%。这个案例真正值得关注的,是隔离、启动速度、可观测性和成本之间如何形成一套系统设计。

普通容器隔离为什么不一定够

SeaVerse 上的每个作品都是一个独立工作负载。用户生成的代码会经历运行、测试、集成和验证,并可能访问文件系统、消耗 CPU 与内存,甚至触发异常进程行为。多租户环境中,一次逃逸或资源失控影响的可能不只是单个作品。

传统容器共享宿主机内核。命名空间、cgroup、seccomp 和 Linux capabilities 可以缩小攻击面,但当平台需要持续执行动态生成的代码时,团队通常还会希望增加一道更明确的内核边界。

GKE Agent Sandbox 的价值在于把这种边界纳入 Kubernetes 的调度模型。SeaVerse 使用了基于 gVisor 的隔离能力,也提到了 Kata Containers 与 Cloud Hypervisor 组成的 microVM 方案,并可根据工作负载在 microVM 和 gVisor 隔离运行时之间切换。两者并非简单的优劣关系:

  • gVisor 在应用与宿主机内核之间增加用户态内核层,适合关注启动速度和密度的动态沙箱。
  • Kata Containers + microVM 提供更接近虚拟机的隔离边界,适合安全要求更高或需要不同兼容性取舍的任务。
  • 普通容器 仍适合可信的控制服务、API、队列消费者和监控组件,没有必要把所有 Pod 都放进成本更高的隔离环境。

合理的架构通常会把控制面与执行面分开:API、调度器和元数据服务运行在普通节点池;真正执行用户或 Agent 代码的 Pod 才进入沙箱节点池。

从“黑盒失败”变成可定位的运行时

强隔离如果带来不可观测的执行环境,故障处理成本会迅速上升。一个作品打不开,原因可能是生成代码报错、依赖下载失败、内存超限、启动探针失败、存储挂载异常,也可能只是调度容量不足。

SeaVerse 之前只能看到沙箱失败,却缺少足够的运行状态、指标和失败信号。接入 GKE 原生日志与监控后,沙箱内的行为能够进入统一的诊断链路。用户不会直接看到 Pod、节点或日志,但会感受到体验能否快速打开、点击后是否响应,以及修改后能否立即再次预览。

平台至少应为每次执行附带以下维度:

  • tenant_id:租户或用户标识,日志中应使用不可逆或内部 ID;
  • experience_id:作品标识;
  • sandbox_id:单次执行环境标识;
  • revision:生成内容的版本;
  • runtime_class:gVisor、microVM 或普通容器;
  • queue_latency_msstartup_latency_ms:区分排队慢和启动慢;
  • termination_reason:正常退出、超时、OOM、探针失败或平台回收。

同时需要警惕日志本身成为泄露渠道。不要记录用户提示词中的秘密、访问令牌或完整生成文件;多租户日志查询也必须执行访问控制。

可以这样实践:建立一个最小 gVisor 沙箱节点池

下面是一个可改造的基线示例,用于展示 GKE 中常见的沙箱节点池和 RuntimeClass 使用方式。它不等同于 SeaVerse 的生产配置,也没有覆盖 GKE Agent Sandbox 的全部产品能力。运行前请确认当前 GKE 版本、区域和项目已支持对应功能,并根据最新产品文档核对参数。

先修改项目、集群和区域变量。假设本机已经安装并认证 gcloud,且目标集群已经存在:

export PROJECT_ID="your-project-id"
export CLUSTER="your-gke-cluster"
export REGION="us-central1"

gcloud config set project "$PROJECT_ID"

# 创建专门运行沙箱工作负载的节点池。
gcloud container node-pools create sandbox-pool \
  --cluster="$CLUSTER" \
  --location="$REGION" \
  --machine-type="e2-standard-4" \
  --num-nodes=1 \
  --enable-autoscaling \
  --min-nodes=1 \
  --max-nodes=10 \
  --sandbox type=gvisor

gcloud container clusters get-credentials "$CLUSTER" \
  --location="$REGION"

随后部署一个最小测试工作负载。示例显式设置 CPU、内存和临时存储限制,关闭特权提升,并使用只读根文件系统。真实平台还应增加网络策略、出口代理、镜像签名验证、执行超时和租户配额。

apiVersion: v1
kind: Namespace
metadata:
  name: agent-sandbox-demo
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-app
  namespace: agent-sandbox-demo
data:
  server.py: |
    from http.server import BaseHTTPRequestHandler, HTTPServer

    class Handler(BaseHTTPRequestHandler):
        def do_GET(self):
            body = b"hello from an isolated sandbox\n"
            self.send_response(200)
            self.send_header("Content-Type", "text/plain")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)

    HTTPServer(("0.0.0.0", 8080), Handler).serve_forever()
---
apiVersion: v1
kind: Pod
metadata:
  name: sandbox-demo
  namespace: agent-sandbox-demo
  labels:
    app: sandbox-demo
spec:
  runtimeClassName: gvisor
  automountServiceAccountToken: false
  restartPolicy: Never
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: python:3.12-alpine
      command: ["python", "/app/server.py"]
      ports:
        - containerPort: 8080
      resources:
        requests:
          cpu: "100m"
          memory: "64Mi"
          ephemeral-storage: "64Mi"
        limits:
          cpu: "500m"
          memory: "128Mi"
          ephemeral-storage: "256Mi"
      securityContext:
        allowPrivilegeEscalation: false
        privileged: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]
      volumeMounts:
        - name: app
          mountPath: /app
          readOnly: true
        - name: tmp
          mountPath: /tmp
  volumes:
    - name: app
      configMap:
        name: demo-app
    - name: tmp
      emptyDir:
        sizeLimit: 32Mi
---
apiVersion: v1
kind: Service
metadata:
  name: sandbox-demo
  namespace: agent-sandbox-demo
spec:
  selector:
    app: sandbox-demo
  ports:
    - port: 80
      targetPort: 8080

将文件保存为 sandbox-demo.yaml 后执行:

kubectl apply -f sandbox-demo.yaml
kubectl wait --for=condition=Ready pod/sandbox-demo \
  -n agent-sandbox-demo --timeout=120s

kubectl port-forward -n agent-sandbox-demo \
  service/sandbox-demo 8080:80 &

curl http://127.0.0.1:8080
kubectl logs -n agent-sandbox-demo pod/sandbox-demo

清理测试资源:

kubectl delete namespace agent-sandbox-demo

这个示例只是运行时隔离的起点。若要执行真正的生成代码,平台不应直接把任意代码拼进 Deployment,而应建立受控执行协议:使用固定入口程序读取任务包,校验大小和类型,设置硬超时,通过受限的对象存储获取输入,并只把结构化结果写回控制面。

60% 成本下降来自资源匹配,而不只是“换一种运行时”

SeaVerse 报告的“最多降低 60%”是其特定架构和工作负载下的结果,不能直接作为其他系统的预算承诺。值得复用的是背后的成本机制:过去,安全沙箱对特定服务器类型依赖较强,资源很难精确匹配;采用 GKE Agent Sandbox 后,可以在适当规格的云虚拟机上运行隔离工作负载,提高调度和资源分配的灵活性。

可以重点检查四类成本:

  1. 空闲容量:为突发流量预留多少热节点,冷启动能否由队列吸收。
  2. 请求与限制差距:请求值过高会降低装箱密度,限制值过低则会增加 OOM 和重试。
  3. 沙箱生命周期:一次请求一个沙箱最简单,但复用经过清理的沙箱可能更便宜;复用也会增加租户残留风险。
  4. 持久化策略:不是每个作品都需要永久磁盘。临时预览可使用临时存储,需要持续编辑的作品再挂载持久卷或从对象存储恢复。

SeaVerse 还利用持久文件系统支持创作者跨会话继续修改作品。实践中,应让持久数据与执行沙箱解耦:沙箱可以销毁,作品状态则保存在按租户授权的持久卷、数据库或对象存储中。这样既方便弹性扩缩,也能减少旧环境长期存活带来的安全风险。

扩展到高并发前需要验证什么

GKE Agent Sandbox 在正式可用阶段支持单集群每秒最多分配 300 个沙箱,其中 90% 的分配可在 200 毫秒内完成。这说明基础设施具备很高的分配能力,但端到端体验还取决于镜像拉取、节点扩容、依赖安装、应用初始化和存储挂载。

上线前可以使用下面的检查表:

  • 将沙箱分配延迟与应用就绪延迟分开统计;
  • 预拉取大镜像,避免每个沙箱启动时重复下载依赖;
  • 对租户设置并发、CPU、内存、存储和网络出口配额;
  • 默认拒绝不必要的东西向通信和公网出口;
  • 禁止挂载宿主机路径、特权容器和默认服务账号令牌;
  • 为 OOM、超时、调度失败和异常退出建立独立告警;
  • 分别压测 gVisor 与 microVM 路径,不用单一基准替代真实工作负载;
  • 定期验证沙箱销毁后是否残留文件、进程、凭据或网络连接。

SeaVerse 的经验表明,AI 创作平台的竞争力不只来自模型。用户能否把一个想法立即变成可玩的结果,还取决于执行基础设施是否把不可信代码隔离起来、把故障暴露出来,并以合理成本承受突发并发。GKE 与 GKE Agent Sandbox 提供了一个可行基础,但真正的收益仍来自清晰的控制面与执行面划分、精细的资源预算,以及贯穿整个沙箱生命周期的安全策略。


相关推荐