Kibotos

生命周期

用 Go SDK、E2B SDK 或 kibo 停止、启动和删除 Workspace。Go 示例里的 settleOptions 在 ctrl 回答仍在执行时重发命令,写法见 examples/go/quickstart。本页还介绍强制停止、怎样查看停止或删除释放了什么、FAILED 的 Workspace 怎样恢复,以及服务端在哪些情况下自己停止或重启 Workspace。

各状态下能做的操作

Workspace 能做哪些操作取决于它的状态。各状态的含义与转换见Workspace 的状态。

状态可以做什么
CREATING删除,会取消正在进行的创建
AVAILABLE停止、删除、改网络策略、设置到期时间、撤销数据面访问
STOPPING删除;正常停止卡住时可以改用强制停止
STOPPED启动、删除、调整 CPU 与内存、改可写层大小、换绑 Volume、改网络策略(下次启动生效)、清除到期时间
STARTING删除
FAILED取决于是否还持有执行,见从 FAILED 恢复
UNKNOWN删除;正常停止仍在处理时可以强制停止;其余情况等系统确认结果,或用同一个幂等键重发原来的请求
DELETING等待完成
DELETED只能查询
  • 调整 CPU、内存、可写层大小和 Volume 绑定都要求 Workspace 已停止。
  • 除 DELETED 外,任何状态都可以修改 labels 与 annotations,见 labels 与 annotations。
  • 到期时间到了以后,系统按设置的方式停止或删除 Workspace;没有默认的到期行为,见到期时间。

停止

正常停止 Workspace:

current, err := client.Workspaces().GetWorkspace(ctx, connect.NewRequest(&ctrlv1.GetWorkspaceRequest{WorkspaceId: workspaceID}))
if err != nil {
	log.Fatal(err)
}
request := &ctrlv1.StopWorkspaceRequest{
	Metadata:                   &ctrlv1.CommandMetadata{CommandId: kibotos.NewCommandID("example")},
	WorkspaceId:                workspaceID,
	ExpectedExpirationRevision: current.Msg.GetWorkspace().GetExpiration().GetRevision(),
}
stopped, err := kibotos.Settle(ctx, settleOptions, func(ctx context.Context) (*connect.Response[ctrlv1.StopWorkspaceResponse], error) {
	return client.Workspaces().StopWorkspace(ctx, connect.NewRequest(request))
})
if err != nil {
	log.Fatal(err)
}

在 E2B SDK 里,停止就是暂停,见暂停与恢复。

正常停止先关闭数据面,等待 guest 中的写入完成并同步文件系统,再停止 Instance、释放资源。

  • 应用程序已经交给内核的写入会被同步;仍在应用程序缓冲区中的数据需要应用自己 flush。
  • 绑定的 Volume 与根文件系统的保留可写层(retained layer)都保留,内存与进程不保留。
  • 为这个 Workspace 签发的数据面会话凭证全部失效,它的 Exposure 全部被撤销。下次启动后重新申请凭证、重新创建 Exposure,见公开 URL。
  • 同步失败或结果未知时,正常停止不会强制销毁实例。查询这次停止的结果,停不下来时改用强制停止。

启动

启动已停止的 Workspace:

commandID := kibotos.NewCommandID("example")
started, err := client.Workspaces().StartWorkspace(ctx, connect.NewRequest(&ctrlv1.StartWorkspaceRequest{
	Metadata:                   &ctrlv1.CommandMetadata{CommandId: commandID},
	WorkspaceId:                workspaceID,
	ExpectedExpirationRevision: stopped.Msg.GetWorkspace().GetExpiration().GetRevision(),
}))
if err != nil {
	log.Fatal(err)
}
workspace, err := client.WaitWorkspace(ctx, started.Msg.GetWorkspace(), commandID)
if err != nil {
	log.Fatal(err)
}

