Kibotos

Sandbox 与生命周期

用 E2B SDK 在 Kibotos 上创建、暂停、恢复、延期和删除 sandbox,调用与 E2B 相同。本页介绍各个生命周期调用在 Kibotos 上的行为、新 sandbox 得到的资源、到期时间与 Idempotency-Key 重试的规则,以及查询返回的内容。

概述

每个 sandbox 在 Kibotos 里是一个 Workspace给 AI Agent 用的完整 Linux 环境,运行在独立的 MicroVM 里。Agent 在里面读写文件、运行进程、启动服务,不会影响宿主机和其他 Workspace。。生命周期调用对应下面这些接口:

SDK 调用接口在 Kibotos 上
Sandbox.createPOST /sandboxes按部署设定的资源创建 sandbox,见创建 sandbox
getInfo()GET /sandboxes/{id}返回实际生效的配置,见 sandbox 信息
SDK 的列表调用GET /v2/sandboxes列出 sandbox,包括暂停中的
sandbox.kill()DELETE /sandboxes/{id}删除 sandbox。用 volumeMounts 挂载的独立 Volume 保留;创建时没带 volumeMounts 的 sandbox,它的 /data Volume 随之删除。见 Volume
sandbox.pause()POST /sandboxes/{id}/pause冷暂停,见暂停与恢复
Sandbox.connectPOST /sandboxes/{id}/connect恢复暂停中的 sandbox,有效期只延长不缩短
sandbox.setTimeoutPOST /sandboxes/{id}/timeout设置到期时间,可延长也可缩短,见到期时间
无POST /sandboxes/{id}/refreshes延长有效期,至少 15 秒

本页的示例省略了连接选项(apiKey、domain、apiUrl),写法见 E2B 兼容里的示例。

创建 sandbox

创建一个有效期十分钟、到期时暂停而不是删除的 sandbox:

import { Sandbox } from 'e2b';

const sandbox = await Sandbox.create('kibotos-minimal', {
  timeoutMs: 10 * 60_000,
  lifecycle: { onTimeout: 'pause', autoResume: false },
});
  • sandbox 运行起来后请求返回 201,最长等待 90 秒。到时仍未运行的返回 502,这个 sandbox 之后仍可能启动。用同一个 Idempotency-Key 重试,等待的是这个 sandbox,不会再创建一个,见用 Idempotency-Key 重试。
  • 请求体超过 1 MiB 时返回 400。
  • 资源取自部署配置,而不是请求,见资源。
  • 没有 node 能放置时,创建返回 503,见容量不足。
  • sandbox 的有效期见到期时间。

metadata 与选项的大小

网关把 metadata 与 E2B 选项存进 ctrl,因此受 ctrl 的合计上限约束:

上限值计入
annotations 合计262144 字节metadata 的 JSON 原文,加上 maskRequestHost 等其他 annotation 的 key 与 value
labels 合计65536 字节每个 metadata 条目的 label(key 超过 63 字符或不合 label 规则时按 48 字符摘要计),加上命名空间、token、布尔选项等其他 label 的 key 与 value

超出任一上限时,创建返回 400,不创建 sandbox。

资源

E2B 的创建请求不带资源字段,网关按部署参数为每个新 sandbox 申请资源:

资源网关配置默认值
CPUKIBOTOS_E2B_DEFAULT_CPU_MILLIS1 核
内存KIBOTOS_E2B_DEFAULT_MEMORY_BYTES1 GiB
根文件系统的可写空间KIBOTOS_E2B_DEFAULT_DISK_BYTES5 GiB
  • cpuCount、memoryMB、diskSizeMB 回显 sandbox 实际得到的值。
  • diskSizeMB 是 node 确认过的可写空间。sandbox 正在启动、或从未成功放置时还没有确认的值,GET /sandboxes/{id} 与列表接口照常返回它,diskSizeMB 为 0。E2B 要求这个字段是非负整数、不能为空,上游缺少这个值时同样返回 0。
  • 可写空间从放置起占用 node 存储池的容量,实际写入的数据才占用磁盘。存储池小的部署要按 sandbox 数量调小这个值。
  • 配置只影响之后创建的 sandbox,已有 sandbox 的可写空间不变。

部署方按安装 E2B 网关设置这些变量。

暂停与恢复

暂停一个 sandbox,再恢复它:

await sandbox.pause();
const resumed = await Sandbox.connect(sandbox.sandboxId);

在 Kibotos 上,暂停是「冷暂停」:网关调用 Kibotos 的 StopWorkspace 停止 sandbox,恢复时调用 StartWorkspace 重新启动。这是 Kibotos 明确选择的语义。

