Kibotos

重装与升级

本页介绍如何在不停止 Workspace 的情况下重装同版本的包、升级到新版本。各版本额外的升级步骤见从 v0.1.x 升级到 v0.2.0与从 v0.2.x 升级到 v0.3.0,卸载见卸载。 升级分两种:同一发布线内(同一 MAJOR.MINOR 的正式版本与 -rc.N 版本之间)逐台替换,ctrl 与 node 不用同时停;跨 MINOR 以及涉及 -alpha.N、-beta.N 的升级整套停机替换。 首次安装见安装概览。node 与 VMM 的进程模型和维护检查命令的细节见 node 与 VMM 进程。 ctrl 与网关以容器运行时,判据与步骤与本页相同,执行方式见用容器运行。

概述

理解下面几点,后面的步骤就容易读了。

VMM 独立于 node 运行。 每个 Instance 的 VMM 是一个独立的 systemd transient service。停止 node 服务不会停止 VMM;新的 node 启动后按持久化的绑定记录重新接管它们。因此替换 node 程序不需要停止 Workspace。目标版本换了 VM runtime 时,运行中的 VMM 继续使用启动时的 runtime 安装,Workspace 下次启动才换到新的 runtime。

数据面连接独立于 node。 exec、terminal、文件传输和端口转发的连接由 node 启动的数据面进程持有。停止 node、在同一发布线上替换 node 程序都不断开这些连接;跨发布线的替换会断开它们。见数据面进程。

同一 MINOR 内可以混合运行。 从 v0.1.0 起,同一 MAJOR.MINOR 的正式版本与 -rc.N 版本构成一条发布线,ctrl 接受同一发布线上版本不同的 node,不论哪边更新。MAJOR.MINOR 不同的 node 连不上 ctrl;-alpha.N、-beta.N、v0.0.x 与未发布构建要求 ctrl 与 node 的源码 revision 完全相同。

正常停止 Workspace 需要 guest 配合。 ctrl、node 和 guest 来自发布包。如果 guest 版本太旧、不支持停止前的准备接口,停止命令会明确失败,而不是退化为直接销毁。

外部调用方的接口另有承诺。 本页说的是部署方替换程序;外部应用调用的接口有自己的兼容窗口与发布说明,见兼容承诺。

持久记录有版本范围。 node 写在本地的每一类持久记录都声明自己能读取的版本范围,最多两个版本。替换程序前的检查会列出目标版本读不了的记录;没有向旧格式的转换。

node 可以接管比自己旧的 guest。 guest 的协议版本在接受范围内即可,缺少的能力只让用到它的操作失败。

同版本重装与重启

普通的 systemctl restart kibotos-node 走进程接管路径:VMM 留在各自的服务里,systemd 回收旧 node 的辅助进程后启动新 node,独占锁保证同时只有一个 node 写状态目录。 两个后端都要核对实际的 VMM、辅助进程与独占锁,仅凭 VMM 进程还在不能判断接管完成。

重装同版本的包:

sudo systemctl stop kibotos-node.service
sudo kibotos-node check-maintenance --config /etc/kibotos/node/config.toml --operation upgrade
sudo apt-get install --reinstall ./kibotos-node_1.2.3_amd64.deb
sudo systemctl start kibotos-node.service

--operation upgrade 允许保留已解绑的 Volume 和保留的可写层。

注意:

  • 用 --reinstall,不要先 remove 或 purge。删除包之后就没有旧程序来执行维护检查,带着残留状态重新安装会被拒绝。
  • 升级与重装时,包脚本只要求 node 服务已停止,不检查资源。
    • 替换文件不会停止或删除任何 VMM。新 node 启动后接管它们;接管不了的 Instance 标为 FAILED,它的 VMM 继续运行。
    • 包脚本执行时,磁盘上只有旧二进制,回答不了「新版本能否接管」。这个问题由部署方在替换前回答:同版本重装执行上面的 check-maintenance,跨版本执行目标版本的 check-upgrade,见跨版本升级第 5 步。
    • 卸载仍然由包脚本执行 check-maintenance --operation remove,检查不通过就拒绝卸载:卸载之后宿主上没有程序能管理剩下的 VMM。检查通过后,包脚本结束全部数据面进程。
    • 替换文件也不会停止数据面进程。新 node 启动后接管或替换它们,见数据面进程。
  • ctrl 同样先停止服务、重装、再手动启动。包脚本不会自动重启服务。
  • 如果之前执行过 kibo node drain,node 恢复并与 ctrl 同步状态后,还要执行 kibo node cancel-drain node-a 才会重新接收新的 Workspace。
  • 停止 node 不断开 exec、terminal、文件传输和端口转发的连接,node 停着时也可以新建连接:这些连接由数据面进程持有,ctrl 继续按 node 最后上报的数据面证书签发会话,直到证书过期。例外是 ctrl 自己在 node 停着期间重启过:ctrl 要等 node 重新连上才再认识它的证书。

