跳到主要内容

Microsandbox — 总览

30 秒导读: Microsandbox 是一个本地运行时,把不可信的代码(AI agent 生成的代码、插件、CI 任务、爬虫……)塞进一个硬件级隔离的微型虚拟机(microVM)里跑。用起来像 Docker——同样是 image / exec / stop 那套工作流、同样吃标准 OCI 镜像——但底座换成了微VM:平均启动 < 100ms、没有长驻守护进程、可以直接嵌进你的应用代码。这一章只给全景与路由:讲清它是什么、大盘怎么转、每个部件干什么、主线怎么走一遍,然后把你送到对应的深入章节。


1. 这是什么(零基础也能懂)

一句话定义: Microsandbox 是一个用微VM运行不可信负载的本地运行时——你给它一个容器镜像和一条命令,它在一个和你主机内核隔离的小虚拟机里把命令跑起来,再把结果交回给你。

它要解决的问题: 你在写一个 AI agent,想让模型生成的代码真的跑起来看看结果。但这段代码不可信——可能删你的文件、读你的密钥、把机器当跳板。传统选择要么不安全(直接在主机跑),要么太重、太慢(开一台完整虚拟机、或依赖一个常驻的容器守护进程)。

它的取舍: 用 microVM 拿到硬件级隔离(比容器强的边界),同时靠 libkrun 这类轻量 VMM 把启动压到毫秒级、把整个 VM 变成你进程的一个子进程——不需要先起服务器、不需要后台 daemon。README 把这几点列为核心卖点(README.md:28README.md:36-38)。

它能做什么(功能一览):

能力说明
硬件隔离microVM 技术,隔离边界在硬件层(README.md:32)
跨平台Linux(KVM)、macOS(Apple Silicon/HVF)、Windows(WHP)
OCI 兼容直接跑 Docker Hub / GHCR 等标准镜像(README.md:34)
毫秒启动M1 上客机启动平均 < 100ms(README.md:36)
可嵌入Sandbox::builder(...).create() 在你代码里直接开 VM,无 daemon(README.md:37)
不泄露的密钥密钥在主机侧注入网络流量,从不进入 VM(README.md:38,见 05)
长驻会话沙箱可 detached 后台运行,适合长生命周期会话

用起来什么样: 一段 Rust SDK 代码就是它最直观的样子——建 builder、create()(此时才真正开一台 microVM 子进程)、exec() 在里面跑命令、stop() 关掉:

use microsandbox::Sandbox;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let sandbox = Sandbox::builder("my-sandbox") // 起一个名字
.image("python") // 用哪个 OCI 镜像
.cpus(1).memory(512) // 资源上限
.create().await?; // ← 这一步才真正 boot 一台 microVM

let output = sandbox
.exec("python", ["-c", "print('Hello from a microVM!')"])
.await?; // 在客机里跑命令

println!("{}", output.stdout()?);
sandbox.stop().await?; // 关机
Ok(())
}

来源:README.md:133-155。Python / TypeScript / Go 也有对等 SDK(README.md:160-244),命令行则是 msb run python -- ...(README.md:262)。

一句话类比: 把它当"进程级的 Docker,但每个容器其实是一台一秒就开机的迷你虚拟机"。 你熟悉的 image / exec / volume 心智全部适用,只是隔离边界从"共享内核的 namespace"升级成了"独立内核的 microVM"。


2. 顶层全景(它大概怎么转)

怎么读这张图

从上到下是三层:你的代码(SDK/CLI)→ 一个叫 msb sandbox主机进程(它一个人同时扛着 VMM 和 relay)→ 微VM 客机里的 agentd(客机的 PID 1)。左右两侧是三个支撑子系统(镜像、文件系统、网络),它们为这条主线准备"能启动的根文件系统""能读写的盘""能受控上网的栈"。虚线是控制/数据流。

你的应用 / 终端
┌───────────────────────────┐
│ SDK (Rust/Py/TS/Go) │ Sandbox::builder(...).create().exec().stop()
│ 或 msb CLI │
└─────────────┬─────────────┘
│ fork+exec 隐藏子命令 `msb sandbox`,读回启动 JSON 拿 PID
│ 之后经 Unix socket 收发"帧"

┌──────────────────────────────────────────────┐ 主机侧,单进程
│ `msb sandbox` 进程 │
│ ┌───────────────┐ ┌──────────────────┐ │
│ │ VMM (libkrun) │◄────►│ AgentRelay │ │
│ │ vm::enter() │ ring │ 搬运帧的中转 │ │
│ └───────┬────────┘ 缓冲 └────────┬─────────┘ │
└──────────┼───────────────────────┼────────────┘
│ virtio 设备 │ virtio-console "agent" 口
▼ ▼
┌──────────────────────────────────────────────┐ 客机内,microVM
│ agentd (Linux, PID 1) │
│ init 挂载 → 会话循环:收帧、起子进程、回帧 │
└──────────────────────────────────────────────┘

