跳到主要内容

Kubernetes Agent Sandbox — 架构与原理(入口页)

30 秒导读: agent-sandbox 是 Kubernetes 官方 SIG-Apps 孵化的一个项目。它给 Kubernetes 加了一个新的自定义资源 Sandbox:你写一小段 YAML 声明"我要一个有稳定名字、有持久磁盘、能暂停、能到期自动清理的单个 Pod",一个控制器就替你把底层的 Pod、Service、PVC 全部建好并托管其生命周期。它的头号目标场景,是给 AI agent 提供一次性、隔离的沙箱来跑不可信的、LLM 生成的代码

本页是这个项目的导航入口,只做两件事:让你零基础看懂"这是什么"(Layer 0),以及看懂"它大概怎么转、由哪些部件组成"(Layer 1),最后给你一张阅读地图和代码地图。具体代码走读不在本页,都拆进了下面 5 章。


Layer 0 · 这是什么(零基础也能懂)

一句话定义

agent-sandbox = 一个 Kubernetes CRD(Sandbox)+ 一个控制器,把"单实例、有状态、有稳定身份、可暂停可过期的容器"变成一个声明式 API

(CRD = Custom Resource Definition,自定义资源定义,让你能在 Kubernetes 里发明自己的资源类型,像内置的 Pod、Service 一样用 kubectl apply 管理。)

它解决谁的什么问题

Kubernetes 原生擅长两类工作负载:

  • Deployment:一堆无状态、可随意替换的副本(比如 Web 服务器,挂了再拉一个一模一样的就行)。
  • StatefulSet:一组有编号、有序、有稳定身份的有状态 Pod(比如数据库集群 node-0/node-1/node-2)。

但有一类需求两边都不贴:"我只要一个 Pod,但它必须有稳定的名字和网络身份、有能活过重启的磁盘、能被暂停省钱、能到点自动销毁"。README 把典型场景列成四类(README.md:159-164):

场景举例
开发环境每个开发者一个持久、可联网的云端 IDE 环境
AI agent 运行时给 agent 一个隔离环境,专门执行不可信的、LLM 生成的代码
笔记本 / 研究工具单容器、可持久的 Jupyter Notebook 会话
单 Pod 有状态服务构建代理、小型数据库这种"就一个实例但要稳定身份"的东西

你当然可以用"StatefulSet(副本数=1)+ Service + PVC"硬拼出来,但 README 直言这样做繁琐、且缺少休眠(hibernation)这类专门的生命周期管理(README.md:166)。agent-sandbox 就是把这套组合收敛成一个更轻、更贴合 agent 场景的原生资源

它能做什么(核心功能)

  • 稳定身份(Stable Identity):每个 Sandbox 有稳定的主机名和网络身份(README.md:28)。
  • 持久存储(Persistent Storage):可挂能活过重启的持久卷(README.md:29)。
  • 生命周期管理:控制器托管 Pod 的创建、定时删除、暂停与恢复(README.md:30)。
  • 扩展能力:可选的 extensions 模块再加三种资源——模板复用、热池预热、按需领取(见 Layer 1)。

用起来什么样(最小示例)

装好控制器后,写一段 YAML 声明一个 Sandbox 就够了(README.md:140-151):

apiVersion: agents.x-k8s.io/v1beta1
kind: Sandbox
metadata:
name: my-sandbox
spec:
podTemplate:
spec:
containers:
- name: my-container
image: <IMAGE>
kubectl apply -f my-sandbox.yaml

apply 之后,控制器会创建一个跑你指定镜像的 Pod,你就能通过它稳定的主机名 my-sandbox 去访问它(README.md:153)。注意你写的只是"我想要什么"(desired state),底层的 Pod/Service 是控制器替你算出来并维持的——这就是"声明式"。

一句话直觉

把它想成"Kubernetes 上的一台轻量单机虚拟机体验":一个有固定名字、带一块自己的磁盘、能开机/关机(暂停/恢复)、能设置自动到期的独立盒子——只不过底座是 Kubernetes 原语,不是真 VM(README.md:18 原文即用"lightweight, single-container VM experience"作比)。对 AI agent 来说,这个盒子的意义是:agent 生成的代码在盒子里跑,炸了也炸在盒子里,不伤主机、不伤别的租户


Layer 1 · 全景图(它大概怎么转)

怎么读这张图

从上到下是"抽象 → 具体"。用户要么直接创建一个 Sandbox(核心路径),要么创建一个 SandboxClaim 去热池里领一个现成的(扩展路径)。中间那个控制器进程是大脑,它监听这些资源,替你把最底层的 Pod / Service / PVC 建好、维持好。虚线框里是可选的 Extensions