启动会创建新的实例,不恢复之前的进程和内存。

  • 它接受 STOPPED 的 Workspace,也接受不持有执行、没有开始过删除的 FAILED Workspace,见从 FAILED 恢复。
  • 创建在建好实例之前失败的 Workspace 也可以启动;失败的原因没有消除时,这次启动会以同样的原因失败。
  • 创建还没建出 Workspace 自己的 Volume 就失败时,启动会把它建出来:Volume ID、存储池与容量都不变。

强制停止

强制停止用于正常停止完成不了的情况,包括停止卡住、FAILED 且仍持有实例:

kibo workspace stop --force "$workspace_id"

它不等 guest 停止写入,只请 guest 做一次短时间同步,然后停止 Instance、释放资源。Workspace 进入 STOPPED,Volume 与可写层都保留,之后可以启动。

警告

这次同步不保证覆盖最后的写入,kibo 显示「not confirmed on disk」。下次启动时文件系统靠日志恢复一致,效果等同一次断电。

  • 强制停止前 kibo 会请求确认,--yes 跳过确认。
  • 与正常停止一样,强制停止让 Workspace 的数据面会话凭证失效,并撤销它的全部 Exposure。
  • 实例的 VMM 已经退出时没有可停的机器,强制停止直接释放实例仍占用的 Volume、网络与可写层挂载,同样进入 STOPPED。
  • 正常停止与到期停止失败时,服务端不会自行改为强制停止。

没有其他命令在处理时,强制停止只接受下面这些 Workspace,其余被拒绝,Workspace 不变:

Workspace强制停止
AVAILABLE接受
STOPPING 或 UNKNOWN,正常停止仍在处理接受。强制停止取代正常停止,原命令以 CANCELLED 失败结束
FAILED,仍持有执行接受,不论失败发生在哪个阶段
FAILED,不持有执行拒绝。直接启动
开始过删除(曾有删除被接受)拒绝。再次删除完成它;这样的 Workspace 也不接受启动与配置修改

删除

删除 Workspace,并等到它变为 DELETED:

commandID := kibotos.NewCommandID("example")
request := &ctrlv1.DeleteWorkspaceRequest{
	Metadata:                   &ctrlv1.CommandMetadata{CommandId: commandID},
	WorkspaceId:                workspaceID,
	ExpectedExpirationRevision: workspace.GetExpiration().GetRevision(),
}
if _, err := kibotos.Settle(ctx, settleOptions, func(ctx context.Context) (*connect.Response[ctrlv1.DeleteWorkspaceResponse], error) {
	return client.Workspaces().DeleteWorkspace(ctx, connect.NewRequest(request))
}); err != nil {
	log.Fatal(err)
}
if err := client.WaitWorkspaceDeleted(ctx, workspaceID, commandID); err != nil {
	log.Fatal(err)
}

delete 在请求确认前会先说明绑定的 Volume 是一起删除还是保留。--yes 跳过确认,没有终端可以提示时必须加。与 stop 一样,delete 默认最多等一小时,结束等待不会取消删除,见等待结果。

删除哪些数据

数据删除 Workspace 时
随 Workspace 新建的 Volume(默认情况,挂在 /data)删除
用 --volume 绑定的已有 Volume默认保留,只解除绑定,数据原样保留
可写层(根文件系统的其余部分)删除
已经为这个 Workspace 签发的凭证全部失效,已打开的连接被关闭

警告

默认情况下,删除 Workspace 会连同它的 Volume 与 /data 里的数据一起删除。要保留 Volume,在 Workspace 停止时修改绑定,或者先导出数据,见创建时的 Volume与导出、导入与恢复。

Volume 是否随 Workspace 删除是绑定的设置,不是 Volume 的种类。创建 Workspace 或绑定 Volume 时用 --delete-with-workspace 设置,见绑定、换绑与解绑 Volume。

什么时候可以删除

  • 除 DELETING 与 DELETED 外,任何状态都可以直接删除。
  • 删除 CREATING 的 Workspace 会取消正在进行的创建。
  • 删除一旦被接受,Workspace 就不再接受启动、强制停止与配置修改。已经开始的删除要完成时,再次删除;Workspace 处于 DELETING 时等它完成。
  • 到期动作为 delete 的到期时间到了以后,Workspace 会被删除,见到期时间。