支撑子系统(为主线备料,不在热路径上按需参与):
image ──► OCI 拉取/缓存/合并 ──► 只读根镜像(EROFS)+ 可写上层(ext4)
filesystem ──► virtio-fs 后端(passthrough/memfs/dualfs):主机目录穿透 + 写时复制
network ──► smoltcp 用户态网络栈:DNS 过滤 / TLS 拦截 / 端口发布 / 密钥注入

关键点:VMM 和 relay 在同一个进程里。 运行时 crate 的文档原话是"运行在单个 sandbox 进程内的、统一的 VM + relay 逻辑"(crates/runtime/lib/lib.rs:1-3)。所以主机侧不是"VMM 一个进程 + 网络代理一个进程",而是一个 msb sandbox 子进程一肩挑。

主机↔客机之间不是普通 socket,是 virtio-console。 relay 从 console 后端的环形缓冲区读 agentd 写来的帧、往回写主机的帧(crates/runtime/lib/relay.rs:1-4),协议本身是 CBOR 编码的帧,跑在一个名为 agent 的 virtio-console 口上(crates/protocol/lib/lib.rs:1-3AGENT_PORT_NAMEcrates/protocol/lib/lib.rs:79)。细节见 02

部件一句话职责

部件一句话职责所在 crate / 路径
SDK对外 API:builder → create/exec/stop,把命令翻成帧发给 relaysdk/rust(sdk/rust/lib/lib.rs)
runtimemsb sandbox 进程的内核:vm::enter() 起 VMM + AgentRelay 中转crates/runtime(crates/runtime/lib/lib.rs)
agentd客机里的 PID 1:先 init 挂载,再进会话循环起子进程、回结果crates/agentd(crates/agentd/lib/lib.rs)
protocol主机↔客机共享的帧类型与时序常量(CBOR-over-virtio-serial)crates/protocol(crates/protocol/lib/lib.rs)
imageOCI 镜像拉取、内容寻址缓存、层合并,产出 EROFS 只读根 + ext4 上层crates/image(crates/image/lib/lib.rs)
filesystemvirtio-fs 后端(passthrough/memfs/dualfs)+ 内嵌的 agentd 二进制crates/filesystem(crates/filesystem/lib/lib.rs)
networksmoltcp 用户态网络栈:策略、DNS、TLS、端口发布、密钥注入crates/network(crates/network/lib/lib.rs)
climsb 命令:create/exec/stop/pull/ls…,以及隐藏的 msb sandbox 入口crates/cli(crates/cli/lib/lib.rs)
utils共享常量(~/.microsandbox 目录布局、二进制名、版本)与小工具crates/utils(crates/utils/lib/lib.rs)

还有一批非主线的支撑 crate:db(sea-orm,记沙箱/卷/运行状态)、migration(数据库迁移)、metrics / metrics-collector(CPU/内存/网络实时指标)、packages/agent-client(SDK 底层用的帧客户端)、packages/microsandbox-types(跨语言共享类型,ts-rs 导出)。它们在总库里点到为止,不单独开章。

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

一次 Sandbox::builder("my-sandbox").image("python").create().await?exec 再到 stop,大致经历:

  1. 准备料。 SDK 解析 builder 配置。若镜像没缓存,image 子系统先拉 OCI 镜像、合并层,产出只读根(EROFS)+ 可写上层(ext4)(03)。
  2. 开进程。 SDK 把配置拼成参数,fork+exec 一个隐藏子命令 msb sandbox,并从它 stdout 读回一段启动 JSON 拿到 PID(sdk/rust/lib/runtime/spawn.rs:1-5:257:259 spawn_sandbox)。
  3. VMM 接管。 msb sandboxmicrosandbox_runtime::vm::enter(config),这个函数永不返回——它变身成 VMM,把 microVM 拉起来(crates/cli/lib/sandbox_cmd.rs:203crates/runtime/lib/vm.rs:409 pub fn enter(config: Config) -> !)。
  4. 客机启动。 客机内核起来后,agentd 作为 PID 1 先做同步 init(挂 virtio-fs 根、runtime 目录、网络),再进入异步会话循环(crates/agentd/bin/main.rs:1-9crates/agentd/lib/init.rs:20crates/agentd/lib/session.rs)。
  5. 执行命令。 sandbox.exec(...)(sdk/rust/lib/sandbox/mod.rs:1435)把请求编成帧,经主机的 AgentRelay(crates/runtime/lib/relay.rs:97)搬过 virtio-console;agentd 起子进程、把 stdout/stderr 帧回传(02)。
  6. 关机。 sandbox.stop()(sdk/rust/lib/sandbox/mod.rs:1218)触发协议约定的关机时序:agentd 同步落盘、卸载、请求内核 poweroff,主机侧有兜底超时窗口(crates/protocol/lib/lib.rs:16-63)。生命周期全貌见 01

3. 阅读地图(建议顺序)

各章由浅入深,建议顺着读;也可按任务直接跳。

