Files
dsh_ai1net_server/docs/集群与实例/搬运与共享重建方案_guest_w47到w106_20260915.md
admin ce8e6ceed9 chore(工作区): 纳入版本控制基线(回收 411 MB 过程产物)
回收 411 MB(470 M → 58.8 M),全部经回收站,可恢复:
- 待清理/(146.2 M,含 relay 分片 128 M 与 42 项过程目录)
- tmp/(32.4 M,按接续棒命名的过程临时区)
- .workbuddy/tmp/(39.5 M)
- 4 份 workbuddy.db 冗余副本(101 M,09-23 事故的坏副本 / 抢救产物)
- tmp/im16/gw/centrifugo 二进制(63.9 M,可重下)+ 缓存残留

入库范围:常驻规则(CODEBUDDY.md / README.md / state.py)、在途接续入口与
接续包、docs/、交付物/、交接单/、归档/、scripts/、.codebuddy/、
.workbuddy/memory/;共 398 件,其中 >60 KB 的 26 件全为文档。

排除(.gitignore):tmp/、待清理/、运行态日志与缓存、*.db 与 DB 备份整目录、
打包二进制(*.tar.gz / *.tgz)、记忆修复前备份。
2026-09-24 07:51:03 +08:00

13 KiB
Raw Permalink Blame History

guest 迁移(w-47 → w-106)与「共享重建」方案

状态:规划稿(未执行) | 立稿:2026-09-15 | 触发:用户要求「规划搬运和重建方案;MCN 依赖应以可共享的方式重建,避免后续搬其他用户重复重建」

0. 一句话

只搬 46.3 MB 不可再生数据;792.7 MB 的 Python 环境 + 362.7 MB 的 Node 依赖改为「平台侧共享目录 + 新机重建」,装一次、全平台用户共用。


1. 事实基础(本轮实测,勿再重测)

项 数值 / 事实
必搬(不可再生) 48,539,522 B = 46.3 MB / 1193 文件
可重建 / 可丢 ≈ 2.9 GiB:trash 1379.5 · ws/.local(pnpm store) 732.9 · MCN/.venv 792.7 · home/profiles/web/node_modules 362.7 · tmp 26.4 · 各类缓存 ~36
47 → 106 直连速率 ~22 KB/s(实测 5.5 min 走 7.3 MB)⇒ 46.3 MB ≈ 35 min;1.7 G 需 21 h ✗
106 现状 dshs-worker(19000) 在跑;无 provisioner、无 pnpm 链路;磁盘余 32 G;已建 OS 账号 uid 100002;无 guest 数据
平台现成机制 实例 bwrap 已有 --ro-bind-try /var/lib/dshs/bundled-skills ⇒ 「平台共享只读目录」这套已经存在,共享 venv 走同一套路
平台官方口径 src/supervisor/orchestrator.ts:557:额外依赖走 pip install --target <ws>/.pylibs + PYTHONPATH,或自建 venv(不改平台) ⇒ 现状是每用户一份,正是要改的点

必搬口径(可复现): du -sb <用户目录> --exclude=trash --exclude=tmp --exclude=.venv --exclude=node_modules --exclude=.local --exclude=.cache --exclude=.npm --exclude=.node-compile-cache --exclude=.pnpm-cache --exclude=.pnpm-store --exclude=__pycache__ ⚠️ 分项相加会大于总量(pnpm store 与 node_modules 硬链接,du 同一 inode 只计一次)—— 报体积别用分项求和。


2. 依赖分三类 → 共享落点

类 现状(每用户一份) 目标 落点
Python:MCN venv 792.7 MB / 人 ✗ 全平台一份 /var/lib/dshs/shared/python/mcn@<版本>/,bwrap --ro-bind-try 进实例
Node:Profile 依赖 362.7 MB / 人(pnpm store 697 MB 里大部分可复用) store 共享;node_modules 按 profile 重建 共享 store /var/lib/dshs/shared/pnpm-store + pnpm install --frozen-lockfile
系统库 / 字体 ws/syslibs 5.24 MB + ws/.fonts 15.68 MB 一份 同共享目录(或纳入平台 syslibs 机制)