重装网关

替换或重装网关包之前,先停止服务,并确认服务处于 inactive 且没有残留进程。服务在运行、失败或状态未知时,包脚本会拒绝操作;排除故障原因后,用 systemctl reset-failed 清除失败状态。以 E2B 网关为例(Exposure 网关把 kibotos-e2b 换成 kibotos-gw):

sudo systemctl stop kibotos-e2b.service
sudo apt-get install --reinstall ./kibotos-e2b_1.2.3_amd64.deb
sudo systemctl start kibotos-e2b.service

注意:

  • 网关停止时还有代理的连接是正常的。服务先给它们一段时间自行结束,到点就直接关掉,日志里按 server 记一条写明连接数的 warn,服务仍然停在 inactive,不需要在装包之前清除失败状态。
  • 跨版本升级按跨版本升级的停机流程与 ctrl、node 一起进行。先升 ctrl 再升网关:包安装成功不代表网关能读取旧版本的状态;Exposure 网关按 zone 向 ctrl 解析 hostname,ctrl 不认这个接口时整条 zone 不可用。
  • 网关不接受命令行参数,全部配置来自 /etc/kibotos/e2b/config.env 或 /etc/kibotos/gw/config.env。用 systemctl edit 覆盖过 ExecStart 的,升级前删除覆盖,把参数改写成对应的环境变量,变量名见 e2b.example.env 与 gw.example.env。
  • Exposure 网关不保存状态,停机期间已有的 Exposure 记录在 ctrl 里不受影响;停机期间该 zone 的请求全部不可达。tunnel 的配置与 DNS 不随它升级改变。
  • E2B 网关同版本重装后,检查健康接口并用 SDK 做一次验证。

准备目标版本的程序

升级前的检查要在当前版本还装着时运行目标版本的 kibotos-ctrl 与 kibotos-node。在每台宿主机上把它运行的那个目标版本的包解到安装目录之外的一个新目录。ctrl 宿主机上:

set -eu
test ! -e /tmp/kibotos-next
dpkg-deb -x kibotos-ctrl_1.2.4_amd64.deb /tmp/kibotos-next
/tmp/kibotos-next/usr/bin/kibotos-ctrl version --json

每台 node 宿主机上:

set -eu
test ! -e /tmp/kibotos-next
dpkg-deb -x kibotos-node_1.2.4_amd64.deb /tmp/kibotos-next
/tmp/kibotos-next/usr/bin/kibotos-node version --json
  • node 包同时带着目标版本的 VM runtime,位于 /tmp/kibotos-next/usr/lib/kibotos/node。用 --runtime-dir 把这个目录传给 kibotos-node check-upgrade;不传时检查的是当前已安装的 runtime。
  • 解出来的这份只用于检查,升级完成后删除 /tmp/kibotos-next;安装仍然走 apt-get install。

停机前的预检

停机窗口应该只用来替换文件。下面两条命令都用目标版本的程序、在服务还在运行时执行,把「有没有东西挡着」这个问题提前问掉。两者都是只读的,可以随时重复执行,都不替代停机后的完整检查。

node

check-maintenance 与 check-upgrade 都要取 node 的独占锁,只能在服务停止后执行。为了不在停机窗口里才发现「某个 Workspace 必须先停」,先对每台仍在运行的 node 跑一次预检:

sudo /tmp/kibotos-next/usr/bin/kibotos-node check-upgrade --preview --config /etc/kibotos/node/config.toml --runtime-dir /tmp/kibotos-next/usr/lib/kibotos/node

