Skip to main content

休眠与唤醒

OpenKruise Agents 允许将运行中的沙箱 休眠(pause),使其停止消耗 CPU / 内存;之后再 唤醒(resume),回到运行态。整个过程中沙箱身份保持不变(同一个 sandboxID、同一个 Pod)。

⚠️ 该能力仍在持续演进。底层的捕获机制(是否保留内存状态、是否对文件系统做检查点等)依赖集群环境(例如内存态保留目前仅在阿里云 ACS 支持)。本文只介绍如何使用 API;关于状态保留的具体保证请参考平台运维手册。

概述

提供两种并列的接入方式,底层操作的都是同一个 Sandbox 资源:

接入方式面向的使用者典型场景
E2B SDK(pause / connect)基于 E2B Python / JavaScript SDK 的应用代码在空闲时编程式休眠、按需唤醒
Kubernetes CRD集群运维、声明式 GitOps、kubectl 或自定义控制器切换 spec.paused 或配置 spec.pauseTime

休眠 / 唤醒是 一对一 的:整个 pause → resume 过程中,沙箱 ID 保持不变。若需要「快照后克隆多个新沙箱」这种一对多的工作流,请参考 快照管理

工作原理(简述)

  1. 休眠(Pause):冻结沙箱 Pod。所有活动的 WebSocket / PTY / 命令流连接都会断开,客户端需要在唤醒后重连。
  2. 唤醒(Resume):将 Pod 恢复为运行态。沙箱 ID 保持不变。
  3. 捕获的具体范围(内存 / 文件系统)取决于运行时平台以及其背后 SandboxSpec 的配置。

休眠沙箱

E2B SDK 在沙箱句柄上暴露了 pause() 方法,底层调用 POST /sandboxes/{sandboxID}/pause

from e2b_code_interpreter import Sandbox

with Sandbox.create(template="code-interpreter", timeout=300) as sbx:
sbx.run_code("a = 1")
sbx.pause() # 沙箱进入 paused 状态;sandboxID 保持不变
import { Sandbox } from 'e2b'

const sbx = await Sandbox.create({ template: 'code-interpreter', timeoutMs: 300_000 })
await sbx.betaPause()

注意事项:

  • 对非 running 状态的沙箱执行 pause 会返回 409 Conflict
  • 休眠沙箱的存活时间与运行态 timeout 分开控制。sandbox-manager 默认使用 forever 休眠保留策略;如需设置更短的 保留窗口,请参考保留休眠沙箱

自动休眠(Auto Pause)

除了显式调用 pause,还可以在创建沙箱时声明 到期自动进入 paused——到时间后沙箱不会被销毁,而是转为 paused 状态,保留身份等待后续唤醒。

参考 E2B 官方文档 - Auto-pause:创建沙箱时将 lifecycle.on_timeout 设为 "pause"

from e2b_code_interpreter import Sandbox

sbx = Sandbox.create(
template="demo",
timeout=600, # 10 分钟;到期后进入 paused,而不是被删除
lifecycle={
"on_timeout": "pause",
"auto_resume": False, # 见下方说明
},
)
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.create({
template: 'demo',
timeoutMs: 10 * 60 * 1000, // 10 分钟;到期后进入 paused
lifecycle: {
onTimeout: 'pause',
autoResume: false, // 见下方说明
},
})

⚠️ 当前 OpenKruise Agents 尚未实现 auto_resume 即使将其显式设为 true,休眠中的沙箱也 不会 被自动唤醒;客户端仍需在需要时显式调用 Sandbox.connect(sandbox_id, ...)(见下一节)。建议显式写为 false 以表明语义。

保留休眠沙箱

reserve-paused-sandbox-duration 用于控制一个带 timeout 的 Sandbox 在 实际执行 pause 转换后 继续保留多久。 Sandbox 休眠时,OpenKruise Agents 会按下面的方式重新计算 spec.shutdownTime

pause 转换执行时间 + reserve-paused-sandbox-duration

该值必须是正数 Go duration,例如 30m2h168h。特殊值 forever 表示内置的 100 年 保留窗口,并不是真正无限期的 deadline。0、负数以及 1d 都是非法值 (time.ParseDuration 不支持 d 单位)。

