数据截至 (上游 commit 415259e527d2)
OpenSandbox — 架构与原理
30 秒导读: OpenSandbox 是阿里开源的通用沙箱平台,给 AI 应用(编码 agent、GUI agent、代码执行、RL 训练)提供「安全、可编程、可大规模调度的一次性电脑」。它的核心是两个平面的分离:一套 OpenAPI 协议把「谁来管容器的生老病死」(控制面)和「怎么在容器里跑命令/读写文件/执行代码」(数据面)彻底切开——你换掉底层是 Docker 还是 Kubernetes,上层的执行 API 一字不变。
1. 这是什么(零基础也能懂)
一句话定义: OpenSandbox 是一个「沙箱即服务」平台——你发一个 HTTP 请求,它给你一台隔离的、临时的、装好环境的容器;你再发请求,就能在里面跑 shell 命令、执行 Python、读写文件、开终端(PTY)。
解决什么问题 / 给谁用: 假设你在写一个 AI agent,它会生成代码并想「真的跑一下」。你绝不敢让模型生成的代码直接在你的服务器上执行——它可能 rm -rf、可能偷你的密钥、可能挖矿。于是你需要一个用完即弃的隔离环境。OpenSandbox 就是把「造这样一台环境、在里面执行、然后销毁」这件事标准化成协议 + 运行时,让你不用自己去拼 Docker API、iptables、seccomp 这些底层。
它能做什么(功能):
- 用统一 API 创建 / 暂停 / 恢复 / 快照 / 销毁沙箱,底层可选 Docker(本 地)或 Kubernetes(大规模分布式调度)。
- 在沙箱里执行命令、跑代码解释器(Jupyter 内核)、读写/搜索/替换文件、开交互式 PTY 终端。
- 给沙箱套更强的隔离:既能用 gVisor / Kata / Firecracker 这类安全容器运行时,也能在容器内部再用 bubblewrap 套一层「可回滚」的嵌套沙箱。
- 管网络进出:统一入站网关(ingress)按沙箱 ID 路由,逐沙箱出站策略(egress)按域名放行/拦截,还能用「凭证保险箱」把真密钥注入到出站请求里而不让工作负载看到明文。
- 配套多语言 SDK(Python / Java / JS / .NET / Go)、
osbCLI、MCP server。
用起来什么样: 一段最小的 osb CLI 交互(取自 README.md):
osb sandbox create --image python:3.12 --timeout 30m -o json
# → 返回一个 sandbox-id,容器已在后台异步provision
osb command run <sandbox-id> -o raw -- python -c "print(1 + 1)"
# → 2
第一条走控制面(造出容器),第二条走数据面(在容器里执行)——这正是理解 OpenSandbox 的钥匙。
一句话直觉/类比: 把它想成「云函数的孪生兄弟」,但反过来:云函数给你无状态的一次调用,OpenSandbox 给你一台有状态、可交互、能装任何东西、随时能拍快照冻结再解冻的一次性电脑。控制面像酒店前台(发钥匙、开房、退房),数据面像房间里的服务电话(点餐、打扫、叫醒)。
本节不谈实现。记住一句话:「管容器的」和「在容器里干活的」是两拨代码、两套 API,故意分开。
2. 顶层全景(它大概怎么转)
OpenSandbox 是个多组件系统。先看谁是谁,再看一次请求怎么流。
2.1 部件一句话职责
| 部件 | 干什么 | 语言 / 位置 |
|---|---|---|
| 协议 specs | 用 OpenAPI 定义「生命周期 API」「执行 API」「出站 API」「诊断 API」的契约 | specs/*.yml *.yaml |
| server(控制面) | FastAPI 服务,收生命周期请求,决定用 Docker 还是 K8s 去创建/暂停/快照/销毁容器 | Python · server/opensandbox_server/ |
| execd(数据面) | 每个沙箱容器里都跑的 Go 守护进程,监听 44772 端口,提供命令/文件/PTY/代码解释器/嵌套隔离 | Go · components/execd/ |
| ingress(入站网关) | 反向代理,按 sandbox-id 从 header 或 URI 路由到对应容器,校验安全访问签名 | Go · components/ingress/ |
| egress(出站网关) | 每沙箱一个 sidecar,透明拦截出站流量,按域名策略放行/拦截,内含凭证保险箱 | Go · components/egress/ |
| SDK / CLI / MCP | 多语言客户端、osb 终端工具、MCP server,封装上面两套 API | sdks/ cli/ |
控制面 = Python,数据面/网络面 = Go。 这不是随意的:控制面要跟 Docker SDK、Kubernetes client、编排逻辑打交道(Python 生态顺手);数据面要塞进每个容器、常驻、低开销、直接摸 Linux namespace/seccomp(Go 单二进制顺 手)。
2.2 顶层图(怎么读:上半是「管容器」的控制面,下半是「进容器」的数据面,左边是客户端)
┌──────────────── 客户端(SDK / osb CLI / MCP / agent)────────────────┐
│ │
①管理请求 │ 创建/暂停/快照/销毁 ②执行请求 跑命令/读写文件/开终端
▼ ▼
┌───────────────────────────┐ ┌──────────────────────────────┐
│ SERVER 控制面 (Python) │ │ INGRESS 入站网关 (Go) │
│ FastAPI /v1/sandboxes ... │ │ 按 sandbox-id 路由 + 签名校验 │
│ api/lifecycle.py │ │ proxy/host.go │
└────────────┬──────────────┘ └───────────────┬──────────────┘
│ 按 config.runtime.type 选后端 │ 转发到容器 44772
┌────────────┴───────────────┐ ▼
▼ ▼ ┌───────────────────────────────────────┐
┌─────────────┐ ┌────────────────┐ │ 沙箱容器 ( 一个/多个) │
│ Docker 后端 │ │ Kubernetes 后端│ ──创建/调度──▶ │ ┌─────────────────────────────────┐ │
│ docker_svc │ │ k8s workload │ │ │ EXECD 数据面 (Go, :44772) │ │
└─────────────┘ └────────────────┘ │ │ 命令/文件/PTY/代码解释器 │ │
│ │ + 嵌套隔离 bwrap+overlay+seccomp│ │
│ └─────────────────────────────────┘ │
│ │ 出站流量 │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ EGRESS sidecar (Go) │ │
│ │ 域名策略 + 凭证保险箱 + mitmproxy│ │
│ └─────────────────────────────────┘ │
└───────────────────────────────────────┘
2.3 主线走一遍(高层,不进代码)
造一台沙箱(控制面):
- 客户端
POST /sandboxes,body 里写镜像、超时、网络策略等 →server/opensandbox_server/api/lifecycle.py。 - server 按配置
config.runtime.type选后端(docker 或 kubernetes)——services/factory.py的create_sandbox_service。 - 后端异步 provision:创建容器/Pod、注入 execd、按需拉起 egress sidecar,先返回
Pending,provision 完转Running。
在沙箱里干活(数据面):
- 客户端把执行请求发给 ingress(或经 server 的代理路由)→ ingress 按
sandbox-id找到容器端点、校验访问签名。 - 请求打到容器里的 execd(:44772)→ execd 跑命令 / 执行代码 / 读写文件,结果流式返回。
- 若代码要访问外网,流量先过 egress sidecar,按域名策略放行,必要时由凭证保险箱注入真密钥。
收尾: 暂停(冻结进程与内存态)、快照(把 rootfs 存成可复用镜像)、或直接销毁(TTL 到期 / 主动 kill)。
3. 阅读地图(建议顺序)
这套文档拆成 7 章,由浅入深。按顺序读能从「协议契约」一路走到「最底层的 namespace/seccomp」;也可按任务直接跳章。
| 顺序 | 章节 | 讲什么 | 适合谁 |
|---|---|---|---|
| 0 | OpenSandbox — 这是什么 / 全景 / 阅读地图(本页) | 零基础入门 + 顶层全景 + 导航 | 所有人先读 |
| 1 | 协议契约与沙箱生命周期状态机 | 四份 OpenAPI 契约、沙箱状态机(Pending→Running→Paused→Terminated)、鉴权 | 想懂「对外长什么样」 |
| 2 | 控制面:从一次 create 请求到容器落地 | FastAPI 路由 → service 抽象 → 异步 provision 全链路 | 改控制面 / 接新后端 |
| 3 |