它列出的阻塞项就是停机后的检查会再列一次的那些。现在处理,窗口里就只剩替换。预检判定哪些项、报告怎样读,见停机之前先用 --preview 问一遍。

--config 指向的文件要能被目标版本读取。目标版本改了 node 配置的写法时(例如升级到由 ctrl 设置池容量),运行中的 node 还在用旧写法,预检在加载配置这一步就会失败。这时按目标版本的写法另存一份副本,让预检读取副本:

sudo cp -p /etc/kibotos/node/config.toml /etc/kibotos/node/config.next.toml
sudoedit /etc/kibotos/node/config.next.toml
sudo /tmp/kibotos-next/usr/bin/kibotos-node check-upgrade --preview --config /etc/kibotos/node/config.next.toml --runtime-dir /tmp/kibotos-next/usr/lib/kibotos/node

副本只用于预检。停机后的检查(跨版本升级第 5 步)要先把改动写进 /etc/kibotos/node/config.toml 本身再执行:维护检查按 --config 的路径认定这台 node 的服务单元,用副本执行时会把 kibotos-node.service 当成别的 node,不核对它的进程是否都已退出。改之前留一份原文件,检查不通过、要启动原版本时换回去。

ctrl

ctrl 侧不需要另一个开关:ctrl 的升级检查不取任何锁、也不写任何东西,对着还在服务的 ctrl 直接跑就行,命令与停机后完全相同。

sudo -u kibotos-ctrl /tmp/kibotos-next/usr/bin/kibotos-ctrl check-upgrade --config /etc/kibotos/ctrl/config.toml

这时候报告怎么读:

检查项停机前跑出来的结论
配置、PKI、数据库版本、Template 目录表结构与停机后相同。这几项是发现问题最贵的地方,提前跑的价值也在这里
Workspace 固定使用的 Launch对当时存在的 Workspace 与停机后相同;此后新建的 Workspace 不在这次结论里
未完成的对象列出的是执行那一刻仍在进行的命令、Transfer、执行与收尾任务。运行中的部署有这些是正常的,drain 并等待收敛之后才会清空

因此停机前这条命令的退出码通常非零,原因只在「未完成的对象」一节;要判断升级是否被挡住,看的是其余各项。等真正停机之后再跑一次,那一次的结论才是替换判据。

同一 MINOR 内逐台升级

适用于当前版本与目标版本在同一发布线上:MAJOR.MINOR 相同、不低于 v0.1.0,且都是正式版本或 -rc.N 版本,例如 v0.1.2 升到 v0.1.4,或 v0.2.0-rc.1 升到 v0.2.0。其他情况(包括涉及 -alpha.N、-beta.N 的替换)按下文跨版本升级停机替换。

先升 ctrl,再逐台升 node。正在替换的那一台 node 不执行新的生命周期操作,但它上面的 exec、terminal、文件传输和端口转发连接不断开,期间也可以新建(ctrl 按它最后上报的数据面证书继续签发会话);新 node 启动后换用新的数据面进程,旧进程等已有连接结束后退出,见数据面进程。其余 node 上的 Workspace 不受影响。ctrl 替换期间,已经建立的数据面连接继续可用,新的 Workspace 操作与新的数据面会话要等 ctrl 恢复。

逐台升级的步骤

步骤操作完成条件
1准备目标版本的程序,确认目标版本与当前版本在同一发布线上;执行停机前的预检(ctrl 一次,每台 node 一次)目标文件完整;版本属于同一发布线;预检没有阻塞项
2停止 ctrl,按ctrl 的升级检查用目标版本检查,替换 ctrl 包,按报告执行迁移,启动 ctrlkibo node list 中全部 node 重新变为 READY
3选一台 node 执行 kibo node drain <node>,等待它上面进行中的生命周期命令与 Transfer 完成ctrl 不再往这台 node 调度新 Workspace
4停止这台 node,用目标版本执行 kibotos-node check-upgrade(命令见跨版本升级第 5 步),替换 node 包,启动 node原有 Instance 被接管;kibo node list 中这台 node 为 READY,RELEASE 为目标版本
5执行 kibo node cancel-drain <node>,回到第 3 步处理下一台全部 node 的 RELEASE 为目标版本

