Kibotos

身份、配置与连接

本页说明 ctrl、node 和客户端共同遵守的身份、证书与配置规则。它回答「这个配置项是什么意思」「证书从哪来、多久过期」这类问题。

配置事实源

ctrl 与 node 只读取严格的 TOML:出现未知字段直接报错。完整字段、示例值与约束以 ctrl.example.toml 和 node.example.toml 为准。示例中的值只是示例,不是所有字段的默认值。每个表与键及示例中的注释见 ctrl 配置与 node 配置。

配置项说明
ctrl [identity].trust_domainOperator 与 node 身份所属的信任域,小写域名形式。初始化后不能修改
ctrl [identity].hostctrl 两个监听地址共用的主机名或 IP。客户端连接时的主机名必须与它一致;不接受通配符
ctrl [api].listenWorkspace API 与 Operator API 的 mTLS 监听地址
ctrl [node_api].listennode 注册、证书签发和 node 主动连接 ctrl 的监听地址
ctrl [data_plane].host_suffix必填。每个 node 的数据面证书会包含 <node_id>.<host_suffix>
ctrl [data_plane].default_extra_hosts可选。加入所有 node 数据面证书的额外主机名或 IP
ctrl [storage].rootctrl 自己的 PKI 与凭证加密密钥所在目录。init 在这里创建 PKI,serve 从这里读取;serve 发现没有 credential-keys/ 下的密钥时生成一个,权限 0600,只属于服务账号
node [ctrl].endpoint / proxyctrl node API 的 HTTPS 地址,以及可选的正向代理
node [data_plane].listen / advertise数据面在本机的监听地址,以及 ctrl 告诉客户端使用的对外地址
node [storage].rootnode 的身份、持久状态、Template 缓存与 VM runtime 的根目录
node [[storage.pool]]至少声明一个存储池:一个目录,装着 Volume 的块文件、保留的可写层与一个标记文件。池的 path 可以等于 storage.root,也可以在别处(例如 NFS 挂载)。池的容量不在这里声明,见池容量
node [runtime].socket_rootnode 的 Unix socket 目录。node 不会再在它下面追加 node ID,路径要足够短
ctrl [metrics]可选。实例指标存储的 remote write 地址、签发写入凭证的私钥文件与 CA,以及 instance_info_labels。没有这一段时不写任何实例指标。node 从 ctrl 取得写入地址与凭证,node 的配置里写了这一段会拒绝启动。见实例指标存储
ctrl [traces]可选。trace 存储的 OTLP/HTTP 地址、签发 trace token 的私钥文件与 CA,以及 node 数据面的采样比例。没有这一段时不产生 span。node 从 ctrl 取得地址与凭证,node 的配置里写了这一段会拒绝启动。见链路追踪
ctrl 与 node [telemetry].listen可选。服务自身指标的监听地址,明文 HTTP、不认证,只提供 GET /metrics。不写时不开监听。与 [metrics] 无关,见集群与服务指标
  • ctrl 的默认配置路径是 /etc/kibotos/ctrl/config.toml,node 是 /etc/kibotos/node/config.toml。用 --config 指定其他绝对路径。
  • 证书、CA 和签名私钥保存在受 ctrl 或 node 管理的目录里,不写在 TOML 中。
  • node 的 ID 来自注册时得到的客户端证书,不是配置项。
  • node 的 [resources] 声明这台宿主能给 VM 的 CPU 与内存,即物理量减去宿主自己要留的部分。它不能超过宿主的在线 CPU 数与 MemTotal,否则 node 拒绝启动。超卖不写在这里,由 Operator 用 kibo node overcommit 设置倍数,见超卖倍数。
  • Template 缓存上限由 [storage].template_cache_limit 声明。缓存需要空间时,按最近使用的先后淘汰运行中的 Instance 没有用到的内容,包括传输中断留下的部分文件。调低上限后,node 启动时淘汰到上限以内;运行中的 Instance 用到的内容保留,淘汰不够时 node 照常启动,新的 Template 准备因容量不足失败,直到这些 Instance 停止。Volume 与保留的可写层的存储容量是每个池在 ctrl 上的容量,用 kibo storage-pool set-capacity 设置。node 不会自动探测机器容量。
  • 不需要 guest 网络时省略 [host_network]。public-internet 策略所需的双栈接口、路由和 DNS 配置见 node 配置示例。

