运营 bridge

运营 bridge 及其背后那个环的笔记:加载一份方案、挺过重启、让贡献持续流动,并把引擎挡在互联网之外。

网关(公共入口)与 bridge(引擎门面)是运营者要保持健康的两个长期服务,其后是 p4 的 agent 和它们的 stage server。引擎完全不做认证——它假定彼此可达的机器就是应该彼此可达的——所以一切公共流量都汇聚到网关,而 bridge 经隧道访问、不对外发布。

加载

一份方案,以及加载它所用的那个数字

  • 放置是你写的方案,不是你发的请求:谁要求 bridge 去服务,它就回 409。先生成方案、dry-run,再用 --confirm 加载。
  • load generation 在第一条命令发出之前就写到磁盘上。它由加载者选定,在每次会话和卸载时按完全相等校验,且在机器上不留任何记录——弄丢了,已加载的模型连拆都拆不掉。
  • 节点的 generation 就是同一个数字。用两个不同的数字加载一个环,它只服务一次请求头部就会停,下一次会话则会半加载地挂住。每次加载都用一个新值,否则上一次失败尝试遗留的注册会与它冲突。
  • 没有运行日志(operational journal),agent 就拒绝加载。那是可重放安全的加载所需的准入记录,不是调试开关。
挺过重启

什么会回来,什么不会

  • agent 重启会丢掉它的节点。stage server 只存在于运行时;模型必须照方案重新加载一次。这是恢复流程,而不是哪里出了故障。
  • 网关不会替你重新加载。它的环看门狗会发现某个模型停止了服务,从 bridge 的 409 中得知放置在外部,说一次之后就不再问。
  • 贡献计数器活在 bridge 的内存里。网关每 30 s 轮询一次并增量记账;重启只丢掉尚未被轮询的部分,而当计数器倒退时网关会重设基线,而不是重复支付。
锁紧

引擎不面向互联网

  • 把 bridge 绑定到 loopback 并给它一个服务令牌。没有令牌它谁都不认证,任何能触达它的东西都能免费驱动整个环——它在启动时就会这样告诉你,而不是让你事后才发现。
  • agent 公示的是其他 agent 要拨的地址。用主机之间最快的那张网,跨主机绝不用 loopback,并把那张网挡在公网之外。
  • 如果某个东西必须坐在公网 IP 上,记住 Docker 发布的端口在 INPUT 链之前就已被 DNAT,因此针对 dport 的规则不会命中。改在 DOCKER-USER 链中按 conntrack 的原始目的端口(--ctorigdstport)过滤,并用排在 After=docker.service 之后的 systemd oneshot 持久化。
自伤陷阱

两个真花时间的坑

  • 未设置的运营者钱包看上去就是零收益。网关会跳过任何没有所有者的贡献行,且不记录任何日志。节点明明在服务,看起来却像闲置。
  • `pkill` 会匹配到它自己的命令行。ssh host 'pkill -f server.js; ...' 杀掉的是正在运行它的那个 shell。把匹配模式放进脚本文件而不是远程命令里,用字符类(server[.]js),并且记住以裸 node server.js 启动的进程没有路径可匹配——改用它监听的端口去找。