microsandbox:AI代码执行的硬件级沙箱
microsandbox 基于 libkrun 构建 microVM 沙箱,200ms 冷启动、硬件级隔离、OCI 兼容,提供 Python/Rust/JS SDK 与声明式 Sandboxfile。它不是容器缝合怪,而是为 LLM 工具调用而生的‘毫秒级可信执行单元’。

还在用 subprocess.Popen 执行用户代码?该换匕首了
我上周在线上 debug 一个 LLM 工具调用失败的问题,日志里赫然躺着一行:
OSError: [Errno 13] Permission denied: '/tmp/.cache/pip'
——用户代码里 pip install 被 SELinux 拦了,而我们的服务正运行在 Kubernetes 的 restricted PSP 下。我们花了 4 小时给 Docker 配 seccomp、加 AppArmor profile、调 cgroup memory limit……最后发现,问题根源不是权限,而是抽象泄漏:我们试图用进程级隔离承载 AI 级别的不可信代码执行。
这正是 microsandbox 出现的意义。它不修修补补,直接掀桌重来:放弃 Linux namespace + cgroups 这套“软隔离”,直奔硬件虚拟化——但又不是传统 VM 那种 5 秒冷启动的笨重货。它用的是 libkrun,一个基于 KVM 的轻量 microVM runtime,专为单应用、短生命周期场景设计。每个沙箱都是一个独立 microVM,CPU、内存、IO 全部由硬件强制隔离,连内核态都互不可见。
更狠的是性能:200ms 内完成 microVM 启动 + OCI 镜像加载 + Python 解释器初始化 + 代码执行。这不是 benchmark 数字,是 README 明确写出的实测值(Linux x86_64, host with 32GB RAM)。什么概念?比 curl -I https://api.github.com 平均耗时(230ms)还快。
架构三刀:CLI、SDK、Project,一刀切开抽象污染
microsandbox 不是“另一个 CLI 工具”,它是一套分层执行契约:
-
CLI 层(
msb/msx/msr):面向运维与调试,命令即语义。msx python= eXec a one-off sandbox;msr myapp= Run a project sandbox;msi py-data= Install as system command —— 这种 git-style 命名不是炫技,是把心智负担压到最低。 -
SDK 层(Python/Rust/JS):面向 AI Agent 编程。所有操作皆
async、可await、支持async with上下文管理。没有全局状态、没有隐式环境继承、没有残留进程。你拿到的不是一个 shell,而是一个PythonSandbox对象,它的.run()方法返回Execution对象,.output()是 awaitable future。 -
Project 层(
Sandboxfile):面向工程化复用。它长得像 Cargo.toml + docker-compose.yml 的私生子:
yaml
## Sandboxfile
name: "py-data"
image: "python:3.12-slim"
memory: "512Mi"
cpu: "1"
files:
- src: "./notebooks/"
dst: "/workspace/"
env:
PYTHONPATH: "/workspace"
msb init 自动生成骨架,msb add app --image python 注册依赖,msb build 打包为 OCI image,msb run 启动带持久化 ./menv 的沙箱——这个目录会完整保留 pip install 的包、Jupyter history、甚至 VS Code 设置。这不是沙箱,这是带快照的 IDE 工作站。
硬核代码解析:Rust SDK 如何驯服 microVM
别被 PythonSandbox 名字骗了——底层全是 Rust。来看最核心的 SDK 示例,它揭示了 microsandbox 的真实控制流:
rust
use microsandbox::{SandboxOptions, PythonSandbox};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 构建沙箱配置:声明式,非命令式
let options = SandboxOptions::builder()
.name("test")
.memory("256Mi") // 可精确控制,非 cgroup soft limit
.build();
// 2. 创建沙箱实例:此时 microVM 已启动,Python 解释器就绪
let mut sb = PythonSandbox::create(options).await?;
// 3. 连续执行两段代码:共享同一沙箱上下文(变量 name 跨行存活)
let exec = sb.run(r#"name = "Python""#).await?; // 注意 raw string 避免转义
let exec = sb.run(r#"print(f"Hello {name}!")"#).await?;
// 4. 获取输出:底层走的是 VSOCK + MCP 协议(MicroVM Control Protocol)
println!("{}", exec.output().await?); // prints Hello Python!
// 5. 显式销毁:microVM shutdown,内存清零,磁盘快照可选保存
sb.stop().await?;
Ok(())
}
关键点深挖:
SandboxOptions::builder()是 builder pattern,避免构造函数参数爆炸,且支持链式配置内存/CPU/网络策略;sb.run()不是popen()封装,而是通过 VSOCK(host ↔ microVM 的高速 socket)发送代码到 guest 内的 microsandbox-agent 进程,后者用exec执行并捕获 stdout/stderr;exec.output().await?底层调用的是 MCP 协议的GET_OUTPUTmessage,响应体是 JSON 包含stdout,stderr,exit_code,duration_ms;sb.stop()触发libkrun的kill_vm(),microVM 状态被 KVM 清零,无残留。
实战:嵌入 LLM 网关的 5 行改造
假设你有一个 FastAPI 网关,接收用户 Python 代码:
python
## before: 多线程 + subprocess —— 危险!
import subprocess
result = subprocess.run(
["python", "-c", code],
capture_output=True,
timeout=30
)
换成 microsandbox SDK:
python
## after: 异步、隔离、可控
from microsandbox import PythonSandbox
import asyncio
@app.post("/execute")
async def execute_code(code: str):
async with PythonSandbox.create(
name="llm-exec",
memory="512Mi",
cpu="1"
) as sb:
exec = await sb.run(code)
output = await exec.output()
return {"stdout": output.stdout, "exit_code": output.exit_code}
注意:无需 Docker daemon、无需 root 权限、无需安装 containerd —— 只要 host 支持 KVM(lsmod | grep kvm),microsandbox CLI 会自动下载 libkrun 二进制并管理 microVM 生命周期。
踩坑指南:现实骨感与锋利边界
- Windows 支持是 WIP:目前仅 Linux x86_64 生产可用,macOS 通过 QEMU 兼容层实验性支持,Windows 完全未覆盖。别想着在 GitHub Actions Windows runner 上跑它。
- 镜像必须 OCI 兼容:不能直接拉
python:3.12,得用microsandbox build从 Dockerfile 构建(它会注入 agent、精简 rootfs、设置 init 进程)。官方提供预构建的microsandbox/python系列镜像,推荐直接用。 - MCP 协议细节藏在源码里:README 没写,但
microsandbox-agent的 Rust 源码定义了完整的 message schema(src/agent/protocol.rs),包括EXEC,GET_OUTPUT,STOP_VM。想深度集成?直接读它。 - 没有 REST API Server:作者明确拒绝提供 HTTP wrapper —— “If you need an HTTP API, wrap the SDK yourself.” 这很 Rust,也很清醒。
我的真实看法:它不是沙箱,是执行原语
microsandbox 的野心不在替代 Docker,而在定义一个新的计算原语:Sandbox-as-Function。它把“执行一段不可信代码”这件事,从操作系统进程抽象,拉升到硬件虚拟机抽象,并封装成可组合、可 await、可嵌入任何语言的函数调用。
如果你还在用 exec()、subprocess 或 Docker for 微服务间调用,microsandbox 可能超纲;但如果你正在构建 LLM Tool Calling、Code Interpreter、Auto-Agent Workflow,那么它不是“可以试试”,而是“必须评估”。
它现在是 BETA,文档稀疏,Windows 缺失,但它的内核足够干净:libkrun + Rust + OCI + MCP。这意味着——你随时可以 fork,删掉不用的 SDK,只留 Rust core,把它编译进你的 C++ 推理服务里。这才是开源硬核项目的真正价值:不给你成品,给你锻造成品的铁砧和锤子。
最后一句:
msx python敲下去,200ms 后你的代码已在另一个 CPU 核心上运行。那一刻,你会理解什么叫“隔离即默认”。