forkd REST API完全参考:Controller守护进程全端点、认证、TLS与Prometheus监控详解
【免费下载链接】forkd高性能Agent沙箱,预热虚拟机可以在约 100 毫秒内派生出 100 个独立实例;运行过程中约 150 毫秒“分叉”出一个新的运行环境。底层使用 KVM 隔离,并利用快照+写时复制降低资源开销。项目地址: https://gitcode.com/deeplethe/forkd
forkd 是一个高性能 Agent 沙箱系统,通过快照+写时复制(Copy-on-Write)技术让预热虚拟机在约 100 毫秒内派生 100 个独立实例。forkd Controller 守护进程对外暴露一套 REST API(默认127.0.0.1:8889),本文带你从启动、认证、TLS 加密到每一个 v1 端点与 Prometheus 监控指标,完整读懂这套 API。
一、认识 Controller:forkd 的"控制平面" 🎛️
你可以把 forkd 想象成一套"虚拟机流水线":
- 快照(Snapshot):把一台预热好的虚拟机冻结成
vmstate + memory.bin文件,作为"母版"; - 沙箱(Sandbox):从母版快速恢复出的独立子虚拟机,彼此完全隔离(KVM 级别);
- 分支(Branch):运行中的沙箱暂停约 150 毫秒,复制出新母版再恢复运行。
所有这些操作都通过forkd Controller 守护进程的 REST API 驱动,CLI、Python SDK 都是它的"客户端"。官方端点文档见 docs/API.md,路由实现在 crates/forkd-controller/src/http.rs。
二、一键启动:默认配置与安全底线
默认启动方式(参考 crates/forkd-controller/src/main.rs):
forkd-controller serve \ --bind 127.0.0.1:8889 \ --state /var/lib/forkd/state.json \ --audit-log /var/log/forkd/audit.log \ --token-file /etc/forkd/token几个关键默认值:
| 配置项 | 默认值 | 说明 |
|---|---|---|
--bind | 127.0.0.1:8889 | 仅回环地址,本地单租户可用 |
--state | /var/lib/forkd/state.json | 快照/沙箱注册表,自动创建 |
--audit-log | /var/log/forkd/audit.log | 每请求一行 JSON 的审计日志 |
--token-file | 未设置 | 不设则免认证(仅限回环) |
| BRANCH 并发上限 | 4 | 可用--branch-concurrency调整 |
🔒安全底线(fail closed):如果绑定到非回环地址(如0.0.0.0:8889)却没给--token-file,守护进程会直接拒绝启动,避免裸奔。这个校验逻辑就在 crates/forkd-controller/src/lib.rs。
三、认证详解:Bearer Token 三步走 🔐
启用认证只需两个动作:
- 守护进程侧:把令牌写入文件并传给
--token-file。令牌要求:非空、至少 16 字节高熵随机值;占位符(REPLACE_ME/CHANGE_ME开头)会被直接拒绝; - 客户端侧:每个请求带上请求头:
curl -H "Authorization: Bearer <token文件内容>" \ http://127.0.0.1:8889/v1/sandboxes- 例外:
/healthz永远免认证(/healthz/带尾斜杠也可以),这样负载均衡器和 K8s 探活不需要持有凭证。
认证中间件实现在 crates/forkd-controller/src/auth.rs,有两个值得新手留意的细节:
- 令牌比较采用constant-time 比较(
subtle::ConstantTimeEq),杜绝"响应时间暴露令牌长度"的时序侧信道; - 令牌在启动时读取一次,轮换令牌需要重启守护进程。
所有 401 响应都返回统一格式:
{ "error": "missing bearer token" }四、TLS 加密:两条 PEM 文件开启 HTTPS 🌐
想让 API 走 HTTPS(多租户或跨主机部署的推荐姿势),只需成对提供:
forkd-controller serve \ --bind 127.0.0.1:8889 \ --tls-cert /etc/forkd/cert.pem \ --tls-key /etc/forkd/key.pem- 两个参数必须成对出现,只给其一会报错退出;
- 底层使用 rustls(aws-lc-rs 加密提供器),配置加载见 crates/forkd-controller/src/lib.rs;
- 建议配合 Bearer Token 双保险使用,K8s 部署示例见 packaging/k8s/forkd-controller.yaml。
部署前建议先跑一次forkd doctor,它会检查内核版本、UFFD_WP、memfd、HugePages 等 14 项前置条件,一眼确认你的主机是否满足live_fork等高级 API 的能力要求:
五、v1 全端点速查表 📋
API 采用/vN前缀做版本管理,破坏性变更会进入新前缀,旧主版本并行支持一个小版本。当前 v1 共 20 个端点:
5.1 状态与发现端点
| 方法 | 路径 | 说明 | 认证 |
|---|---|---|---|
| GET | /healthz | 存活探针,恒返回{"ok":true} | 免认证 |
| GET | /version | 返回构建版本与 API 版本 | 需要 |
| GET | /metrics | Prometheus 文本格式指标 | 需要 |
5.2 快照端点(Snapshot)
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /v1/snapshots | 用 kernel + rootfs 启动母版机、等待用户态预热后做快照 |
| GET | /v1/snapshots | 列出全部已注册快照 |
| DELETE | /v1/snapshots/:tag | 删除快照;链式快照支持?cascade=true(递归删整棵子树)或?force=true(孤立化子节点),二者互斥 |
| GET | /v1/snapshots/:tag/info | v0.5 链信息:链深度、父哈希、磁盘占用、依赖者列表 |
| POST | /v1/snapshots/:tag/compact | 把多层 diff 链压平为无父的独立快照(原子落盘,中断不残留半成品) |
POST /v1/snapshots的核心参数:tag(1–64 位字母/数字/-/_)、kernel、rootfs、tap、boot_wait_secs(≤60,默认 10 秒预热窗口)。
5.3 沙箱端点(Sandbox)——一次 fork 100 台 🚀
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /v1/sandboxes | 从快照 tag fork N 个子沙箱(1 ≤ n ≤ 1000) |
| GET | /v1/sandboxes | 列出活跃沙箱 |
| GET | /v1/sandboxes/:id | 单个沙箱元数据 |
| DELETE | /v1/sandboxes/:id | 终止沙箱并清理 cgroup,返回 204 |
| POST | /v1/sandboxes/:id/ping | 与 Guest 内 agent 往返,验证存活 |
| POST | /v1/sandboxes/:id/exec | 在沙箱内起子进程(可设timeout_secs) |
| POST | /v1/sandboxes/:id/eval | 在已预热的 Python 解释器(PID 1)里求值表达式 |
创建请求中最常用的开关:
per_child_netns: true—— 每个子 VM 独占网络命名空间(需先运行 scripts/netns-setup.sh 预配池);memory_limit_mib—— 通过 cgroup v2memory.max限制内存;live_fork: true—— 以 memfd 支撑内存启动,为后续mode: "live"分支铺路(要求 Linux ≥ 5.7);prewarm: true—— 恢复后立即做一次丢弃型快照,把首次 BRANCH 的冷缓存惩罚(2–9 倍)摊平到创建阶段。
一次 API 调用批量派生 100 个沙箱的实测曲线(每沙箱内存占用与累计耗时):
5.4 BRANCH 分支端点:150 毫秒"分身" ⚡
POST /v1/sandboxes/:id/branch是 forkd 的灵魂端点:暂停运行中的沙箱 → 快照其内存与 vmstate 为新 tag → 恢复运行。三种模式:
mode | 暂停窗口 | 原理 |
|---|---|---|
"full" | 0.5–8 s | 暂停期内写完整 guest RAM |
"diff" | ~200 ms(空闲源) | 只写脏页,完整镜像异步重建 |
"live" | 子 50 ms | UFFD_WP 异步捕获脏页,需live_fork: true启动 |
两个高频选项:
tag可省略,守护进程自动生成branch-<源id>-<时间戳>-<hex>;wait: false(仅 live 模式)——源恢复(约 10 ms)立即返回,快照状态为"writing",后台拷贝完成后翻转为"ready",轮询GET /v1/snapshots即可感知。
同一 tag 的并发 BRANCH 会收到409 Conflict;超过并发上限(默认 4)返回503 Service Unavailable。不同模式的暂停窗口对比实测:
5.5 Workspace 端点:可挂起的有状态工作区 📦
Workspace 是"快照 tag + 名字"的封装,支持跨守护进程重启的 suspend/resume:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET / POST | /v1/workspaces | 列出 / 创建(创建即拉起一个运行中沙箱) |
| GET / DELETE | /v1/workspaces/:name | 查询 / 删除(连带清理其状态快照) |
| POST | /v1/workspaces/:name/suspend | 挂起到ws-<name>-state状态 tag,可选diff: true加速写入 |
| POST | /v1/workspaces/:name/resume | 从最近状态快照恢复运行 |
状态机为running → suspended → running;守护进程崩溃后状态变为stale,需重新 resume。
六、Prometheus 监控:/metrics 指标清单 📊
GET /metrics输出 Prometheus 文本格式(text/plain; version=0.0.4),指标名保持稳定,可直接被 exporter 依赖:
| 指标 | 类型 | 用途 |
|---|---|---|
forkd_snapshots_total | gauge | 已注册快照数 |
forkd_sandboxes_active | gauge | 活跃子 VM 数 |
forkd_branches_in_flight | gauge | 正在写 memory.bin 的 BRANCH 数 |
forkd_branch_concurrency_cap | gauge | 配置的 BRANCH 并发上限 |
forkd_orphan_firecrackers_detected_total | counter | 检测到孤儿 Firecracker 进程累计次数(可配告警) |
forkd_build_info{version="X.Y.Z"} | gauge | 恒为 1,label 携带构建版本 |
最小 Grafana 告警建议:forkd_orphan_firecrackers_detected_total增长、forkd_branches_in_flight长期贴近 cap 值。
七、审计日志与错误码 📝
每个请求都会向审计日志追加一行 JSON(时间戳、方法、路径、状态码、延迟、来源 IP、UA),实现在 crates/forkd-controller/src/audit.rs。运维要点:
- 日志轮转:rename 文件后向守护进程发送
SIGHUP,它会原子重开路径,不丢记录; - 优雅停机:SIGTERM/SIGINT 触发最多 30 秒的在途请求排空;
- 统一错误体:所有 4xx/5xx 都带
{ "error": "human-readable message" }。
| 状态码 | 典型场景 |
|---|---|
400 Bad Request | tag 非法、mode与diff同时设置、cascade与force冲突 |
401 Unauthorized | 缺 Bearer Token 或令牌不匹配 |
404 Not Found | 快照 tag / 沙箱 id / workspace 名不存在 |
409 Conflict | tag 已存在、快照正在写、删除会破坏 diff 链(未带 cascade/force) |
500 Internal Error | Firecracker 启动/恢复/快照失败 |
503 Service Unavailable | BRANCH 达到并发上限、共享 tap 被占用、netns 池耗尽 |
八、延伸阅读 📚
- 端点契约细节(含请求/响应 JSON 示例):docs/API.md
- 安全设计与威胁模型:docs/SECURITY.md
- 运维手册(systemd 单元:packaging/systemd/forkd-controller.service):docs/RUNBOOK.md
- BRANCH 模式设计推导:docs/design/branching.md
- 暂停窗口实测数据:bench/pause-window/RESULTS-v0.3.md
💡 小贴士:本地单租户开发可直接用默认回环免认证模式;只要计划把 API 暴露到局域网或 K8s 集群,请始终成对启用
--token-file与 TLS。
【免费下载链接】forkd高性能Agent沙箱,预热虚拟机可以在约 100 毫秒内派生出 100 个独立实例;运行过程中约 150 毫秒“分叉”出一个新的运行环境。底层使用 KVM 隔离,并利用快照+写时复制降低资源开销。项目地址: https://gitcode.com/deeplethe/forkd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考