Kibotos

写操作与错误

通过 API 修改状态的程序都遵守同一套规则:先查询服务端的能力,写请求带幂等键与期望版本,按统一的格式读取错误。本页逐条介绍这些规则以及承载它们的字段。

先查询能力

调用业务方法前,先调用 ServerInfoService/GetServerInfo。响应有两个字段:

字段含义
source_revision服务端构建自哪个源码版本,仅供展示
capabilities字符串列表,如 workspace.create、workspace.filesystem、workspace.desktop,完整清单与命名规则见能力名
  • 没有 API 版本号可以比较。
  • 需要某个能力的操作在能力列表里找不到它时,应该让这一个操作失败,而不是拒绝整个服务端。
  • kibo 在每条命令前做精确的字符串匹配,缺失时退出码为 14。

写操作的约定

有两个字段让写请求可以安全地重发、安全地并发:幂等键让重发的请求不会重复执行,期望版本让请求不会覆盖别人的修改。

幂等键

除了下面列出的两个请求,每个写请求都带一个客户端生成的命令 ID(幂等键):

服务面字段位置格式
Workspace API请求中的 CommandMetadata metadata,字段 command_id^[A-Za-z0-9][A-Za-z0-9._/-]*$,1 到 128 字节
Operator API请求中的 string command_id同上

不符合上表格式的命令 ID,v0.3.x 仍然接受,v0.4.0 起返回不可重试的 invalid_argument。部署方怎样查出这些调用方,见从 v0.2.x 升级到 v0.3.0。

下面这些 ID 有额外的限制:

ID限制不符合时
所有写请求不能以 expiration/、host-memory/、guest-shutdown/ 开头,这些前缀留给 ctrl 自己发起的命令Workspace API 现在就返回 invalid_argument,Operator API v0.4.0 起返回
ApplyArtifactReclamation 的 command_id不能含 /invalid_argument
BeginArtifactPublication 里 Template、Platform 发布的 command_id匹配 ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$:不能含 /,可以含 :BeginArtifactPublication 本身成功,这次发布在写入清单时失败
  • GetWorkspaceCommand 与 GetVolumeCommand 读取已有的命令,ID 不受这些规则限制。
  • Go SDK 的 kibotos.ValidateCommandID 检查上表的格式和保留前缀;程序要自己调用,SDK 发送请求时不检查。kibo 在发送前检查 --command-id。

命令 ID 只出现在请求消息里,不是 HTTP 头。请在提交前把它保存下来。

服务端把命令 ID 与输入和已有的记录比较:

  • 用相同的命令 ID 和相同的输入再次提交,返回第一次的结果,不会重复执行。失败也一样:命令失败后用同一个 ID 重发,只会回放这次失败。
  • 一个命令 ID 对应一次尝试。结果未知或命令还在执行时,保持原 ID 重发;错误详情带 command_settled 时,失败已确定,要重试就换新 ID。
  • 命令 ID 由对象推导时(比如防止重复创建),让它带上会随尝试变化的部分,比如已失败的次数,否则失败一次后再也跑不起来。
  • 用相同的命令 ID 但不同的输入提交,返回 already_exists。
  • CreateWorkspace 与 UpdateWorkspaceNetworkPolicy 比较输入时不看 network_policy.revision:这个值由服务端分配,请求里填什么都被忽略。

RevokeEnrollment 与 RetainLaunchRevision 没有命令 ID:它们的效果本身可以重复施加。重复撤销不改变结果,重复保留到同一时刻也一样。

命令的返回时机

命令什么时候返回,取决于命令本身:

命令返回时机结果怎么查
CreateWorkspace、StartWorkspace受理即返回,Workspace 处于 CREATING 或 STARTING,执行器继续执行GetWorkspaceCommand
StopWorkspace、DeleteWorkspace、RevokeWorkspaceDataPlane等命令完成,最长 1 分钟超时返回可重试的 UNAVAILABLE,命令继续执行;用 GetWorkspaceCommand 查
UpdateWorkspaceNetworkPolicyAVAILABLE 的 Workspace 等 node 确认或报告失败,最长 1 分钟;STOPPED 的 Workspace 立即返回超时或 node 不可达时返回可重试的 TIMED_OUT 或 UNAVAILABLE,Workspace 处于 UNKNOWN,直到 node 再次汇报。见修改什么时候生效
ExportWorkspace、ImportTransfer、RestoreWorkspace等命令完成,最长 1 分钟超时同上;错误详情带当前的 Transfer,用它的 transfer_id 调 GetTransfer
Volume 的创建、扩容与删除,ResizeWorkspaceWritableLayer在请求内完成,响应带回结果状态结果未知时,Volume 命令用 GetVolumeCommand,可写层扩容用 GetWorkspaceCommand