该策略只会重新计算已有的 timeout。通过 never-timeout 扩展创建的 Sandbox 没有 shutdownTime,休眠保留策略不会 为其创建 deadline。

创建时通过 e2b.agents.kruise.io/reserve-paused-sandbox-duration metadata 扩展设置持久化保留策略。 该策略同时适用于自动休眠和后续的手动休眠:

from e2b_code_interpreter import Sandbox

sbx = Sandbox.create(
template="demo",
timeout=600,
lifecycle={"on_timeout": "pause", "auto_resume": False},
metadata={
"e2b.agents.kruise.io/reserve-paused-sandbox-duration": "2h",
},
)

手动 pause 时,可以通过 x-e2b-kruise-reserve-paused-sandbox-duration 请求头覆盖持久化值。 当该请求实际执行 running → paused 转换时,成功接受的覆盖值会持久化,供后续 pause 操作继续使用:

sbx.pause(
headers={
"x-e2b-kruise-reserve-paused-sandbox-duration": "30m",
}
)

取值优先级为 pause 请求头 → 已持久化策略 → forever 默认值。创建 metadata 或 pause 请求头包含非法值时, sandbox-manager 会返回 400 Bad Request。由 manager 创建且未显式设置该值的 Sandbox 使用 forever,并将其 持久化到内部注解 agents.kruise.io/reserve-paused-sandbox-duration

唤醒沙箱

E2B SDK 侧 推荐 使用 Sandbox.connect(...)——它会隐式地唤醒一个休眠中的沙箱,同时刷新其 timeout。遗留的 resume 端点仅出于向后兼容而保留,新代码不应再使用。

from e2b_code_interpreter import Sandbox

sbx = Sandbox.connect(sandbox_id, timeout=300) # 如果休眠则唤醒,并刷新 timeout
sbx.run_code("print(a)")
import { Sandbox } from 'e2b'

const sbx = await Sandbox.connect(sandboxId, { timeoutMs: 300_000 })

注意事项:

  • 若沙箱已经在运行,connect 只会刷新 timeout,并且是 只延长(extend-only) 策略:永远不会缩短剩余时间。(例外:paused → running 的唤醒会直接采用请求的 timeout。)
  • 对不存在或不属于当前 API-key 用户的沙箱调用 connect 会返回 404 Not Found

能力矩阵

能力E2B SDKKubernetes CRD
休眠运行中的沙箱sbx.beta_pause()spec.paused: true
唤醒休眠中的沙箱Sandbox.connect(id, ...)spec.paused: false
到 timeout 时自动触发 pauselifecycle.on_timeout='pause'
在绝对时间点自动触发 pausespec.pauseTime
自动唤醒(auto-resume)❌ 暂不支持❌ 暂不支持
配置进入 paused 后的删除时间✅ 创建 metadata 或 pause 请求头✅ 自动休眠使用注解;手动休眠写 spec.shutdownTime
唤醒的同时设置 / 刷新 timeoutSandbox.connect(id, timeout=...)✅ 同一次 patch 中写 spec.shutdownTime / spec.pauseTime
运行态下对 timeout 的只延长(extend-only)保护❌ 用户写入值可缩短
观察 paused / running 状态通过 SDK 响应status.phasePaused / Running

如果你需要「只延长、永不缩短」的 timeout 刷新语义,请走 E2B SDK;CRD 路径更适合声明式 / GitOps 批量管控「暂停 / 运行 + 绝对时间」的场景。

注意事项

  • 连接会断开。 休眠时 Pod 被冻结,所有活动连接(WebSocket / PTY / 命令流)都会断开,客户端需要在唤醒后重连。
  • 休眠期间的生命周期。 运行态 timeout 不会在休眠后原样继续倒计时;自动删除由 spec.shutdownTime 控制, 休眠保留策略可以基于 pause 转换执行时间重新计算它。
  • 旧版 SDK。 遗留的 POST /sandboxes/{sandboxID}/resume 端点仅为旧版 SDK 兼容保留。新代码一律使用 Sandbox.connect(...)
  • 状态保留取决于平台。 跨休眠/唤醒是否保留内存状态依赖具体的运行时平台。如果你需要显式的内存 + 文件系统快照、并且希望能克隆出全新沙箱,请使用 快照管理