E2B 网关只调用 ctrl 对外的接口;Exposure 网关调用的 ctrl 接口在同一发布线内只新增。两者都可以在第 2 步之后的任意时刻按各自的重装方法替换。

逐台升级的注意事项

  • 第 4 步的检查与跨版本升级相同:guest 协议、runtime 驱动范围与本地记录格式超出目标 node 支持范围的 Workspace 会被列为阻塞。升级到同一发布线上更新的版本时,这些范围只会扩大,正常情况下不会出现。
  • 目标版本的 Platform 通常可以在任何一步发布,旧 node 也能启动它。
  • 目标版本换了 VMM runtime 时,旧 node 启动不了新 Platform,也接管不了新 runtime 启动的 Instance。这时全部 node 替换完成后再发布 Platform,node 替换后不能回退到换 runtime 之前的版本。该版本 CHANGELOG.md 的「升级须知」会写明。
  • 升级中途停下是允许的状态:ctrl 与各 node 可以长期保持同一发布线上的不同版本。
  • node 可以逐台回退到同一发布线上的旧版本,步骤与升级相同,换了 VMM runtime 的版本除外。ctrl 回退不要求 node 一起回退,但第 2 步执行过数据库迁移后,旧 ctrl 会拒绝更高的 schema,这时只能往前修。
  • 某台 node 替换后启动或接管失败时,保持它的 drain,按回退处理这一台,其余 node 不受影响。

跨版本升级

适用于 MAJOR.MINOR 不同的升级,以及 v0.0.x、-alpha.N、-beta.N 与未发布构建之间的替换。ctrl 与全部 node 一起停机替换。

升级到 v0.2.0 的起点必须是 v0.1.x。更早的版本先升级到最新的 v0.1.x,再升级到 v0.2.0:第 5 步的检查会拒绝更早版本的数据库与 node 本地记录,见从 v0.1.x 升级到 v0.2.0。

升级替换的是程序,不是 Workspace。VMM 和 guest 里的进程在整个过程中持续运行,新的 node 接管同一个 Instance,Workspace 的 generation 不变。 exec、terminal、文件传输和端口转发的连接会断开:新 node 启动时结束旧版本的数据面进程;从 v0.1.x 升级时,停止旧 node 就会断开。新的数据面进程启动后可以重新建立;guest 内的进程和内存不受影响。

跨版本升级的步骤

按顺序执行。某一步的完成条件不满足时,停在那一步处理,不要跳过。

步骤操作完成条件
1准备目标版本的程序,记录当前部署的版本清单;执行停机前的预检(ctrl 一次,每台 node 一次)能精确恢复到旧版本;目标文件完整;预检的阻塞项已处理
2暂停对外的写入入口、自动化客户端和 Template 发布;对所有 node 执行 kibo node drainctrl 不再调度新 Workspace;管理命令仍可用
3用当前版本等待进行中的生命周期命令与 Transfer 完成,然后取一次完整的资源清单没有进行到一半的操作
4停止 ctrl、所有 node、E2B 网关、Exposure 网关,以及其他会写状态的进程辅助进程已退出,独占锁已释放;VMM 仍在运行
5用目标版本的二进制执行离线检查(下面两条命令)报告中没有阻塞项。从检查到安装完成期间保持停机
6替换全部安装文件。检查报告要求迁移时执行 kibotos-ctrl migrate迁移完成;安装文件与目标版本一致
7手动启动目标版本的 ctrl 和所有 node,再启动两个网关全部 node 连上 ctrl;原有 Instance 被接管;资源清单与数据面就绪
8执行 kibo node cancel-drain,恢复对外写入入口能调度新 Workspace;原有 Workspace 的数据面可用

第 5 步的两条命令:

sudo -u kibotos-ctrl /tmp/kibotos-next/usr/bin/kibotos-ctrl check-upgrade --config /etc/kibotos/ctrl/config.toml
sudo /tmp/kibotos-next/usr/bin/kibotos-node check-upgrade --config /etc/kibotos/node/config.toml --runtime-dir /tmp/kibotos-next/usr/lib/kibotos/node