重要

超时或结果未知时也可以用原来的命令 ID 重发,不要换一个新的。

版本校验

修改已有对象的请求带一个期望版本。对象的当前版本与期望不一致时服务端拒绝,避免覆盖别人的修改。

Workspace API 的请求:

请求期望版本字段对应的对象版本
UpdateWorkspaceExpirationexpected_revisionexpiration.revision
StopWorkspace、StartWorkspace、DeleteWorkspaceexpected_expiration_revisionexpiration.revision。没有到期设置时也有版本号
UpdateWorkspaceMemory、UpdateWorkspaceCpuexpected_revision资源配置的版本 resources_revision,两者共用
UpdateWorkspaceVolumeBindingexpected_revisionVolume 绑定的版本 binding_revision,与资源版本各自独立
UpdateWorkspaceNetworkPolicyexpected_revision,可以不带network_policy.revision。为 0 时不检查;不为 0 时即使内容与当前相同,版本不符也拒绝
UpdateEgress、UpdateResolverexpected_revisionEgress 或 Resolver 的 revision
Workspace、Volume、Egress、Resolver 的 labels 与 annotations 修改,如 UpdateWorkspaceLabels、UpdateVolumeAnnotationsexpected_revision对象的 labels_revision 或 annotations_revision

Operator API 的请求:

请求期望版本字段对应的对象版本
DrainNode、CancelNodeDrain、IsolateNode、RetireNode、SetNodeOvercommitexpected_registration_versionnode 的 registration_version
SetOvercommitDefaultsexpected_version超配默认值的 version
SetStoragePoolCapacityexpected_version存储池的 version
SetPlatformDefaultexpected_revision 与 expected_default_version当前默认版本及其指针版本
SetTemplateDefaultexpected_revision,或 expect_no_default当前默认版本

ResizeWorkspaceWritableLayer 与 ResizeVolume 没有期望版本,只有命令 ID 和目标容量。

版本不一致时返回什么错误,取决于是哪个版本:

不一致的版本错误
到期设置的版本:UpdateWorkspaceExpiration 的 expected_revision,或停止、启动、删除的 expected_expiration_revisionfailed_precondition
其他期望版本aborted

到期时间在 Workspace 状态不允许修改时也返回 failed_precondition,用错误详情里的 observed_workspace 区分这两种情况,见到期时间。

修改已删除对象的 labels 或 annotations 同样返回 failed_precondition。

收到这两种错误后,重新读取对象状态再决定下一步,不要自动用新版本重放旧请求。

错误格式

错误使用 Connect 的标准错误码。错误详情中附带 kibotos.ctrl.v1.ErrorDetail,按下面这些字段决定怎样处理:

字段用法
reason更细的原因,FailureReason 枚举,如 SESSION_EXPIRED、CAPABILITY_UNAVAILABLE、CONFLICT。先看它,再看标准错误码
retryable重试是否可能成功。为 false 时,先修改请求或对象;用不用新的命令 ID 看 command_settled
command_settled这是命令已记录的结果:同一个命令 ID 只会回放它,重试要换新 ID。没有这个字段的可重试失败还没有结果,用同一个 ID 重发
accepted_bytes只出现在 SendInput 返回的 resource_exhausted 上:guest 在拒绝之前已经接收的字节数
observed_workspace、observed_volume、observed_transfer失败时对象的状态。用它决定下一步,例如区分版本冲突与状态不允许修改

stage、message 等其他字段与全部原因见 API 参考中的 ErrorDetail 与 FailureReason。

kibo 优先按 reason 决定退出码,其次按标准错误码。退出码见 kibo 退出码。

下一步

  • 认证:获得并续期 Operator 身份。
  • 数据面:会话凭证与对 node 的调用。
  • 能力名:所有能力及其含义。
  • 错误:各失败原因的含义与处理。

本页内容