身份与注册

ctrl 的初始化顺序是 kibotos-ctrl init → migrate → 本机 enrollment create → serve。

init 不联网、不连接数据库、不监听端口。它创建四样东西:签发客户端证书的 CA、ctrl 服务端 CA、数据面会话凭证的签名密钥、ctrl 服务端私钥。 状态完整时重复执行返回 unchanged;状态不完整或不匹配时失败,不会自动修补。

操作执行者结果
kibotos-ctrl enrollment create --operator <id> --output <path>ctrl 宿主机管理员(能访问 ctrl 配置、PKI 和数据库)为第一位 Operator 签发注册密钥;所有 Operator 身份丢失时也用它恢复
kibo enrollment create --operator <id> --output <path>已注册的 Operator为另一位 Operator 签发一次性注册密钥
kibo enrollment create --node <id> --output <path>已注册的 Operator为指定 ID 的 node 签发一次性注册密钥,可附带额外的数据面主机名
kibo context enrollOperator用注册密钥换取 Operator 身份,连同 ctrl 地址保存到 context 目录
kibotos-node join --config ...node 宿主机管理员用注册密钥换取 node 身份,写入 <storage.root>/pki/。不启动 node

身份规则

  • 正式身份的 URI 是 spiffe://<trust-domain>/operator/<id> 或 spiffe://<trust-domain>/node/<id>。
  • node ID 必须是小写域名形式,因为它会成为数据面证书主机名的一部分。
  • 是否有权访问由 ctrl 中的注册记录决定。当前已注册的 Operator 拥有集群管理权限,可以调用 Workspace API 与 Operator API。仅信任 ctrl 的服务端证书(例如浏览器)不能获得任何权限。

注册密钥的规则

  • 默认有效 1 小时,--ttl 可在 1 分钟到 24 小时之间调整。
  • 密钥里包含一把引导私钥和 ctrl 服务端 CA,要当作凭证保管:不放进命令行参数、环境变量、日志或版本库。
  • 注册成功后删除密钥文件。

kibo context enroll 与 kibotos-node join 读取密钥的方式相同:

  • 不给密钥参数时,在终端无回显地询问。标准输入不是终端时,必须给 --key-stdin、--key-fd <n>(n 不小于 3)、--key-file <path> 三者之一,且只能给一个。
  • 密钥不能通过命令行参数或环境变量传入。
  • 密钥必须是一个 token,不超过 16 KiB。
  • --key-file 接受相对路径、绝对路径,以及指向普通文件的符号链接。FIFO、目录和其他特殊文件会被拒绝。
  • 密钥文件对 group 或 other 可读时,命令打印警告,仍然读取,不修改文件。密钥文件的权限应设为 0600。
  • 注册写入的身份目录与私钥文件严格检查权限。

kibo context enroll 与 kibotos-node join 都不会覆盖已有的身份目录。目录中的身份过期或损坏时,先停止使用它的进程、删除目录,再用新的注册密钥注册。

ctrl 宿主机上的 kibotos-ctrl enrollment create 会作废该 Operator 尚未使用的旧密钥。kibo enrollment create 的重放见幂等重放。

服务端证书与数据面证书

ctrl 的服务端证书

ctrl 在 init 时创建服务端 CA,serve 用它为 [identity].host 签发服务端证书。每把注册密钥都携带这个 CA 的证书: kibo context enroll 与 kibotos-node join 先用它验证 ctrl 的主机名,再发送引导身份;成功后把 CA 保存为身份目录中的 server-ca.pem。 之后访问 ctrl 的两个 mTLS 端口都只信任这个 CA,不读取系统根证书,也不需要公共 DNS、ACME 或修改系统信任库。

node 的数据面证书