收益:第 2 个及以后用户 ⇒ Python/Node 依赖不再重复下载,省 ≈1.15 GB 与 30+ 分钟/人。


3. 关键设计决定(自决,可推翻)

  1. 共享目录一律只读挂载(ro-bind)⇒ 用户改不坏、不会被各自的 pip 污染;写操作仍走用户自己的 .pylibs。
  2. 版本化 + 显式升级:目录名带版本(mcn@1);升级 = 建新目录 → 切挂载 → 保留旧版供回滚。
  3. MCN 技能改造:不再自带 .venv,改指向共享解释器(脚本里 PYTHON_BIN / PYTHONPATH);playwright 浏览器二进制放共享目录并设 PLAYWRIGHT_BROWSERS_PATH。
  4. 清单入库:从现 venv pip freeze 导出固定版本的 requirements.txt 进仓库 ⇒ 共享环境从此可复现(当前项目里没有任何清单,这是必须先补的前置)。
  5. 平台改动最小化:只加 --ro-bind-try /var/lib/dshs/shared(一行),不动隔离与权限面(仍是只读)。

4. 执行步骤(每步有验收与回滚)

# 动作 验收 回滚
1 47 上导出 MCN 依赖清单(pip freeze + playwright --version) 清单文件生成并入库 无副作用
2 搬 46.3 MB(§1 口径)到 106,落地后 chown -R 100002:100002 字节数/文件数与 47 一致;属主 100002 删 106 目标目录
3 106 建共享目录并重建 MCN venv python -c "import ctranslate2, av, playwright, pandas" 通过 删共享目录
4 平台加一行共享挂载 + build + systemctl restart dshs 实例内 ls /var/lib/dshs/shared 可见 去掉那行重启
5 106 上重建 profile 依赖(pnpm + lock + .dsh-stage/*.tgz) node_modules 生成、bundles 完整 删 node_modules
6 迁移归属:POST /api/admin/users/:id/dsh/migrate {"targetHost":"w-106"} host_id=w-106、epoch+1、106 出现 scope、guest 能进且文件在 再迁回 w-47(数据仍在)
7 源目录打包 → /opt/dsh/backups/migrated/guest-<ts>.tar.gz → 删源 归档可解压且清单核对一致 从归档恢复

5. MCN venv 的建法:选定「在 106 重建」(另一条已否决)

  • 选定 A · 在 106 重建:干净、可复现、跨机架构正确。代价:需先有清单(步骤 1)、需外网装 ~800 MB。
  • 否决 B · 从 47 直接把 venv 拷进共享目录:虽与现状逐字节一致,但走那条 22 KB/s 的链路搬 792.7 MB ⇒ ≈10 小时,且 venv 内含绝对路径,跨机仍有风险 ⇒ 只有缺点,故自决不采用。

6. 与「备份机制」的衔接

  • 归档区:/opt/dsh/backups/migrated/(已建);源目录先打包保留、再删。
  • 策略分离(建议):
    • 用户核心数据(46 MB 级) → 高频(每日)备份,直接放归档区/对象存储;
    • 共享依赖(版本化目录,百 MB 级) → 按版本备份(升级时留一版即可),不必按日。
  • 后续接「备份存储空间」:归档目录可整体同步到对象存储(OSS/COS);挂载点与保留策略一次定好,避免各 worker 各写一套。

7. 红线与「不得净变差」复核(R11)

红线 结论
R2 不改官方 dsh ✅ 只改平台自己的 spawn 参数 + 用户数据
R7 批量/别人 lane 迁移是用户明确指令;平台加一行挂载属我 lane,但先单点验证(步骤 4 先在一台 worker)
R8 中断在线用户 本服务器为开发环境,可直接做,动手前一句话说明
R10 属主 目标侧一律 chown -R 100002:100002(与 47 provision-new-users.sh 同口径)
R11 净变差 共享化让体积/性能/扩展性都变好(每人省 1.15 GB 与 30 分钟);新增的只有一个只读挂载点 ⇒ 权限面不变 ⇒ 无净变差

8. 遗留(本方案不解决,需另立)

  1. 106 没有账号 provisioner(dsh-provision.path 只在 47)⇒ 新用户被调度到 w-106 时无人建 OS 账号,且 worker agent 里也没有 useradd ⇒ 新用户可能起不来。建议把 provisioner 机制铺到每个 worker(否则「新用户落 w-106」这条设计不成立)。
  2. MCN 项目里没有任何依赖清单(requirements.txt/pyproject.toml 都没有)⇒ 步骤 1 是硬前置。
  3. 现有用户的 .venv 仍是各自的(本方案只对新迁移/新建生效);存量收敛需单独排期。

9. 决策更新(2026-09-15 20:5x · 用户定,开始执行)

  • 那 4 个重包「暂不重建」:playwright==1.62.0 · ctranslate2==4.8.2 · onnxruntime==1.30.0 · av==18.1.0(合计 ≈ 443 MB)⇒ 新环境先不装(MCN 依赖这几项的功能暂时不可用,后续需要时再单独排期)。其余按本方案处理。
  • 依赖清单已导出(硬前置完成):mcn-req-full.txt(51 包)与 mcn-req-no4.txt(47 包 —— 重建用这份),落在工作区根目录。 ⚠️ 口径注意:venv 里没有 pip(pip freeze 直接 UnicodeDecodeError)⇒ 改为扫 site-packages/*.dist-info 生成清单(等价且更稳)。
  • 共享 venv 的基础运行时:现有 venv 由 /usr/local/bin/python3 -m venv 创建,指向 /usr/local/dsh-runtime/python-3.12.14/bin/python3.12(平台自带的共享 Python 运行时)⇒ 共享 venv 应基于它建,不要用系统 python。
  • 执行进度:核心数据搬运已在 106 后台启动 —— 脚本 /root/migrate-guest.sh,日志 /var/log/migrate-guest.log,起于 2026-09-15 20:58:16,预计 ~35 分钟(46.3 MB @ ~22 KB/s)。 ⚠️ 该次搬运已作废:其 --exclude 写的是 $U/node_modules、$U/.venv 等顶层路径,而真实依赖在 ws/…、home/profiles/web/… 之下 ⇒ 等于在传全量 3 G(实测 2h10m 只走 133 MB)⇒ 已停并改走 §10 的路径。

10. 执行实况(2026-09-15 23:15 → 09-16 00:2x)—— 已完成

10.1 带宽实测(决定整条路径)

链路 实测速率 结论
47 → 本机(单流) 126 kbps ≈ 16 KB/s 瓶颈在 47 出口
47 → 本机(8 路并行) 783 kbps ≈ 98 KB/s 并行 ≈ 6 倍收益
47 → 本机(16 路并行) 1122 kbps ≈ 140 KB/s 接近饱和
本机 → 106 33.5 Mbps ≈ 4.2 MB/s 极快 ⇒ 作中转最划算
47 → 106(直连) ~22 KB/s(历史实测) 与单流同量级

⇒ 选定路径:47 →(8 路并行拉)→ 本机 →(4.2 MB/s)→ 106。

⚠️ 两个实测坑:① 106 → 47 的 scp 并发超 ~10 会被 47 的 sshd 拒绝(Connection closed);② 即便降到 6 路,部分分片仍会静默中断(只写一半)⇒ 接力脚本必须逐片比对大小并重拉(_relay2.sh:第 1 轮补 5 片,第 2 轮归零)。

10.2 实际搬运量(全部经本机中转 + 逐片校验)

项 原始 压缩后 说明
用户数据(46.3 MB 口径) 46.3 MB 30.1 MB / 15 片 与 47 对账真实缺口 = 0
dsh-runtime(python3.12.14 + jq + rg) 110 MB 39.1 MB / 10 片 ffmpeg/ffprobe(344 MB)暂不传
profile node_modules(含 .pnpm 实体) 362.7 MB 89.6 MB / 11 片 压缩比 4x
business-plugins(3 个 tgz) 44 MB 44.4 MB / 6 片 file-preview + mcn-suite + univer
bundled-skills 12 KB — 直连管道
合计 — ≈ 203 MB 单流口径需 ~3.5 小时

10.3 106 侧「本地重建」(不占 47 带宽,与搬运并行)

  • dsh 主程序:npm i -g @deepseek-ai/[email protected] → /usr/lib/node_modules/@deepseek-ai/dsh(295 MB,与 47 同版本);并补 /usr/local/bin/dsh 符号链接(平台默认以 dsh 命令解析)。
  • MCN 的 Python venv:按 mcn-req-no4.txt(47 包)在 106 重建 ⇒ 远优于传 819 MB;pandas/jieba/matplotlib/bs4 导入通过。
  • whitelist-cache 不传:只被 Manager 侧 src/web/routes/whitelist.ts 读取,106 是 worker。
  • /var/lib/dshs 顶层对齐:bundled-skills ✅ / business-plugins ✅ / secret.key 已有 ✅ / dshs.db 不传(集群下权威库是 47 的 PG)。

10.4 途中发现的三个「实例起不来」级坑(均已修)

  1. 🔴 106 上 /var/lib/dshs/users 是 drwx------(47 是 drwx--x--x)⇒ setpriv --reuid 100002 无法穿越该路径 ⇒ 实例必崩。已 chmod 711;/var/lib/dshs 755 → 711(收窄,对齐 47)。
  2. 🔴 106 上没有 dsh 主程序(/usr/local/bin/dsh 不存在)⇒ 已装同版本 + 建链接。
  3. 🔴 106 上没有 /usr/local/dsh-runtime(python 3.12.14 / jq / rg 全缺)⇒ 已传。

10.5 迁移结果(已验收)

  • POST /api/admin/users/<guest>/dsh/migrate {"targetHost":"w-106"} ⇒ {"ok":true,"from":"w-47","to":"w-106","epoch":4,"port":44155}
  • DB:host_id=w-106、epoch=4(+1)、folder=/var/lib/dshs/users/4092b965-…/ws ✔
  • 106:dsh-100002-43771a07.scope running、端口 44155 监听、实例 HTTP 401(存活)
  • 47:guest 的 scope 已消失(只剩 admin 的)
  • 插件:business-plugins 0.3.23 / portal-entry 0.5.5 在位,特征串命中,实例日志 0 error

10.6 归档与清理

  • 源目录归档:/opt/dsh/backups/migrated/guest-4092b965-20260916.tar.gz(≈1.1 G,含 trash)⇒ 验证后删除 47 上的源目录。
  • 临时物清理:47/106 的 /tmp/{gmig,rt,nm,bp}* 已清;106 的 /root/*.sh 已清;本机的分片目录移入 _中间产物_待清理/。
  • 可复用脚本(在 _中间产物_待清理/):_relay2.sh(带校验重试的接力搬运)· _relay.sh(无校验版)· _mcn-venv-106.sh(远端重建 venv)· _gmig-pull.sh(初版并行拉取)。

11. 遗留(需另立排期)

  1. 106 仍缺 ffmpeg / ffprobe ⇒ 2026-09-16 00:2x 已解决:106 上直接 dnf install -y ffmpeg jq ripgrep(走内网源 mirrors.tencentyun.com,43 MB/s、几十秒),再符号链接进 /usr/local/dsh-runtime/bin/,并在 bwrap 沙箱内实测可执行(ffmpeg 7.0.2)。 ⚠️ 教训(重要):先测目标机自己的下载能力,别默认"只能从 47 搬" —— 106 的 dnf 内网源极快,从 47 搬 344 MB(~40 分钟)纯属绕路。
  2. 106 仍无账号 provisioner(dsh-provision.path 只在 47)⇒ 新用户被调度到 w-106 时无人建 OS 账号。本次 guest 的账号是手工 useradd -u 100002 建的。
  3. MCN 的 4 个重包未装(playwright / ctranslate2 / onnxruntime / av,≈443 MB):按既定决定暂不重建。
  4. 存量用户仍是各自一份 venv / node_modules:本方案只把 guest 迁完,共享化(§2 的三类落点)尚未实施。
  5. 106 上的遗留目录:41a9480e-…(uid 100008,8.9 M,档案 101 的一次性用户残留,PG 行已删)与两个 0 字节目录(2ade6411 / 5f4a51d2)。