顺序章节讲什么什么时候读它
0index.md(本章)全景 + 路由先读:建立大盘心智
101-lifecycle.md进程模型与沙箱生命周期:SDK 一行 → msb sandbox → VMM 启动 → 执行 → 退出想搞懂"一次 create/exec/stop 到底发生了什么"
202-protocol-relay.md主机↔客机通信:二进制帧协议、virtio-console relay、agentd 会话循环关心 exec 的数据怎么流、协议怎么编
303-image-rootfs.mdOCI 镜像 → 可启动根:拉取、缓存、层合并、EROFS 只读镜像关心镜像从哪来、根文件系统怎么造
404-guest-filesystem.md客机文件系统:virtio-fs 后端、写时复制、主机穿透关心客机里读写怎么落到主机、卷怎么工作
505-network-security.md用户态网络栈与安全边界:smoltcp、DNS 过滤、TLS 拦截、不泄露的密钥关心网络隔离、策略、密钥注入

推荐路线: 先 01 建立生命周期骨架 → 02 补上"通信"这条主动脉 → 之后按兴趣挑 03/04/05 三个支撑子系统(彼此独立,任意顺序)。


4. 巧妙之处清单(值得带走的精华)

这里只点名,展开在各自章节。

  • VMM 与 relay 合一进程。 主机侧不拆两个进程,vm::enter()AgentRelay 同居一个 msb sandbox,少一层 IPC、少一个可被攻击面(crates/runtime/lib/lib.rs:1-3;详见 01)。
  • enter() 返回 !:进程"变身"而非"调用"。 沙箱子命令直接把自己交给 VMM,永不回到 CLI 逻辑,语义清晰、无残留状态(crates/runtime/lib/vm.rs:409crates/cli/lib/sandbox_cmd.rs:104-203)。
  • 通信走 virtio-console 环形缓冲,不走 vsock/网络。 relay 直接读写 console 后端的 ring buffer,协议是紧凑的 CBOR 帧(crates/runtime/lib/relay.rs:1-4crates/protocol/lib/lib.rs:1-3;详见 02)。
  • 只读根 + 可写上层的分离。 EROFS 承载不可变镜像层、ext4 承载可写 overlay 上层,天然写时复制(crates/image/lib/lib.rs:1-9;详见 03)。
  • 同一 agentd 二进制被内嵌进主机侧 crate。 filesystem crate 直接携带 agentd 二进制,免去客机里另找 init(crates/filesystem/lib/lib.rs:1-2crates/filesystem/lib/agentd)。
  • 密钥永不进 VM。 用户态网络栈在主机侧把密钥注入出站流量,客机内根本看不到明文密钥(README.md:38crates/network/lib/secrets/mod.rs;详见 05)。
  • 跨主机版本的关机时序被编译期不变量护着。 主机兜底窗口必须 ≥ agentd 内部最长 grace,写死成 const _: () = assert!(...)(crates/protocol/lib/lib.rs:65-72)。

5. 代码地图(导航索引)

三列:主题 | 文件路径 | 关键符号。符号名比行号抗漂移——上游更新后优先用符号 grep

主题文件路径关键符号
SDK 公开面(对外导出全集)sdk/rust/lib/lib.rsSandbox, SandboxConfig, AgentClient, Snapshot, Volume, Image
沙箱句柄与生命周期方法sdk/rust/lib/sandbox/mod.rsSandbox::builder, Sandbox::create, exec, stop
builder → createsdk/rust/lib/sandbox/builder.rsSandboxBuilder::create, create_detached
拉起 msb sandbox 子进程sdk/rust/lib/runtime/spawn.rsspawn_sandbox, SpawnMode, ProcessHandle
主机进程内核(VMM+relay)crates/runtime/lib/lib.rs模块 vm, relay, launch, console
VMM 入口(永不返回)crates/runtime/lib/vm.rsenter(-> !), StartupCommand, VmConfig
主机侧 relaycrates/runtime/lib/relay.rsAgentRelay, AgentRelay::run
隐藏的 msb sandbox 命令crates/cli/lib/sandbox_cmd.rsSandboxArgs, run(-> !),调 vm::enter
CLI 命令入口crates/cli/bin/main.rsCommands::Sandbox, commands/ 各子命令
客机 PID 1 入口crates/agentd/bin/main.rsmain(读 BootParams/AgentdConfig)
客机 init 与会话crates/agentd/lib/lib.rs模块 init, session, serial, agent
主机↔客机协议crates/protocol/lib/lib.rsAGENT_PORT_NAME, 关机时序常量
OCI 镜像子系统crates/image/lib/lib.rsRegistry, GlobalCache, 模块 erofs, ext4
客机文件系统后端crates/filesystem/lib/lib.rsPassthroughFs, MemFs, DualFs, 模块 agentd
用户态网络栈crates/network/lib/lib.rs模块 stack, dns, tls, secrets, policy, HOST_ALIAS
共享常量与目录布局crates/utils/lib/lib.rsBASE_DIR_NAME, AGENTD_BINARY, PREBUILT_VERSION
workspace 成员清单Cargo.toml[workspace] members, 内部 crate 版本 pin
官方项目地图AGENTS.md"Project Map" 节

边界说明(诚实优先): 本章只给全景与路由,不深入任何单一子系统的实现——生命周期时序、帧编解码、镜像层合并算法、virtio-fs 穿透语义、smoltcp 栈细节都留给对应章节。凡本章一句话带过的机制,均在 01–05 章展开并配 file:line