暂停后保留 sandbox ID 和 Volume(默认挂在 /data)。恢复时重新启动一个新的执行,envd token 与 traffic token 不变。

警告

内存和运行中的进程不保留。根文件系统的修改只是尽力保留,不能当作完整的磁盘快照。需要保留的文件写入 Volume。

暂停

POST /sandboxes/{id}/pause 执行冷暂停:

  • 空请求体、memory:true、memory:false 都执行冷暂停。SDK 的 pause() 默认发送 memory:true,网关同样按冷暂停处理,不声称支持内存暂停。
  • 确认 sandbox 已停止后返回 204。
  • 重复暂停返回 409,SDK 把它转换为返回 false。
  • 暂停会清除到期时间,见到期时间什么时候变化。

恢复

POST /sandboxes/{id}/connect 的结果取决于 sandbox 的状态:

sandbox 状态结果
运行中,或仍在启动运行起来后返回 200。到期时间只延长不缩短,见到期时间
已暂停,或上次因可重试的原因失败启动它并设置本次的有效期,等待启动完成后返回 201
已暂停,且没有 node 能放置503,消息含 resource_exhausted。sandbox 仍是暂停,见容量不足
90 秒内没有运行起来502。启动之后仍可能完成,用同一个 Idempotency-Key 重试
因不可重试的原因失败,或在等待期间失败409,消息以 sandbox failed: 开头
已失败且仍占着上次的执行,包括放置失败后 Kibotos 没能释放 node 的少数情况409,Kibotos 拒绝再次启动。运维用 kibo workspace stop --force 停止它之后,connect 即可恢复

返回的 token 与创建时相同。与 E2B 一致,connect 不轮换 token。

意外的暂停、重启与失败

情形sandbox 状态怎样处理
宿主内存耗尽,sandbox 被内核杀掉暂停connect 即可恢复。与主动暂停一样,内存和进程不保留,最后的写入可能丢失
guest 自己关机暂停connect 即可恢复
guest 自己重启仍是 running,查询与 connect 照常成功envd 与应用端口的请求在 guest 回来之前失败,重试即可。内存和进程不保留
其他原因意外结束,例如 VMM 故障失败,不会自行恢复connect 返回 409,查询与暂停返回 502,列表不列出它,重试都不会成功。运维用 kibo workspace stop --force 停止它之后,connect 即可恢复

Kibotos 怎样处理这些情形、适用哪些后端,见服务端自行处理的停止与重启。

容量不足

启动时没有 node 能放置 sandbox(例如所有 node 内存都紧张),这次 connect 返回 503,消息含 resource_exhausted。其他接口遇到容量不足(例如创建 sandbox 或 Volume)同样返回 503。

  • 这样的 sandbox 与上游 E2B 恢复失败时一样仍是暂停:查询返回 state: paused,列表按暂停列出,再次暂停返回 409。容量恢复后再次 connect 即可启动它,不需要运维介入。
  • 创建时就没能放置的 sandbox 也按暂停列出。用 metadata 找到它,再 connect 启动或删除。
  • 启动失败后的到期时间见启动失败之后。

通过应用端口自动唤醒(autoResume)、快照与克隆目前不可用,见不支持的能力。

到期时间

让运行中的 sandbox 在十分钟后到期:

await sandbox.setTimeout(10 * 60_000);

各请求设置到期时间的方式不同:

请求效果
create按请求的 timeout 设置有效期。JS SDK 总会发送 timeout,不设 timeoutMs 时是 5 分钟;请求不带 timeout 时用网关的 KIBOTOS_E2B_DEFAULT_TIMEOUT,默认 1 小时。倒计时从 ctrl 接受命令开始,包含创建耗时
connect只延长:新的 endAt 是现有到期时间与「now + 请求的 timeout」中较晚的那个。恢复时设置本次的有效期,从 ctrl 接受启动命令时开始计算,启动耗时算在其中
timeout按请求值设置到期时间,既可延长也可缩短
refreshes只延长,至少 15 秒(E2B 的 SandboxTimeoutDefault)。duration 缺省、小于 15 秒或不是正数,都按 15 秒处理

到期动作

创建选项到期时
不设置,或 lifecycle.onTimeout: 'kill'删除 sandbox
autoPause: true(SDK 的 lifecycle.onTimeout: 'pause')暂停 sandbox,而不是删除
  • timeout 与 connect 保持创建时设置的动作。
  • 没有开启 autoPause 时,恢复后的 sandbox 到期仍是删除。
  • autoPauseMemory 的两个取值都按冷暂停处理。只设置 autoPauseMemory 而没有开启 autoPause 返回 400。