数据面私钥由 node 在本机生成,ctrl 根据 node 的注册身份签发证书。证书包含的主机名来自三处,去重后使用:

  1. ctrl 派生的 <node_id>.<host_suffix>。
  2. ctrl 配置的 [data_plane].default_extra_hosts。
  3. 签发该 node 注册密钥时传入的 --data-plane-extra-host。

规则:

  • 额外的主机名可以是完整域名或 IP,不接受通配符。任何一个都不能与 ctrl 自己的 [identity].host 相同。
  • node 配置中 [data_plane].advertise 的主机名必须在证书中。
  • 派生的主机名不需要真的在 DNS 中注册。只有客户端用它作为连接地址时,才需要能解析。

例如 host_suffix = "nodes.kibotos.trial"、node ID 为 node-a,并在签发密钥时加上 --data-plane-extra-host 127.0.0.1, 证书就同时覆盖 node-a.nodes.kibotos.trial 和 127.0.0.1,单机上的客户端可以直接连 https://127.0.0.1:<port>。

node 把证书保存在 <storage.root>/pki/data-plane/ 下的 leaf.key、leaf.pem 与 manifest.json,启动时校验并复用,需要时重新签发。

修改主机名集合:

  • 要修改某个 node 的额外主机名,需要撤销该 node,用新的主机名重新签发注册密钥,删除旧的身份目录后重新 join。
  • 修改 ctrl 的 host_suffix 或 default_extra_hosts 只影响之后签发的证书,需要与 node 的 advertise 配置和证书更新一起安排。

数据面客户端如何验证

kibo 与 SDK 等数据面客户端使用与控制面不同的 TLS 配置:信任系统根证书加上 server-ca.pem,按标准规则校验主机名。 因此客户端既能直接连 node,也能连部署方放在 node 前面的公网 TLS 反向代理。反向代理必须在部署方的信任范围内,并正确转发流式请求与长连接。 这种公网 TLS 终止只适用于数据面。ctrl 的 mTLS 端口始终要求注册身份和 ctrl 自己的服务端 CA。

客户端连接

context 目录

kibo context enroll 把 ctrl 地址、Operator 身份、信任的 CA 以及可选的正向代理保存在一个目录里,这个目录称为 context。之后的每条 kibo 命令都读取它。

  • 默认位置是 $XDG_CONFIG_HOME/kibo/context;未设置 XDG_CONFIG_HOME 时为 ~/.config/kibo/context。环境变量 KIBO_CONTEXT_DIR 可以指定另一个绝对路径。
  • 目录中有 context.json、当前的 identity-<serial>.pem 与 identity-<serial>.key、control-client-ca.pem 和 server-ca.pem。
  • context 目录已存在时,enroll 拒绝覆盖。需要重新注册时先删除旧目录。
  • 全局参数 --endpoint 或环境变量 KIBO_ENDPOINT 只改变本次请求的地址,身份与信任的 CA 仍来自 context。

正向代理

kibo context enroll --proxy 与 node 的 [ctrl].proxy 接受 http://、https://(CONNECT)或 socks5:// 代理,例如 --proxy socks5://proxy.example:1080。

  • kibo 把 enroll 时给出的代理保存在 context 中,之后的每条命令都使用它,数据面连接也一样。
  • 显式设置优先。没有设置时按 HTTPS_PROXY、ALL_PROXY、NO_PROXY(及小写形式)选择;访问 loopback 地址不使用环境变量中的代理。
  • TLS 验证和 mTLS 在代理隧道内完成。代理地址中的用户名和密码不会出现在输出或日志中。
  • 数据面不跟随重定向,只在 TLS 验证成功后发送会话凭证。

续期、撤销与恢复

有效期

证书有效期与续期
ctrl 服务端证书30 天,只保存在内存中。剩余不到 10 天时重新签发并原子切换;ctrl 重启时重新签发
Operator 与 node 的客户端身份30 天。剩余不到 10 天时续期:kibo 在访问 ctrl 前自动续期,也可以执行 kibo context renew;node 在运行中自动续期
node 数据面证书30 天。进入续期窗口后带退避重试,期间当前证书继续使用;过期后拒绝新的 TLS 握手
两个 CA不在线轮换。恢复时必须使用原来的状态;更换 CA 需要重新初始化 ctrl,并让所有客户端重新注册
  • 自动续期失败时,kibo 打印警告,继续使用身份直到它过期。
  • 身份过期后无法续期,需要用新的注册密钥重新注册。