┌───────────────────────────────┐
创建 Sandbox │ 用户 / SDK │ 创建 Claim
┌─────────────── │ (kubectl / Go / Python 客户端) │ ───────────────┐
│ └───────────────────────────────┘ │
v v
┌───────────┐ ┌───────────────────────────┐
│ Sandbox │ <──────────── adopts(领取/绑定) ────────── │ SandboxClaim │
│ (CRD) │ └───────────────────────────┘
└───────────┘ │ warmPoolRef
│ v
│ ┌──────────────────── Extensions(可选,--extensions)────────────────────┐
│ │ ┌───────────────┐ pre-warms(预热) ┌───────────────────────┐ │
│ │ │ SandboxWarmPool│ ───────────────────> │ 一池预建好的 Sandbox │ │
│ │ └───────────────┘ └───────────────────────┘ │
│ │ │ sandboxTemplateRef │
│ │ v │
│ │ ┌───────────────┐ │
│ │ │SandboxTemplate │ (可复用的 Blueprint 模板) │
│ │ └───────────────┘ │
│ └───────────────────────────────────────────────────────────────────────┘

│ 控制器 reconcile(把期望状态落成真实资源)
v
┌──────────────────────────────────────────────────────────┐
│ 控制器进程 agent-sandbox-controller │
│ SandboxReconciler + 3 个扩展 Reconciler + 4 个 webhook │
└──────────────────────────────────────────────────────────┘
│ 创建并持有(owner reference)
├───────────────┬──────────────────┐
v v v
┌────────┐ ┌──────────┐ ┌──────────┐
│ Pod │ │ Service │ │ PVC │
│(运行时) │ │(稳定身份) │ │(持久存储) │
└────────┘ └──────────┘ └──────────┘

│ (数据面,可选)流量经 sandbox-router 反向代理进入 Pod
v
访问:稳定 hostname / Pod-IP 快路

图里的 SandboxClaim -> Sandbox 用 "adopts" 是因为 Claim 不是新建一个 Sandbox,而是从热池里**领取(adopt)**一个已经预热好的现成 Sandbox 并绑定给你——这正是"热"的来源,省掉了冷启动。详见 03-extensions-warmpool-claim.md

部件一句话职责

素材来源:README 的架构 mermaid(README.md:44-83)与控制器入口 cmd/agent-sandbox-controller/main.go:306-393 里实际注册的四个 Reconciler + 四个 webhook。

部件一句话职责所在文件(符号)
Sandbox(CRD)核心资源:声明一个有稳定身份/持久存储的单 Pod 的期望状态api/v1beta1/sandbox_types.goSandbox / SandboxSpec
SandboxReconciler核心控制器:把 Sandbox 对象 reconcile 成 Pod/Service/PVCcontrollers/sandbox_controller.goSandboxReconciler.Reconcile
SandboxTemplate(CRD)可复用的 Blueprint 模板,供 WarmPool 引用extensions/api/v1beta1/sandboxtemplate_types.goSandboxTemplate
SandboxWarmPool(CRD)维护一池预热好的 Sandbox,减少冷启动等待extensions/api/v1beta1/sandboxwarmpool_types.goSandboxWarmPool / TemplateRef
SandboxClaim(CRD)用户的"领取单",从 WarmPool 领一个现成 Sandboxextensions/api/v1beta1/sandboxclaim_types.goSandboxClaim / WarmPoolRef
3 个扩展 Reconciler分别驱动 Claim / Template / WarmPool 的调谐extensions/controllers/SandboxClaimReconciler 等)
4 个 admission webhook对 Sandbox 及三个扩展资源做准入校验/默认化cmd/agent-sandbox-controller/main.go:316-392ctrl.NewWebhookManagedBy
sandbox-router独立数据面:反向代理,把请求按 Pod-IP 快路或 DNS 送进目标 Sandboxsandbox-router/proxy/resolve.goResolve / SourceCache
Go / Python SDK客户端库:用代码创建、连接、管理 Sandbox 生命周期clients/go/sandbox/clients/python/agentic-sandbox-client/

注意分工: Sandbox 本身是核心(Core),装了就有;Template / WarmPool / Claim 三件套是扩展(Extensions),只有启动控制器时带 --extensions 才会注册(main.go:99 的 flag、main.go:322if extensions 分支)。sandbox-router 是一个独立的可选数据面组件,不在主控制器进程里。

主线走一遍(高层,不进代码)

以最核心的路径为例——用户直接创建一个 Sandbox

① 用户 kubectl apply 一个 Sandbox YAML(声明期望状态)

v
② SandboxReconciler.Reconcile 被触发,读到这个 Sandbox 对象
│ (main.go:306 注册的核心 controller)
v
③ reconcileChildResources:按 Spec 建/更新子资源
├─ reconcilePVCs → 持久存储
├─ reconcilePod → 运行时 Pod(打上 owner reference)
└─ reconcileService→ 稳定网络身份

v
④ computeConditions → 算出 Ready 等状态条件,写回 Status
│ (Ready=DependenciesReady 表示全部就绪)
v
⑤ 之后每次 reconcile 检查 shutdownTime:到期就删子资源,
按 shutdownPolicy(Delete/Retain) 决定是否连 Sandbox 对象一起删