timeout 的取值

  • timeout 的取值与 E2B 相同:正整数是秒数;0 与负数都表示立即到期。E2B 用 endAt = now 表达,网关用最短的正期限表达,因为 ctrl 只接受正的到期时长。
  • connect 与 timeout 的请求字段在 E2B 里是必填,缺失时按 0 处理。只有 create 可以省略。
  • 对 connect 来说,0、负数与缺失字段请求的都是「现在」,因此保持原值。请求的 timeout 比剩余时间短时保持原值,不推进原生的到期 revision。这与 E2B 相同,connect 只增不减。
  • 部署可以用 KIBOTOS_E2B_MAX_TIMEOUT 限制单次请求的时长。create 与 connect 超过上限时返回 400,与 E2B 在团队上限处的位置相同;timeout 与 refreshes 不做这个检查,E2B 也不做。

到期时间什么时候变化

  • 这些请求都在原生的到期设置更新成功后才返回成功。inspect 与 list 返回的 endAt 直接来自原生的到期时间。
  • 访问文件与执行命令不会改变有效期。
  • 暂停或恢复时,到期时间和状态变化在同一次原生调用中提交。暂停成功的 sandbox 没有到期时间,之前设置的删除动作不会在暂停期间触发;启动成功的 sandbox 一定带有本次的到期时间。启动失败是例外,见启动失败之后。
  • 到期动作由 ctrl 执行,网关没有自己的定时器。网关停止不影响已设置的到期时间。
  • ctrl 暂时不可用时延期会失败,恢复后 ctrl 按已保存的时间执行到期动作。
  • ctrl 已开始执行到期动作后,不能再通过延期取消。

启动失败之后

  • 恢复前没有到期时间的 sandbox(例如暂停中的),恢复失败后仍没有到期时间,超过这次请求的 timeout 也不会被暂停或删除。
  • 启动命令在 ctrl 接受时就写入了本次的到期时间,网关在启动失败后再发一次原生调用清除它。网关在这两次调用之间退出时,这个到期时间会保留。
  • 创建时就没能放置的 sandbox 保留创建时的到期时间,到期后按创建时的设置删除;对它的 connect 失败时,到期时间换成这次请求设置的。

用 Idempotency-Key 重试

create、connect、pause、timeout、refreshes、修改网络和删除支持 Idempotency-Key 头。同一个 key 的请求内容必须相同。key 超过 256 字节时返回 400。

结果未知时(例如请求中断后),用同一个 key 重试。网关先向 ctrl 查这条命令是否已经提交:已提交就等它完成并返回结果,未提交才重新发起。

  • Idempotency-Key 的值不是 Kibotos 的幂等键(command ID)调用方为每个写请求生成的稳定标识。用同一个幂等键重发请求,操作不会执行两次。。网关把它与命名空间、操作和 sandbox 一起推导出幂等键,同一个值用在不同操作上会得到不同的幂等键,不能拿它去原生 API 查询命令。
  • 幂等键由 key 推导,网关不保存任何东西。以上都不依赖网关本地状态,换一台网关实例重试同样成立。
  • 同一个 key 换了请求内容,ctrl 判为冲突,网关返回 409。
  • 删除与 refreshes 同样按 key 推导幂等键,重试时等待同一条命令完成。
  • 版本冲突返回 409。网关不会读取新版本后重试旧请求,需要基于当前状态发起新请求。

sandbox 信息

GET /sandboxes/{id} 与列表接口返回实际生效的配置。与生命周期有关的字段:

字段回显规则
lifecycle到期动作为删除时返回 {"onTimeout":"kill","autoResume":false},为暂停时返回 onTimeout:"pause"。暂停中的 sandbox 没有到期时间,回显的是下次启动将使用的设置
endAt直接来自原生的到期时间
cpuCount、memoryMB、diskSizeMBsandbox 实际得到的值,见资源

SDK 2.46.1 的 getInfo() 保留这些字段以及网络、端口与 Volume 的字段。SDK 的列表调用只保留 volumeMounts,其他字段需要通过 getInfo() 读取。

其他字段的回显规则在各自的页面:网络字段见网络,allowPublicTraffic 与 maskRequestHost 见应用端口,volumeMounts 见 Volume。

注意

  • sandbox 的实际状态与到期时间以原生 API 的查询结果为准。

下一步

  • 命令与文件:在 sandbox 里执行命令、传输文件。
  • Volume:跨暂停、在 sandbox 删除后保留数据。
  • 网络:控制出网访问。
  • 到期时间:Workspace 的到期时间怎样工作。

本页内容