删除之后

DELETED 的 Workspace 仍能用 kibo workspace get 按 ID 查询。列表默认不包含已删除的 Workspace,加 --include-deleted 才显示,见列表过滤。

要逐项确认运行环境、Volume、可写层等部分是否已经释放,见查看释放情况。

查看释放情况

kibo workspace cleanup-status 查看一个 Workspace 的执行已经释放了哪些部分、还占用着哪些部分。停止或删除之后,用它确认资源是否真的已经释放:

kibo workspace cleanup-status "$workspace_id"

这条命令只读,不触发释放,也不改变状态。

输出包含三部分:

部分内容
总体状态COMPLETE、PROCESSING、NEEDS_ATTENTION 或 UNKNOWN
Components逐项列出执行的各个部分,每项显示状态(RELEASED、PRESENT、PENDING、ISOLATED、UNKNOWN)、读取来源与观测时间
Release只在释放尚未完成时出现,写明这次释放从什么时候起尚未完成,以及最后一次确认执行的时间

怎样看结果

  • Release 一栏里的时间是诊断信息,不是期限:释放仍在重试,Components 一栏说明还占用着哪些部分。
  • 观测本身不完整时,结果的 completeness 为 PARTIAL 或 UNKNOWN,退出码相应是 17 或 18。此时未知的部分不能当作已释放。
  • RETAINED_LAYER 或 VOLUME_DELETION 为 PENDING、来源是控制面状态时,Workspace 已删除,文件等存储池有可用的 node 后删除。总体状态在这期间是 PROCESSING。
  • 存储池被宣告丢失后,这两项是 RELEASED:池里已经没有可以读到的数据。

从 FAILED 恢复

「持有执行」指 Workspace 在某个 node 上还有没释放的 Instance 与资源预留。响应里没有字段直接给出它,所以恢复时不必先判断,按下面的顺序做:

  1. 强制停止。成功时 Workspace 进入 STOPPED。
  2. 启动。第 1 步被拒绝时同样执行这一步:Workspace 本来就不持有执行。
  3. 两步都被拒绝时,重新读取 Workspace,按它当前的状态处理。

常见的 FAILED 与是否持有执行:

情形持有执行
创建或启动失败,ctrl 已经销毁下发过的实例否,直接启动
创建或启动失败,销毁实例也失败是
运行中 VMM 意外退出:被杀、宿主内存不足,或者 guest 内核崩溃、guest 内重启使 VMM 退出是。node 保留这个 Instance,它仍占着 Volume、网络与可写层;强制停止之前启动会被拒绝

guest 卡住而 VMM 仍在运行时,Workspace 保持 AVAILABLE,不进入 FAILED,见 guest 回应情况。

服务端自行处理的停止与重启

宿主内存耗尽由服务端处理,不需要人工介入;guest 自己重启与关机是否也由服务端处理取决于后端:

情形Firecracker 后端KiboVM 后端
guest 自己重启保持 AVAILABLE,在同一台 node 上换一个 VMM。等 guest 回来,重试数据面请求不处理。Workspace 进入 FAILED:复位与 VMM 内部故障的退出码相同,node 一律按故障处理。按从 FAILED 恢复处理
guest 自己关机不处理。VMM 继续运行,Workspace 保持 AVAILABLE,guest 不再回应。先强制停止再启动服务端强制停止,进入 STOPPED。直接启动
宿主内存耗尽服务端强制停止,进入 STOPPED。直接启动与 Firecracker 相同
  • guest 关机后与宿主内存耗尽时的强制停止,是服务端唯一会自己发起的强制停止,效果与调用方的强制停止相同:Volume 与可写层保留,最后的写入可能没有落盘。
  • Workspace 已经开始删除,或者有其他命令正在处理时,服务端不发起停止。
  • 要停止或重启 Workspace,用停止与启动操作,不要在 guest 里关机或重启。

guest 自己重启