撤销

kibo enrollment revoke --operator <id> --yes 或 --node <id> --yes 立即终止该身份,且不可撤回:作废尚未使用的注册密钥,拒绝之后的请求、注册和续期。撤销 node 还会断开它当前与 ctrl 的控制连接。

撤销不影响已有的 Workspace 和进行中的数据面连接,它们按各自的规则继续。只是想让 node 暂停接收新的 Workspace,用 kibo node drain。

要让被撤销的 Operator 或 node 回来,重新签发一把注册密钥,再执行 kibo context enroll 或 kibotos-node join。

备份与恢复

恢复一套部署需要同时匹配的 PostgreSQL 数据、ctrl PKI、node 持久状态和客户端身份,以及版本能互相连接的 ctrl 与 node。不要只删除 ctrl 的 PKI 却保留其他状态。

需要重建一套可丢弃的试用环境时,先停止所有进程,按部署文档清理全部状态,再从空目录初始化。不要手工修改数据库的迁移版本,也不要伪造身份文件。

运行账户与状态目录

进程或目录说明
ctrl可以用专用的服务账户运行,需要能读取配置、数据库连接串和自己的 PKI
node必须以 root 运行,负责以 kibotos-vmm 账户启动 VMM
VMM以系统账户 kibotos-vmm 运行,需要属于 kvm 组并能读写 /dev/kvm
node 的存储目录保存独占锁、启动序号、Instance、Template 缓存、VM runtime 和 node 身份。删除它就丢失了 node 的全部本地状态
node 的存储池保存 Volume 的块文件与保留的可写层,可以在存储目录之外(例如 NFS 挂载)。声明它、初始化它的标记文件见安装 node
node 的 socket 目录保存进程运行期间的 socket 和 VMM 的临时状态。只有停止 node 并确认没有残留 VMM 后才能删除
  • 存储目录与 socket 目录的上级目录必须允许 kibotos-vmm 进入。
  • node 会创建并校验自己的目录。不要用符号链接或放宽私钥权限来绕过校验。

执行权

同一个数据库上只有一个 ctrl 执行:调用 node、运行命令与后台工作、写入数据库。它靠数据库里的一行执行权保证,与连接和数据库会话无关,经连接代理或连接池也成立。

情形行为
ctrl 启动时没有别的 ctrl 执行立即执行
另一个 ctrl 正在执行只回答从数据库读取的请求,写入、node API 与 node 控制连接返回可重试的 unavailable;日志记 another ctrl executes; answering reads only until it stops
执行的 ctrl 正常退出停下全部工作后释放执行权,等着的 ctrl 立即接手
执行的 ctrl 崩溃或与数据库断开执行权 30 秒后过期,等着的 ctrl 才接手;断开的 ctrl 在过期之前停止执行
执行的 ctrl 失去执行权它此后的写入全部失败,进程以错误退出,由服务管理器重启后只读等待

接手的 ctrl 先把全部 node 标为观测过期,等 node 重新连接并上报完整资源清单后才调度到它上面。

替换 ctrl 时先停止旧的,再启动新的,并等待 node 重新连接并上报完整的资源清单。

版本兼容

只有版本兼容时,node 才能连上 ctrl:

ctrl 与 node 的版本规则被拒绝时 ctrl 的日志
都是 v0.1.0 或更高的正式版本或 -rc.N 版本,MAJOR.MINOR 相同版本可以不同,见逐台升级
都是 v0.1.0 或更高的正式版本或 -rc.N 版本,MAJOR.MINOR 不同拒绝连接is not in ctrl release line
其余版本(-alpha.N、-beta.N、未发布构建、v0.0.x)源码 revision 必须完全相同does not match ctrl release

本页内容