Kibotos

node

本页介绍如何让 node 停止接收新的 Workspace、在 node 宕机或失联时将它隔离、退役 node、设置超卖倍数,以及查找和指定 Workspace 所在的 node。

node

用 kibo node 查看 node 的注册状态,并在维护前让它停止接收新的 Workspace:

node_id=node-a
kibo node list --page-size 20
kibo node get "$node_id"
registration_version=$(kibo node get "$node_id" --json | jq -er '.result.registration_version')
kibo node drain "$node_id" --command-id drain-a --expected-version "$registration_version"
# 需要等待清空时可在提交 drain 时加 --wait --timeout 10m。
kibo node cancel-drain "$node_id"

list 与 get

两条命令原样返回 ctrl 中的节点注册记录:

字段内容
node_id、admission、drain_requested节点 ID、是否已获准加入、是否已请求 drain
isolated是否处于isolate 声明生效的状态
statusctrl 推导出的当前状态
最近一次会话启动序号(incarnation)、会话 ID、node 的版本、是否存活
最近一次完整上报上报时间、已分配的资源、这个 node 持有的 Instance 与 Volume 数量
schedulable 与 overcommit放置实际使用的 CPU 与内存,以及生效的倍数和来源(全集群默认或本 node 覆盖),见 overcommit
host_usage控制连接存活时,node 最近一次采样的实际用量;只在 get 里显示
registration_versiondrain、cancel-drain、isolate 与 overcommit set 的期望版本

list 的人读输出是每个 node 一行的表格;--json 输出的 result 与 API 字段同名。list 的排序与分页由服务端完成。

列内容
RELEASEnode 二进制的发布版本。未正式发布的构建显示 unreleased,没有值时显示 -
CLOCKctrl 最近一次测得的 node 时钟偏差(node 减 ctrl)。超过允许偏差时标 (over)。控制连接不在时显示 -
INSTANCESnode 最近一次上报的 Instance 数量
CPU_ALLOC/SCHED、MEM_ALLOC/SCHED已分配量与可调度量。CPU 以核数显示,内存按最大的二进制单位保留一位小数
MEM_TIGHT宿主内存是否紧张,见 Host usage
REG_VERSION注册记录的版本,只在 --wide 中显示

kibo node get 与 JSON 输出分别给出发布版本、源码 revision 和注册记录版本,node get 的注册记录版本、启动序号、会话 ID 与上报版本只在 --wide 中显示;Latest session 一节还给出时钟偏差的不确定度与 node 宿主内核报告的同步状态。

控制会话开始时以及之后每次定期同步 node 状态时,ctrl 都测量一次 node 的时钟。偏差减去不确定度后超过 30 秒时,调度不再把新的 Workspace 放到这个 node 上,已有的 Workspace 继续运行。之后某次测量回到 30 秒以内,这个 node 才重新接收新的 Workspace,因此要修正宿主机的时间同步。

drain 与 cancel-drain

  • 两者都以 registration_version 作为期望版本。会话变化、资源上报和管理操作都会让这个版本递增。
  • drain 只做一件事:ctrl 不再把新的 Workspace 调度到这个 node,node 本身也拒绝新的创建请求。已有 Workspace 的停止、删除、导出照常执行。cancel-drain 恢复调度。
  • drain 不会迁移或销毁 Workspace。要清空一个 node,Operator 需要自己用 kibo workspace stop/delete 或 kibo transfer export 处理上面的 Workspace;kibo workspace list --node "$node_id" --all -q 列出它们。
  • kibo 不会代替你操作宿主机。维护顺序是:drain → 清空 Workspace → 看到 DRAINED → 停止 node 服务。

drain --wait

提交后按固定间隔查询,直到 Instance 与 Volume 数量都归零:

结果退出码说明
状态到达 DRAINED0
超过全局 --timeout 仍未到达16drain 请求已经提交,drain_requested 保持为 true。kibo 不会再提交一次
等待期间 drain 被取消或 node 被撤销13

DRAINED 的条件是这个 node 上不再运行任何 Instance,也不再持有任何 Volume 或保留的可写层的使用权(use right):一个共享存储池里别的 node 持有使用权的对象不计入这个数量。只要还有一项不满足,状态就停在 DRAINING。

isolate

kibo node isolate 是操作员对一个 node 的断言:"这台宿主机已经关机,或者它已经写不到自己的任何存储池"。这不是 ctrl 自己能验证的事实:

kibo node isolate "$node_id" --command-id isolate-a --expected-version "$registration_version" --confirm-host-cannot-write
  • 必须带 --confirm-host-cannot-write:操作员在断言这个事实,也在承担断言错了的后果——一个其实还在写存储的 node 被声明 isolate,会损坏它正在使用的块文件。
  • 只要这个 node 还有存活的控制会话,isolate 就会被拒绝(退出码 13):能负责任地做这个断言的只有 ctrl 之外、正在看着这台宿主机的操作员。