在 Firecracker 后端上,guest 里执行 reboot -f、echo b > /proc/sysrq-trigger 这类复位时,node 在同一台 node 上为同一个 Instance 启动新的 VMM。Workspace 始终是 AVAILABLE,执行代与数据面凭证不变。

  • Volume 与可写层保留,内存和进程不保留;没有落盘的写入可能丢失。
  • guest 回来之前,数据面新请求返回可重试的 unavailable,已建立的流随旧 VMM 结束。
  • kibo workspace get 的 Guest 一行显示重启次数与最近一次复位的时间。
  • 10 分钟内复位超过 3 次时不再重启,Workspace 进入 FAILED,失败信息写明复位次数,按从 FAILED 恢复处理。
  • 新 VMM 没有启动成功,或重启进行到一半时 node 自身重启,Workspace 也进入 FAILED,失败信息写明原因。

guest 自己关机

在 KiboVM 后端上,guest 里执行 poweroff -f 或以 POWER_OFF 调用 reboot(2) 时,服务端对它执行强制停止,Workspace 进入 STOPPED。启动它即可继续使用。

  • 停止完成之前 Workspace 仍是 AVAILABLE,这段时间数据面请求被拒绝。
  • 到期策略按停止的规则处理。
  • Workspace 已经开始删除或有其他命令正在处理时,服务端等下一次上报再判断。

宿主内存耗尽

宿主内存耗尽时,内核会杀掉宿主上的一台 VM。服务端对这台 VM 的 Workspace 执行强制停止,Workspace 进入 STOPPED。启动它即可继续使用。

在服务端完成停止之前,Workspace 会短暂处于 FAILED,失败信息写明宿主内存不足。

用 API

kibo 命令API
kibo workspace stopStopWorkspace
kibo workspace stop --forceStopWorkspace,mode 为 STOP_MODE_FORCE。需要服务端声明能力 workspace.stop.force
kibo workspace startStartWorkspace
kibo workspace deleteDeleteWorkspace
kibo workspace cleanup-statusWorkspaceObservationService/GetWorkspaceCleanup
  • 停止的结果用命令 ID 经 GetWorkspaceCommand 查询,包括正常停止同步失败或结果未知的情况。
  • 强制停止被拒绝时返回 failed_precondition,ErrorDetail.reason 为 CONFLICT。
  • 由 VMM 意外退出导致的 FAILED 不设置 failure.stage,因为失败不发生在任何操作里。

停止后的落盘情况

停止完成后,命令结果的 durability 说明写入是否确认落盘:

值含义
STOP_DURABILITY_CONFIRMED正常停止成功,写入已同步
STOP_DURABILITY_UNCONFIRMED强制停止,包括服务端发起的;或 KiboVM 后端有一块可写盘没有刷到存储设备,这时 Workspace 照常停止

停止原因

Workspace 在 STOPPING 与 STOPPED 时带 last_stop,说明是哪一次停止把它带到这里;StartWorkspace 与 DeleteWorkspace 被接受后不再返回它。

字段含义
causeSTOP_CAUSE_REQUESTED:调用方的 StopWorkspace;STOP_CAUSE_EXPIRED:到期;STOP_CAUSE_GUEST_SHUTDOWN:guest 关机;STOP_CAUSE_HOST_MEMORY_EXHAUSTED:宿主内存耗尽
command_id这次停止的命令,可以用 GetWorkspaceCommand 查结果
durability停止完成后与命令结果相同;停止完成之前为 STOP_DURABILITY_UNSPECIFIED

服务端发起的停止,命令 ID 带固定前缀:

  • guest 关机为 guest-shutdown/。
  • 宿主内存耗尽为 host-memory/。

调用方的命令 ID 不能使用这两个前缀,否则返回 invalid_argument。guest 关机后进入 STOPPED 的行为对应能力 workspace.stop.guest_shutdown。

排查

启动被拒绝

  • 现象:FAILED 的 Workspace 启动返回错误。
  • 原因:Workspace 仍持有执行,旧实例还可能占着存储。
  • 处理:先强制停止再启动,见从 FAILED 恢复。

下一步

本页内容