🎯 一句话总结:forkd把一个已经启动并预热的Firecracker microVM保存成快照,再用写时复制快速生成大量隔离子机。它适合代码解释器、并行评测和多Agent执行,当前仍处于Alpha阶段,需要Linux、KVM和严格的网络权限配置。
📌 forkd是什么

forkd是一个面向AI Agent并行任务的microVM沙箱运行时。父虚拟机只启动一次,提前加载Python依赖、JIT运行时、模型权重或浏览器;子虚拟机从父快照恢复,共享尚未发生变化的内存页。
每个子机都是独立的Firecracker进程,由KVM提供虚拟化隔离。子机修改内存时,Linux内核通过MAP_PRIVATE执行写时复制,变化后的页面才形成独立副本。
| 能力 | 实现方式 |
|---|---|
| 隔离 | 每个子机独立Firecracker + KVM |
| 快速启动 | 从预热父快照恢复 |
| 内存复用 | Copy-on-Write页面共享 |
| 运行环境 | 完整Linux、TCP网络、apt与HTTPS |
| 资源限制 | cgroup v2,目前重点支持memory.max |
| 接口 | CLI、REST、Python、TypeScript、MCP |
| 运维 | systemd、Prometheus指标、JSON审计日志 |
| 许可证 | Apache 2.0 |
项目当前README标记为Alpha。磁盘格式和API在1.0之前仍可能变化,生产系统应固定版本并保留迁移方案。
⚙️ 为什么能快速分叉

传统虚拟机要重复启动内核、挂载磁盘、加载解释器并导入依赖。forkd把这些工作放在父机阶段完成:
启动父microVM
↓
加载Python、依赖、模型或浏览器
↓
暂停并保存内存、磁盘和设备状态
↓
多个子Firecracker进程映射同一快照
↓
子机只复制自己修改的页面
BRANCH允许对正在运行的沙箱制作分支。Agent可以在执行高风险命令前保存状态,再让多个子机分别尝试不同方案。
v0.4的Live Branch要求父沙箱以live_fork=True启动。它使用memfd共享内存,并通过UFFD_WP跟踪写入页面。官方基准在1.5 GiB源虚拟机上记录了56ms p50、64ms p90的暂停窗口;内存复制在父机恢复后继续进行。
from forkd import Controller
c = Controller()
parent = c.spawn_sandboxes(
"pyagent",
n=1,
per_child_netns=True,
live_fork=True,
)[0]
branch = c.branch_sandbox(
parent["id"],
tag="checkpoint-1",
mode="live",
wait=False,
)
# wait=False返回时,快照可能仍处于writing状态
# 确认status=ready后再从该tag创建子机
grandchildren = c.spawn_sandboxes(branch["tag"], n=5)
wait=False用于缩短调用等待时间,并不代表后台快照已经完成。程序需要轮询快照状态,避免从尚未就绪的分支继续启动。
🛠️ 安装与第一次运行
前置条件
| 项目 | 要求 |
|---|---|
| 操作系统 | x86_64 Linux,推荐Ubuntu 22.04或更新版本 |
| 虚拟化 | CPU支持硬件虚拟化,主机可访问/dev/kvm |
| cgroup | cgroup v2 |
| Live Branch | Linux 5.7以上,并启用userfaultfd或提供CAP_SYS_PTRACE |
| 容器环境 | 云主机需提供裸金属KVM或明确支持嵌套虚拟化 |
普通共享VPS和多数受限容器无法直接访问KVM。执行安装前先确认云平台允许嵌套虚拟化。
一键路径
项目README当前给出的预构建版本为v0.5.3:
curl -sSL https://github.com/deeplethe/forkd/releases/download/v0.5.3/forkd-v0.5.3-x86_64-linux.tar.gz \
| sudo tar -xz -C /usr/local/bin/
sudo -E forkd quickstart
quickstart会检查KVM、Firecracker、Guest Kernel、网络和快照目录。它会说明准备执行的配置;默认需要明确同意,传入--yes才会自动确认。
安装脚本和二进制具有主机级权限。正式服务器应从forkd Releases 确认版本与发布资产,再在隔离测试机执行。
手动检查
forkd doctor
forkd doctor覆盖KVM、硬件虚拟化、cgroup v2、IP Forward、Tap、Network Namespace、Firecracker版本、磁盘、Guest Kernel、Controller连接以及Live Fork所需能力。
随后可拉取官方示例快照并启动三个子机:
forkd pull deeplethe/langgraph-react
sudo -E forkd fork --tag langgraph -n 3 --per-child-netns
也可以从Docker镜像构建自己的预热快照:
sudo -E forkd from-image python:3.12-slim \
--tag py-numpy \
--extra python3-numpy
sudo -E forkd fork --tag py-numpy -n 5 --per-child-netns
from-image第一次运行需要拉取镜像、制作ext4、启动预热并保存快照。后续启动会复用已经生成的内容。
🧪 CLI、SDK与MCP用法
创建100个隔离子机
sudo bash scripts/netns-setup.sh 100
sudo forkd snapshot --tag pyagent \
--kernel ./vmlinux-6.1.141 \
--rootfs ./python-rootfs.ext4 \
--tap forkd-tap0
sudo -E forkd fork \
--tag pyagent \
-n 100 \
--per-child-netns \
--memory-limit-mib 256
sudo forkd eval \
--child forkd-child-42 \
-- "numpy.zeros(100).sum()"
Python SDK
pip install forkd
from forkd import Sandbox
with Sandbox() as sb:
result = sb.commands.run("uname -a")
print(result.stdout)
print(sb.eval("numpy.zeros(5).tolist()"))
eval()复用Guest内已预热的PID 1解释器;commands.run()会启动新进程。官方示例中,两者分别用于低延迟表达式和普通Shell命令。
TypeScript SDK
npm install @deeplethe/forkd
import { Controller } from '@deeplethe/forkd';
const ctrl = new Controller();
const [parent] = await ctrl.spawnSandboxes({
snapshotTag: 'pyagent',
n: 1,
perChildNetns: true,
liveFork: true,
});
const branch = await ctrl.branchSandbox(parent.id, {
mode: 'live',
wait: false,
});
SDK默认读取FORKD_URL和FORKD_TOKEN。Token应通过Secret或权限受控的环境文件注入,避免写入仓库。
MCP Server
pip install forkd-mcp
Claude Desktop配置示例:
{
"mcpServers": {
"forkd": {
"command": "forkd-mcp"
}
}
}
MCP Server向Agent暴露创建沙箱、执行命令和运行代码等工具。生产环境应限制可用快照、网络出口、命令权限和最大子机数量。
📊 基准怎么看