成功后,ctrl 一次完成下面几件事:

  • 释放这个 node 持有的每一个 Volume 与保留的可写层的使用权,共享池与只有它接入的池都算。
  • 释放这个 node 名下所有的分配。
  • 这个 node 上运行的每一个 Workspace 变为 FAILED,原因是 UNAVAILABLE,可以重试启动。
  • 发给这个 node、还没有完成的命令失败。

返回结果给出释放的 Volume 数、保留的可写层数与因此失败的 Workspace 数。

这些 Workspace 什么时候能重新启动或删除,取决于它们的对象在哪个池:

对象所在的池能重新启动或删除的时机
共享池不必等这个 node 回来,由另一个接入这个池的 node 启动或删除
只有这个 node 接入的池这个 node 回来之后,或者另一台接入同一个池的宿主机加入之后
  • 重新启动后的数据与宿主机掉电后相同:已经写到池里的内容都在,旧宿主机页缓存里还没回写的写入可能丢失。
  • 共享池放在 NFS 上时,另一个 node 能正确接手的前提是挂载没有加 nocto,见把存储池放在 NFS 上的前提条件。
  • isolate 会让这个 node 当前的启动序号(incarnation)失效:用这个或更早的启动序号重新连接会被拒绝,ctrl 同时告诉这个 node 它已被 isolate。
  • node 收到后销毁自己的全部 Instance,然后退出,由 systemd 重启;重启后以新的启动序号重新连接,isolate 自动清除,不需要额外的命令。
  • 共享池上的对象已经交给别的 node 时,原 node 即使没有连上 ctrl,也会在几秒内从池里的持有者记录发现这一点,自行停掉仍在写这些对象的 Instance。
  • isolate 不删除任何对象,也不代替你确认宿主机确实已经关机或确实已经断开存储。声明错了没有事后校验,后果是数据损坏。

retire

宿主机不再回来时,用 kibo node retire 让这个 node 退役。退役是终态:

kibo node retire "$node_id"
  • 只接受状态为 DRAINED 的 node,或当前启动序号已被 isolate 的 node,其余返回 failed_precondition,退出码 13。
  • 执行前要在终端确认;没有终端时加 --yes。显式 --command-id 时必须同时给 --expected-version,同一对重放返回同一结果。

退役之后:

  • 这个 node 不再是任何存储池的成员,待使用的 enrollment grant 被撤销,控制会话被关闭。
  • 它的登记保留下来,状态是 RETIRED。Allocation 和对象的上一任持有者还引用这条记录。
  • 它不能再登记。给同一个 node_id 签发 grant、drain、isolate 都返回 failed_precondition。新宿主用新的 node_id。
  • 被 isolate 之后退役的 node 如果回来,以被 isolate 的启动序号连接时照样收到隔离拒绝并销毁全部 Instance;换了新的启动序号才因未准入被拒绝。
  • 最近一次执行在它上面的 Workspace,kibo workspace cleanup-status 的 RUNTIME、VOLUME_ATTACHMENT、RESIDUAL 显示 RELEASED,来源是控制面状态。

与退役的 node 一样,kibo enrollment revoke 撤销的 node 不是池成员:它不列在池的 Nodes 里,也不算作别的 node 进入 DRAINED 时「池的另一台接入 node」。

只有它接入的池退役后没有成员。这时分两种情况:

overcommit

node 的 [resources] 只写宿主能给 VM 的 CPU 与内存。超卖由 ctrl 的倍数表达:放置用的可调度量等于 node 报告的量乘以倍数。改倍数不需要重启 node:

kibo node overcommit get
kibo node overcommit set-default --cpu 4
kibo node overcommit set "$node_id" --cpu 2.5 --memory 0.9
kibo node overcommit set "$node_id" --cpu default
  • 倍数写成十进制,最多三位小数,CPU 与内存都在 0 到 16 之间。
  • 内存倍数大于 1 时,guest 实际用到的内存可能超过宿主内存。宿主内存耗尽时内核杀掉其中一台 VM,ctrl 随后自行停止它的 Workspace,调用方直接 start 即可;未落盘的写入可能丢失。KiboVM 的 guest 内存要等进程完全退出才释放,这段时间里内核可能再杀一个进程。按长时间运行后的实际用量设内存倍数,见下面的 Host usage。
  • 宿主可用内存低于总内存的 10% 时,node 判定内存紧张:拒绝新建 Workspace,ctrl 立即改为放到别的 node,所有 node 都放不下时返回 resource_exhausted。可用内存回到 15% 以上后恢复。已有的 Workspace 不受影响。
  • set-default 改全集群的默认值,期望版本是 get 显示的 version。set 改一个 node 的覆盖,期望版本是它的 registration_version;default 清除这一项的覆盖,回到全集群默认。
  • 两条命令都只改给出的那一项,另一项保持当前值。显式传 --command-id 时必须同时传 --expected-version 和两个倍数,这样重放的输入不依赖执行时读到的值。
  • 调低到已分配量以下时,这个 node 不再接收新的 Workspace,已有的照常运行,不会被驱逐。
  • 新值送到 node、node 确认之前,ctrl 不向这个 node 放置,通常不到一秒。node 没有确认时,ctrl 断开它的控制连接,重连后再送一次。