这条主线的代码在 controllers/sandbox_controller.go:154Reconcile)→ :235reconcileChildResources)→ :278computeConditions),到期清理走 ReconcilecheckSandboxExpiry 分支(:202-213)。具体怎么走、所有权与状态条件怎么算,见 02-sandbox-controller.md


阅读地图(建议顺序)

本项目按子系统拆成 5 章,建议按下面顺序读——先懂数据模型,再懂控制器,再看扩展与数据面,最后落到客户端

  1. 01-sandbox-api-model.md — 核心数据模型。 先搞清 SandboxSpec/Status 各字段(SandboxSpecSandboxStatusLifecycleOperatingMode),以及被 Sandbox 与 SandboxTemplate 共享的 SandboxBlueprint。读懂"声明式 API 长什么样"是理解一切的前提。
  2. 02-sandbox-controller.md — 核心控制器。 Reconcile 主循环、reconcileChildResources 建 Pod/Service/PVC、owner reference 所有权模型、computeConditions 状态条件、到期清理。这是项目的"大脑"。
  3. 03-extensions-warmpool-claim.md — 扩展面。 SandboxTemplate / SandboxWarmPool / SandboxClaim 三件套,冷启动 vs 热池领取(adopt)的机制,热池怎么预热、Claim 怎么领。
  4. 04-sandbox-router.md — 数据面。 sandbox-router 反向代理:Pod-IP 缓存快路(SourceCache)、DNS 兜底、X-Sandbox-* 头契约与鉴权(TokenReview)。
  5. 05-client-sdks.md — 客户端 SDK。 Go 与 Python 客户端怎么用代码走完 Sandbox 的生命周期(创建、连接、执行命令、传文件、销毁)。

只想快速评估相关性? 读到这里(Layer 0 + Layer 1)就够判断"这项目是不是我要的"了。想动手/改代码,再往下钻对应章。


巧妙之处(预告)

这些设计点值得带走,本页只点名,具体在各章展开:

  • Blueprint 共享,而非复制。 SandboxSpec 直接内联(json:",inline")一个 SandboxBlueprint,让 SandboxSandboxTemplate 共用同一份工作负载定义——加字段一处即两处生效(api/v1beta1/sandbox_types.go:195-199 的注释专门解释了这个"提升到共享"的约定)。详见 01
  • 到期删子资源,但对象可保留。 Lifecycle.ShutdownPolicyDelete/Retain:到期时底层 Pod/Service 总是被删(省钱),但 Sandbox 对象本身可以 Retain 下来只标记为 Expired,方便审计与复活(sandbox_types.go:226-236)。详见 02
  • 热池领取(adopt),把冷启动摊平。 Claim 不新建 Sandbox,而是从 WarmPool 里领取一个已预热的现成实例,把镜像拉取/初始化的时间提前付掉——对 agent"要一个环境就要立刻能用"极关键。详见 03
  • 路由三级 fallback,快路优先。 sandbox-routerResolve 有明确优先级:显式 Pod-IP → 缓存命中(SourceCache,KEP 的安全快路)→ DNS 兜底,既快又总能工作(sandbox-router/proxy/resolve.go:55-93)。详见 04

代码地图(顶层导航索引)

这张表是给人和 agent 的"跳转表"——认准符号名grep(比行号抗上游漂移)。更细的地图在各章末尾。

主题文件关键符号
控制器进程入口、注册所有 controller 与 webhookcmd/agent-sandbox-controller/main.gomainSandboxReconciler 注册在 :306,扩展在 :322-392)
核心数据模型:Sandbox 的 Spec/Statusapi/v1beta1/sandbox_types.goSandboxSandboxSpecSandboxStatusSandboxBlueprintLifecycle
核心控制器:reconcile 主循环controllers/sandbox_controller.goSandboxReconciler.ReconcilereconcileChildResourcescomputeConditions
扩展 CRD:领取单extensions/api/v1beta1/sandboxclaim_types.goSandboxClaimSandboxClaimSpecWarmPoolRef
扩展 CRD:热池extensions/api/v1beta1/sandboxwarmpool_types.goSandboxWarmPoolSandboxWarmPoolSpecTemplateRef
扩展 CRD:模板extensions/api/v1beta1/sandboxtemplate_types.goSandboxTemplate
扩展控制器extensions/controllers/SandboxClaimReconcilerSandboxWarmPoolReconcilerSandboxTemplateReconciler
数据面反向代理:解析目标sandbox-router/proxy/resolve.goResolveSourceSourceCacheSourceDNS
数据面进程入口(缓存 + 鉴权)sandbox-router/cmd/main.gomaincache.Newauthz.NewTokenReviewAuthorizer
Go 客户端clients/go/sandbox/sandbox.goclient.goconnector.go
Python 客户端clients/python/agentic-sandbox-client/k8s_agent_sandbox/sandbox.pysandbox_client.pyconnector.py

本页为入口导航,不含代码走读;各机制的深入讲解见上面 5 章。所有引用 as-of commit 94fe84eac9bfad4a5b3f3d4dac63b7c5c75a2b8b