SOP — Harbor 预检查「只读探测批量化」改造(probe_batch_20261008)¶
变更对象:
services/harbor/utils/precheck.py(HarborPreCheck.run_all) 变更类型:C 类(改工程代码;只改只读探测的打包方式,判定与文案不动) 撰写:2026-10-08
1. 背景¶
HarborPreCheck.run_all 对每台 harbor 主机串行执行约 11 个 check。经排查:
- 通用静态事实(ssh/os/clock/root/selinux/disk_space 等)已由共享库
PreCheckBase.prefetch合并成「每台一条 shell」,无洼地; - 领域专有检查(
check_data_mount/check_ports/check_docker_repo/check_upstream/check_cert_material,以及 k8s 侧check_containerd) 仍在各自方法内用self._ssh.run(host, 单条命令)逐项独立往返—— 单台 harbor 主机因此多出 11 条往返(ss/ping/findmnt/6×curl/openssl…), k8s 节点多出 1 条。这是本工程唯一未批量的只读探测洼地。
触发条件:三件套改造(同主机拼一段 shell / 主机间并发 / 进程内探测缓存)已在
共享库与 node_access.py / harbor_host.py 落地,本工程预检查是最后一块。
2. 目标¶
把领域专有只读探测并入「每台一次 shell」:
- 可验证状态一:一次
precheck运行,每台主机恰好 1 条远端 shell (改造前 harbor 主机 12 条、k8s 节点 2 条); - 可验证状态二:新旧变更清单(findings)逐条完全一致,报告内容不变;
- 可验证状态三:判定表达式、findings 文案、
skip_checks过滤、run_all 中 check 的调用顺序一律不动;变更类命令一律不动(本工程预检查全部只读)。
3. 前置条件¶
- 操作机
services/harbor/.venv/bin/python可用;共享库.pth已挂载 (precheck_module/paramiko_module/ssh_executor可导入)。 - 目标机 root 免密(
config/default.yaml的nodes),本环境实测可达。 - 不改共享库:
~/py_public_modules/*(precheck_module/base_module等) 一律不动;本次只复用其既有能力(build_probe_shell/parse_probe_output/PreCheckBase._probe/_probe_cache)。 - 备份已落盘:
probe_batch_20261008/backup/precheck.py(见第 7 章)。
4. 影响范围¶
- 主机:1 台 harbor(
192.168.31.31)+ 4 台 k8s(192.168.31.10/13/14/15)。 - 不动服务:仅本地改一个 Python 文件;远端只发只读探测命令,不需停服、 无窗口期。
- 命令语义不变:
main.py precheck/plan/deploy-*/drift等子命令的 参数、输出与返回码不变(gate/has_block逻辑未动)。 - 唯一探测文本变化:3 条 curl 写出口由
-w '%{http_code}'改为-w '%{http_code}\n'(原因见第 5 章步骤 4「坑」),取值不变。
5. 分步操作¶
实现体:
utils/precheck.py(HarborPreCheck)。下列命令为人工复现的等价操作, 实际执行以实现体为准。
步骤 1:备份¶
cd /home/rain/Documents/services/harbor
mkdir -p probe_batch_20261008/backup
cp -p utils/precheck.py probe_batch_20261008/backup/precheck.py
sha256sum utils/precheck.py probe_batch_20261008/backup/precheck.py # 应一致
预期:两行 sha256 相同;台账见 backup/README.md。失败判断:不一致即重做备份。
步骤 2:改造 precheck.py(每台一次 shell + 本地判定)¶
新增「只读探测」小节(实现体 utils/precheck.py L66–177):
_harbor_probes(host)/_k8s_probes(host):把原有各 check 里的命令原样收拢 成「键 → 命令原文」字典(data_mount/ports_ping/ports_ss/docker_repo/upstream:<domain>/cert_material/containerd);_prefetch_all(hosts):按主机把「static_probes()通用静态事实 + 领域专有探测」 合并,用共享库build_probe_shell拼成一段 shell,同一台一次下发;主机间用ThreadPoolExecutor并发(_PROBE_WORKERS=8,超时_PROBE_TIMEOUT=300);_dprobe(host, key):取样统一入口——命中_probe_cache即不再下发,未纳入 批量(独立调用)时单次下发,语义与批量一致;- 各
check_*方法把self._ssh.run(host, <单条命令>)换成self._dprobe(host, "<键>"), 其余判定/文案逐字保留; run_all在进入角色循环前先self._prefetch_all(harbor_hosts + k8s_hosts), 并把role_nodes("k8s")复用为k8s_hosts。
坑(本轮上机对照实测抓到):build_probe_shell 在每条命令后跟
echo "@@rc_<键>=$?"。curl -w '%{http_code}' 不输出换行,会让取到的值变成
200@@rc_docker_repo=0 → docker_repo 误判 BLOCK、upstream 误判 WARN。
旧逐条路径无此问题(每次独立往返)。修法:三条 curl 写出口补 \n
(-w '%{http_code}\n')。任何经 build_probe_shell 批量化的探测命令都必须以
换行结尾,否则段标记会粘进取值——这是复用共享库批量能力时的通用陷阱。
步骤 3:语法校验¶
cd /home/rain/Documents/services/harbor
.venv/bin/python -m py_compile utils/precheck.py probe_batch_20261008/selftest.py
预期:无输出、退出码 0。失败判断:报 SyntaxError → 检查改动后重试。
步骤 4:离线自测(不接触远端)¶
cd /home/rain/Documents/services/harbor
.venv/bin/python probe_batch_20261008/selftest.py
预期:RESULT: PASS(见第 6 章)。失败判断:见第 7 章回滚。
步骤 5:上机新旧对照(只读,可复现)¶
cd /home/rain/Documents/services/harbor
# 新版存档
cp -p utils/precheck.py /tmp/precheck.new.py
# --- 新版 ---
: > logs/harbor.log
t0=$(date +%s.%N); .venv/bin/python main.py precheck >/tmp/new.out 2>&1; rcn=$?; t1=$(date +%s.%N)
echo "NEW rc=$rcn cmds=$(grep -c 开始执行命令 logs/harbor.log) wall=$(echo "$t1-$t0"|bc)"
cp "$(ls -t reports/precheck-precheck-*.md | head -1)" /tmp/new_report.md
# --- 旧版(用备份覆盖)---
cp -p probe_batch_20261008/backup/precheck.py utils/precheck.py
: > logs/harbor.log
t0=$(date +%s.%N); .venv/bin/python main.py precheck >/tmp/old.out 2>&1; rco=$?; t1=$(date +%s.%N)
echo "OLD rc=$rco cmds=$(grep -c 开始执行命令 logs/harbor.log) wall=$(echo "$t1-$t0"|bc)"
cp "$(ls -t reports/precheck-precheck-*.md | head -1)" /tmp/old_report.md
# --- 立即还原并校验 ---
cp -p /tmp/precheck.new.py utils/precheck.py
cmp -s /tmp/precheck.new.py utils/precheck.py && echo RESTORE_OK || echo RESTORE_FAIL
预期:NEW cmds=5 / OLD cmds=20;RESTORE_OK。命令数取自日志里
开始执行命令(SSHExecutor.run 每次远端调用记一行;日志为追加,测前先
truncate/: > 清空,勿用累计计数)。
6. 验证¶
- 自测(
probe_batch_20261008/selftest.py,桩替换远端): [1]新旧 findings 逐条一致(new==old,本例 34 条);[2]新方案每台恰好 1 条 shell;旧方案 harbor 12 / k8s 2;[3]负向对照复现「无\n的 curl 写出口粘行」语义(证明桩忠实)。- 上机对照(2026-10-08 实测):
- 报告内容一致(忽略「生成时间」行后
diff为空):两版均BLOCK 0 / WARN 0 / INFO 34; - 远端命令数 20 → 5(-75%),墙钟 8.44s → 7.52s;
RESTORE_OK且还原后 sha256 与新版存档一致。- 回归:
main.py precheck返回码、报告结构、gate判定未变。
7. 回滚¶
- 备份位置:
probe_batch_20261008/backup/precheck.py(台账backup/README.md)。 - 回滚步骤:
cd /home/rain/Documents/services/harbor
cp -p probe_batch_20261008/backup/precheck.py utils/precheck.py
cmp -s probe_batch_20261008/backup/precheck.py utils/precheck.py && echo ROLLBACK_OK
- 回滚后验证:重跑
main.py precheck,命令数应回到每台 harbor 12 / k8s 2 条。 - 纯代码回滚,无远端状态残留(本变更不改远端任何东西)。
8. 风险说明¶
| 风险 | 缓解 |
|---|---|
| 批量 shell 超时(合并后单条超时) | _PROBE_TIMEOUT=300;各 curl 自身仍有 -m 10/20 上限;实测单台 ~7s |
| 单条探测命令无换行 → 段标记粘进取值(已实测发生) | 所有经批量的命令以换行结尾;curl 写出口补 \n;selftest 负向对照兜住 |
| 把 k8s 探测混到 harbor 主机(角色错配) | _domain_probes 按 role_nodes 分派,harbor/k8s 各取所需 |
| 探测失败被误判成「通过」 | 批量解析沿用 _probe_cache_from:rc=-1 记 unknown,各 check 仍按原判据落 WARN/BLOCK |
| 并发过高被 sshd 拒连 | _PROBE_WORKERS=8,主机数 5,实测无拒连 |
附录 A:本文档交付物清单¶
| 交付物 | 路径 | 说明 |
|---|---|---|
| 变更实现体 | services/harbor/utils/precheck.py |
改造后(新方案) |
| 备份 | probe_batch_20261008/backup/precheck.py |
改造前原文件 |
| 备份台账 | probe_batch_20261008/backup/README.md |
原路径/时间/回滚动作 |
| 离线自测 | probe_batch_20261008/selftest.py |
桩替换远端,断言清单一致 + 每台 1 条 shell |
| 本 SOP | probe_batch_20261008/SOP.md |
本文件 |
| 上机报告 | reports/precheck-precheck-*.md |
新旧两份,内容一致 |
RUNBOOK:本变更不改动任何面向使用的命令与输出语义,既有 RUNBOOK (
../../k8s_ins/ghcr-slow-20261001/RUNBOOK.md)无需更新。
附录 B:实测命令数 · 墙钟¶
| 方案 | harbor 主机命令数 | k8s 节点命令数 | 合计 | 墙钟 (s) | 报告\n清单 |
|---|---|---|---|---|---|
| 旧(备份) | 12 | 2 | 20 | 8.44 | BLOCK 0 / WARN 0 / INFO 34 |
| 新(本方案) | 1 | 1 | 5 | 7.52 | BLOCK 0 / WARN 0 / INFO 34 |
- 口径:命令数 =
logs/harbor.log中开始执行命令行数(每次运行前清空日志); 墙钟 =.venv/bin/python main.py precheck的实测耗时;清单 = 报告正文(忽略生成时间)。 - 数据来源:2026-10-08 实测;旧版由
backup/precheck.py覆盖后运行,跑完已cmp校验RESTORE_OK。
来源:
/home/rain/Documents/services/harbor/probe_batch_20261008/SOP.md| 最后更新:2026-10-08 03:18(由build/sync.py同步,请勿在站点侧修改)