kibo node get 的「Host usage」是实际用量,只用于查看,不参与放置:

项内容
VM CPU、VM memory全部 VM 占用的 CPU 与 guest 实际用过的内存
Memory available宿主可用内存,含可以回收的缓存
Memory tightnode 是否判定宿主内存紧张、从何时起;紧张期间不接收新的 Workspace。kibo node list 的 MEM_TIGHT 列显示同一件事
CPU idle宿主 CPU 的空闲比例
CPU pressure、Memory pressure最近 60 秒里任务因等待 CPU 或内存而停顿的时间占比;some 是至少一个任务在等,full 是全部任务都在等
  • node 每 10 秒采样一次,ctrl 每次对账时(60 秒)取回最新一次,所以读数最多落后约一分钟。
  • 读不到的项显示 -,不是 0。还没有启动过 VM 的 node 没有 VM 两项。
  • VM 两项统计的是整台宿主上的 VM。一台宿主只运行一个 node 时,它就是这个 node 的 VM。
  • guest 用过的内存不会还给宿主,跑得越久的 VM,VM memory 越接近它申请的内存。按实际用量调内存倍数时,看长时间运行后的读数。

Workspace 在哪台 node 上

kibo workspace list 按 node 或 Instance 列出正在执行的 Workspace,kibo workspace get 显示一个 Workspace 所在的 node:

kibo workspace list --node node-a
kibo workspace list --instance inst-01k6…
kibo workspace get ws-01k6…
写法结果
workspace list --node这台 node 上正在执行的全部 Workspace
workspace list --instance以这个 Instance 执行的 Workspace。宿主上的目录、进程参数与日志给出的是 Instance ID,用它反查 Workspace
workspace getNode 一行是所在 node,--wide 再加一行当前 Instance
  • 表格与普通的 workspace list 相同,--wide 另加 INSTANCE 与 NODE 两列。Instance 每次启动换一个新的。
  • 只列出现在有执行的 Workspace。已停止、已删除和还没放置到 node 上的 Workspace 没有 node,workspace get 显示 -。
  • 不再是当前 Instance 的 ID 查不到任何行,与从未存在过的 ID 一样。
  • --node 与 --instance 互斥,也不能与 --state、--label 等过滤同时使用。node 不存在时退出码为 12。
  • kibo 先读一页位置,再逐个读取 Workspace;两次读取之间被删除的 Workspace 不出现。
  • -q --all 只输出 Workspace ID,一行一个,可以交给脚本逐个处理。
  • 连到没有位置查询的旧 ctrl 时,workspace get 的 Node 显示 unknown,命令本身照常成功。

把 Workspace 放到指定 node

--node 把一次创建或启动固定到一台 node,kibo workspace move 把 Workspace 停止后在另一台 node 上启动:

kibo workspace create --template kibotos-coding --node node-c
kibo workspace start ws-01k6… --node node-b
kibo workspace move ws-01k6… --node node-b
  • 只有这一台是候选。它必须像任何放置一样接收这个 Workspace:未 drain、就绪、剩余容量够,并接入 Workspace 的 Volume 与可写层所在的池。不满足时创建或启动失败,不会改放到别的 node。
  • 只对这一次放置生效。Workspace 不记住这台 node,以后不带 --node 的启动照常由调度决定。
  • drain 照样挡住指定放置。冒烟一台新 node 要先取消它的 drain,其间调度也可能把别的 Workspace 放上去。
  • 创建时,随创建的 Volume 与可写层落在这台 node 的默认池。对象在 node 的私有池里时,Workspace 以后只能在这台 node 上启动;要能换 node,用多台 node 共用的池,见 storage-pool。

workspace move 依次做三件事:

步骤做什么不满足时
核对读 Volume 与可写层所在的池,以及目标 node 报告可用的池有对象在目标 node 接不到的池里,或正在搬迁:退出,Workspace 不变
停止Workspace 为 AVAILABLE 时正常停止;STOPPED 与 FAILED 跳过停止失败:按停止的错误退出
启动在目标 node 上启动Workspace 不再运行,错误给出重新启动的命令,即 kibo workspace start ws-01k6… --node node-b
  • 没有热迁移。停止与启动和平常一样,内存与进程不保留。
  • Workspace 已经运行在目标 node 上时直接成功,不停止。
  • --command-id 给出时,停止与启动的命令 ID 是它加上 /stop 与 /start。同一条命令再运行一次,接着处理没完成的那一步。

本页内容