项目在Ubuntu 24.04、Linux 6.14、20 vCPU、30 GiB内存和KVM主机上测试100个沙箱。测试任务是在每个子机中使用已经预热的NumPy运行简单表达式。
| 指标 | forkd官方测试值 |
|---|---|
| 100个子机总启动时间 | 101ms |
| 每个子机新增内存 | 0.12 MiB |
| 单沙箱复用预热解释器 | 1ms |
| 新进程重新导入NumPy | 96ms |
这些数字描述的是“从预热快照分叉”,与容器或虚拟机冷启动属于不同工作点。主机CPU、磁盘、父快照大小、Network Namespace创建、脏页比例和子任务负载都会改变结果。
本机测量可使用:
forkd bench --tag py-numpy --n 5
v0.5加入Diff Snapshot Chain。多层快照可以减少重复保存完整基础镜像,但链越深,校验和组装成本越高。README给出的512 MiB测试中,深度3的启动p50达到1,668ms,而压平后的等价快照约746ms。长期运行应监控链深,并按需要执行:
forkd snapshot-info py-numpy
forkd snapshot-compact --from py-pandas --to py-pandas-flat
🔐 生产部署与已知限制
Controller Daemon适合持续运行的环境:
sudo install -m 0644 \
packaging/systemd/forkd-controller.service \
/etc/systemd/system/
sudo mkdir -p /etc/forkd
sudo bash -c 'head -c 32 /dev/urandom | base64 > /etc/forkd/token'
sudo chmod 600 /etc/forkd/token
sudo systemctl enable --now forkd-controller
REST调用示例:
TOKEN=$(sudo cat /etc/forkd/token)
curl -H "Authorization: Bearer ${TOKEN}" \
-X POST http://127.0.0.1:8889/v1/sandboxes \
-H 'Content-Type: application/json' \
-d '{
"snapshot_tag": "pyagent",
"n": 5,
"per_child_netns": true,
"memory_limit_mib": 256
}'
不要把Controller的8889端口直接暴露到公网。需要远程访问时,应放在受控内网或反向代理之后,并配置TLS、Bearer Token、来源限制和请求速率限制。
当前生产缺口包括:
- 一个Daemon只管理一台主机,尚无内置多节点调度;
- 子Network Namespace默认共享MASQUERADE出口,默认拒绝式Egress需要自行配置iptables;
- 已有
memory.max,CPU、IO和进程数量配额仍需额外处理; - 项目尚未完成第三方安全审计;
- 快照不能跨Firecracker版本或不同CPU微架构随意迁移;
- Live Branch依赖项目维护的Firecracker分支;
- 0.1.0至0.1.3存在路径穿越和占位Token相关安全问题,旧版本必须升级。
⚠️ microVM隔离能提高边界强度,不能自动解决凭据泄露、恶意出网、资源耗尽和内核漏洞。运行不受信代码时,需要同时限制Secret、网络、CPU、内存、进程数、磁盘和执行时间。
❓ FAQ
forkd能替代Docker吗?
forkd面向大量短生命周期、从预热状态分叉的隔离任务。长期服务、标准OCI交付和跨平台开发仍适合Docker。两者可以组合使用:先从Docker镜像制作父快照,再由forkd分叉子机。
云服务器都能安装吗?
主机必须提供/dev/kvm。裸金属服务器通常更直接;虚拟机实例需要平台明确支持嵌套虚拟化。Kubernetes节点同样需要KVM和cgroup v2。
为什么需要Network Namespace?
它为每个子机创建独立网络空间,降低不同Agent之间的网络状态冲突。生产环境还要为每个Namespace增加出口白名单和流量审计。
适合哪些Agent任务?
代码解释器、SWE-bench式并行评测、浏览器自动化、一次任务一个数据库、CI运行不受信代码,以及在高风险步骤前建立分支都符合它的设计目标。
还可以参考哪些方案?
理解Agent与硬件的标准化连接,可阅读MHS控制物理设备 ;多模型路由和普通API工作流可参考本地AI网关搭建 。需要为Agent接入独立模型API时,可查看APIMart API入口 ,模型可用性和费用以实时页面为准。