node 侧检查的判据见 node 与 VMM 进程,ctrl 侧见下文。

跨版本升级的注意事项

  • 目标版本带来新的 guest 时,先用目标版本发布并 approve Platform,再升级 node。guest 随 Platform 交付,旧 Platform 的 guest 在新 node 上可能在就绪阶段失败,失败原因会带在 Instance 的错误里。
  • 第 3 步只要求命令完成,不要求停止 Workspace。需要停止的只有第 5 步报告点出的那些:guest 协议版本超出目标 node 支持范围的 Workspace,以及所用 runtime 安装已损坏、或其 runtime 版本超出目标 node 驱动范围的 Workspace。用正常的停止流程处理它们,让数据落盘,不要销毁 VM。
  • 目标 node 能驱动的 runtime 是它自己固定的版本,加上上一个版本固定的版本。在当前版本下启动的 Workspace 都能被接管;更早启动、此后一直没有停止过的 Workspace,如果它的 runtime 比上一个版本固定的还旧,第 5 步会把它列为阻塞。跳过检查直接替换,这些 Instance 会变为 FAILED,处理方法见 node 与 VMM 进程。
  • 第 4 步之后 VMM 仍在运行,这是预期状态。不要 kill 它们、按名称前缀批量停止 unit,或删除绑定文件。这些操作会破坏第 5 步检查所依赖的进程归属证据。
  • drain 停在 DRAINING 就可以。只要还有已解绑的 Volume,状态就不会到 DRAINED;升级不需要到 DRAINED。
  • 运行中的 guest 缺少目标版本新增的能力不会阻塞升级。这样的 Instance 照常被接管,只是用到该能力的操作在它重启前会失败。check-upgrade 的报告会列出受影响的能力。

回退

  • 检查失败、尚未替换文件时:启动原版本的 ctrl 和 node,等待状态同步,执行 cancel-drain。检查本身不修改任何状态。
  • 目标版本启动或接管失败时:保持对外写入暂停。先用目标版本的控制面停止相关 Workspace,确认 Volume 已解绑、辅助进程已退出,再用旧版本对当前状态执行同样的检查,通过后恢复旧版本的安装文件并按相同顺序启动。
  • 从 v0.1.x 升级到 v0.2.0 时,替换文件之后不能回退,见从 v0.1.x 升级到 v0.2.0。
  • 其他情况下旧版本读不了目标版本写入的数据时,保留现场交由部署方处理。不要用备份直接覆盖。

ctrl 的升级检查

停止服务后、替换文件前,用即将安装的 kibotos-ctrl 对现有部署做只读检查。同一条命令也可以在停止 ctrl 之前先跑一遍,读法见停机前的预检;作为替换判据的那一次仍然在服务停止后执行。

用准备目标版本的程序里解出的那一份:

sudo systemctl stop kibotos-ctrl.service
sudo -u kibotos-ctrl /tmp/kibotos-next/usr/bin/kibotos-ctrl check-upgrade --config /etc/kibotos/ctrl/config.toml

检查内容:

  • 配置能解析并通过校验。
  • PKI 能加载且自洽。
  • 数据库迁移版本。
  • Template 目录的表结构。
  • 每个 Workspace 固定使用的 Launch 制品能被目标版本重新读取与校验。
  • 未完成的对象:处理中的命令、未结束的 Transfer、准备中或已下发的执行、待完成的制品收尾任务、结果未知的分配。

报告逐条列出阻塞项与原因,最后给出汇总。只有没有阻塞项时退出码才是 0。

该命令是只读的:不迁移 schema、不创建目录、不写 PKI 或 artifact store、不启动后台任务、不监听端口。对同一状态重复执行结果相同。

关于数据库版本:

  • 数据库版本低于目标版本要求时不算阻塞。报告会把 kibotos-ctrl migrate --config /etc/kibotos/ctrl/config.toml 列为「替换文件后、启动服务前必须执行」的操作,依赖新表结构的检查项标记为「迁移后适用」。
  • 以下情况是阻塞,必须先处理:迁移状态为脏、数据库版本高于目标版本、数据库版本早于目标版本支持的起点(v0.2.0 要求 v0.1.x 的数据库)。

本页内容