docs(audit): batch-45 — modpack base-image chain (#70/#71/#72), submission-to-server capstone, tooling fixes (#69/#73/#74)

This commit is contained in:
Lemon-miaow committed 2026-09-24 03:19:21 +08:00
1 parent 96aa8176cd
commit 3ed8bd7be9
1 file changed
+53 -1
+53 -1
View File
@@ -45,7 +45,7 @@ IPv6-only 接入(`ssh -6 -i ~/.ssh/id_ed25519 root@fdb2:2c26:f4e4:0:21c:42ff:f
| 14 | controller-runtime 日志噪音 | ✅ 修复:SetLogger 接 slog(`a415246`) |
| 15 | reaper 启用未演练 | ✅ 已演练(见"第二日"节;CronJob 仍 `suspend=true` 防误删) |
## 可达性分级(#1–#68;#62 立案后剔除)——这些缺陷真实使用中到底谁能踩到
## 可达性分级(#1–#74;#62 立案后剔除)——这些缺陷真实使用中到底谁能踩到
回应质疑"是不是全在测边界条件 / 只有内部 hook 才能触发":
@@ -128,6 +128,8 @@ IPv6-only 接入(`ssh -6 -i ~/.ssh/id_ed25519 root@fdb2:2c26:f4e4:0:21c:42ff:f
第四十三批追加(二):#68(构建 context 拉取单次尝试——控制面滚动/重启/驱逐恰好撞上构建窗口时,fetch initContainer 一次 `connection refused` 直接打成终态 `Failed`;`BackoffLimit=0` 无第二次 Pod,代价 = 人工重审重提)②(运维:升级/重启/故障恢复撞上正在进行的构建;构建量大时概率上升)。
第四十五批追加:#69(README 中英"审批通过后自动构建**并部署**"过度承诺——数据模型无目标服务器、部署实为"选用该镜像";① 轻);#70(kaniko 拉内建底座默认 HTTPS——`--insecure` 只覆盖推,任何 `FROM registry.felis.svc:5000/…` 构建必败 ①);#71(kaniko 以 drop-ALL 解包底座层,chown 必败——任何非 scratch 底座必败 ①);#72(trivy 扫 jar 必拉 Java DB、被 egress 锁拒绝——含 jar 即所有真实模组包的构建必败 ①);#73(bootstrap 测试在跑 k3s 的主机上必假失败 ④ 工具);#74(console 断连测试读写竞态 flaky ④ 工具)。
## 已验证事实(正向清单)
- 安装→hook 发码→Owner 绑定→passkey(虚拟认证器)→面板管理员全链路 ✅
@@ -804,6 +806,51 @@ IPv6-only 接入(`ssh -6 -i ~/.ssh/id_ed25519 root@fdb2:2c26:f4e4:0:21c:42ff:f
- 连续镜像构建(docker build)把 VM 根盘从 11G free 压到 4.3G;`docker builder prune -af` 一键回收 **6.5G**(回 11G free)。即每轮全量重建约需 5–7G 构建缓存空间;生产主机根盘建议 ≥40G 并定期 prune(如需可在部署文档补一行,本批未改码)。
- 留档:`/root/bigctx.tar.gz`(200MiB 上下文原件)、`/root/bigctx/`、`/root/stats44.log`、`/root/stats44-build.log`;提交 `sub-cc160b3ad19080f9`(blob 与 `user-uploads` 镜像保留作尺寸样本);镜像 `e2e/conc-b44-{1,2,3}:latest`。
### 本轮新增真机证据(第四十五批:模组构建链三连修 #70/#71/#72 + 提交→装服全链闭环 + 文档/测试修 #69/#73/#74)
**零、现场**:控制面 auditfix63→66(每修一版真机重演);本批目标 = 真实用户会写的那种模组包 Dockerfile(`FROM <平台底座>` + 内容层)。此前所有构建演练都是 `FROM scratch`——用户真实形态的第一步从未跑过,本批连撞三个缺陷。
**一、#70(`ac403b9`):kaniko 拉底座缺 pull 侧 insecure 标志**
- 红证据(真机):提交 `FROM registry.felis.svc:5000/felis/paper:demo`(`bld-1790189685537480076`)→ kaniko `Retrieving image manifest …` 后即败:`Get "https://registry.felis.svc:5000/v2/": http: server gave HTTP response to HTTPS client`。根因:Job 只给了 `--insecure --skip-tls-verify`——kaniko v1.24 `--help` 实测二者均只覆盖 **push**,拉取默认 HTTPS,撞上明文 registry。
- 修复:补 `--insecure-pull` / `--skip-tls-verify-pull`(对称补齐;构建命名空间 egress 本就只许 DNS/内建 registry,不扩大可达面)。单测断言两 flag 在参。
- 真机复验:下一次构建 `Retrieving image manifest` 不再报错,进入解包阶段(随即暴露 #71)。
**二、#71(`6e47730`):kaniko 解包底座层被 drop-ALL 卡死**
- 红证据(真机):`error building image: error building stage: failed to get filesystem from image: chown /etc/gshadow: operation not permitted`——kaniko 以 root 解包 tar 层要把文件 chown 到层里记录的属主(root:shadow 等),drop-ALL 后 CAP_CHOWN/CAP_FOWNER/DAC_OVERRIDE 全无。`FROM scratch` 全用 COPY(属主= kaniko 自己)所以从未暴露;**任何真实底座**必触。
- 修复:仅 kaniko 容器补回最小能力集 `CHOWN + DAC_OVERRIDE + FOWNER`(fetch/trivy 保持 drop-ALL 基线;单测断言"恰好三枚"防漂移)。
- 真机复验:解包通过、COPY、推送成功(进入 trivy 阶段,撞上 #72)。
**三、#72(`b14bacb`):trivy 扫 jar 必拉 Java DB——egress 锁下必败**
- 红证据(真机):kaniko 全绿后 trivy `FATAL … Unable to initialize the Java DB … failed to download artifact from mirror.gcr.io/aquasec/trivy-java-db:1: connection refused`。Java DB 按需下载:镜像一有 jar 就触发——模组包 = jar 集合,故所有真实用户构建都会倒在扫描门;旧构建全 scratch(无 jar)从未触发。
- 修复:新增 `[registry] trivy_java_db_repository`(→ `--java-db-repository`,与 vuln-DB 旋钮对称);installer carry 白名单收录;§8e 配方补 Java DB 镜像步骤;deferred-seams 更新。
- 真机复验(第 4 次尝试,auditfix66):Job spec 实测含 `--db-repository registry.felis.svc:5000/mirror/trivy-db:2 --java-db-repository registry.felis.svc:5000/mirror/trivy-java-db:1`;扫描 `ubuntu 26.04` + `paper/paper.jar` + `pebble` 全 0 漏洞;**Job Complete**(全链 27s,`bld-1790190788310114143`)。
**四、capstone:提交 → 装服 → 起服,全链闭环(零缺陷)**
- 第 4 次尝试产物 `user-uploads/sub-c006cbd633317ccb:latest`(= `felis/paper:demo` + 用户 marker,经完整提交管道构建):
- 白名单自动收录(`source=built`)→ 产品路由 `PATCH /api/v1/servers/test-one {"image": …}` **200**(`image_not_whitelisted` 门通过);
- `POST /servers/test-one/wake` 202 → pod `test-one-0` Running 1/1(25s 内);
- `kubectl -n minecraft exec test-one-0 -- cat /felis-probe-marker.txt` → **`felis-probe44-ok`**(用户构建上下文的内容确在运行中的服务器里);
- 服务器日志 `Done (4.678s)!`(paper 完整启动);RCON 线程应答平台就绪探针;
- 收尾:stop 202、pod 消失、镜像回滚 `felis/paper:demo`、desiredState=Stopped。
- 口径:这是"玩家上传模组包 → 服主审批 → 自动构建 → 选用为该服镜像 → 起服"的机制全链(真实客户端进服仍按决定跳过)。
**五、#69(`5cbfa89`):README 过度承诺"自动部署"**
- 复核(读全):提交数据模型无目标服务器字段;approve→build→白名单是唯一自动化;部署 = 服务器编辑框选镜像(产品路由与 UI 均在);面板文案本身只承诺"自动触发安全构建"。
- 修复:README 中英两行改为"自动构建;产物进入镜像白名单,可直接选用为服务器镜像完成部署"。可达性 ①(轻)。
**六、#73(`2961beb`):bootstrap 测试在跑 k3s 的主机上必假失败(工具级)**
- 红证据:VM(真实 k3s 主机)跑 `bootstrap_test.sh`(**原版同现**)→ `FAIL a missing worlds root is warned about`:用例拿真实路径 `/var/lib/rancher/k3s/storage` 期望 WARN,而该目录在"安装器真正要服务的机器"上必然存在 → 假红;CI 从未见到(runner 无此路径)。
- 修复:warn 情形改用保证不存在的路径;并把 `trivy_db_repository` / `trivy_java_db_repository` carry 断言补齐。VM 复跑 **140 PASS / 0 FAIL**。
**七、#74(`96aa817`):CI flaky——console 断连测试读写竞态(工具级)**
- 红证据:run `35907662213`(纯 README 提交)go 作业红:`TestServerConsoleDisconnectTeardown: expected the first event before disconnect, got ""`;`gh run rerun --failed` 即绿 → 竞态确认。
- 根因:测试只等"源读到第一行"就 cancel,"中继把事件写入响应"尚未发生;cancel 落进缝里时 body 为空。
- 修复:加 `firstDataWriter` 信号(写完成后再 cancel,写→读有 happens-before);本地 `-count=60` 与 `-race ×5` 全绿;CI 复跑 `5cbfa89` = success。
**八、运维注记(非缺陷)**
- 升级滚动撞 kubelet **ephemeral-storage 压力**:auditfix64 滚动时新 api/operator pod `Pending 4m46s`(事件 `untolerated taint(s)`),02:58:12 kubelet eviction manager 回收后自动调度成功。诱因 = 构建把根盘压到 89%(docker 构建缓存 + kaniko/emptyDir 临时层);`docker builder prune -af` 两清共回收 ~11G,余 11G free。生产清单:根盘 ≥40G + 升级前清构建缓存(与批 44 注记合并)。
- 中间失败构建留下的 registry 镜像(`user-uploads/sub-83f6…`、`sub-171e…` = 已推未过门;`sub-c006…` = capstone 产物)留档;测试服 `test-one` 已回 `felis/paper:demo` + Stopped;docker 停。
## 结论:离"生产可用"还差什么(按优先级)
1. ~~构建链路的上下文通道~~ ✅ **已修**(`f79e5eb`/`02fd2de`,真机全链路含拉回校验;Trivy DB 需按 §8e 镜像一次)。
@@ -830,6 +877,9 @@ IPv6-only 接入(`ssh -6 -i ~/.ssh/id_ed25519 root@fdb2:2c26:f4e4:0:21c:42ff:f
22. ~~构建层资源回收~~ ✅ **已修**(第四十三批:#67 build Job TTL——完成 Job/Pod 不再无限堆积;真机:新构建 Job `ttl=604800` + 旧 Job 打 30s TTL 实测被 TTL 控制器收走。同批:6 轮生命周期循环 + operator/api/pg 三处注入全绿、PG 503 语义复验、30 路并发全 200)。
23. ~~构建上下文拉取的短暂断连~~ ✅ **已修**(第四十三批追加:#68——fetch-context 有界重试〔45s 窗口 / 3s 间隔;4xx 不重试〕;真机:api 停机期连续 8 次拒连全部重试、恢复后构建 32s Complete;正常路径无重试开销。附:演练升级暴露的 `FELIS_IMAGE` 两代错位已对齐 auditfix63)。
24. ~~modpack 规模上下文全链 + 并发构建~~ ✅ **已演练**(第四十四批:200MiB 上下文上传 0.44s → 批准 → 构建全链 13s、三路并发构建全绿;TTL 与玩家可见面在规模下复验,零缺陷。见该批节)。
25. ~~内建底座构建(`FROM registry.felis.svc:5000/…`)~~ ✅ **已修并真机闭环**(第四十五批三连修:#70 拉取缺 `--insecure-pull`、#71 drop-ALL 卡解包、#72 trivy Java DB 未镜像——"真实模组包"形态的三个必踩点;修复后 paper 底座构建 27s Complete、`paper.jar` 扫描 0 漏洞)。
26. ~~提交 → 装服 → 起服 闭环~~ ✅ **已演练**(第四十五批 capstone:构建产物 PATCH 为服务器镜像〔白名单门通过〕→ wake → Running 1/1 → 用户 marker 可读 + `Done (4.678s)!`;test-one 已复原为 paper:demo/Stopped)。
27. ~~文档与测试工具面~~ ✅ **已修**(第四十五批:#69 README 部署承诺对齐实现;#73 bootstrap 测试密闭化〔VM 140 PASS〕;#74 console 断连测试消抖;CI 全绿)。
## 剩余待演练队列(截至第四十三批)
@@ -841,6 +891,7 @@ IPv6-only 接入(`ssh -6 -i ~/.ssh/id_ed25519 root@fdb2:2c26:f4e4:0:21c:42ff:f
- ~~全仓覆盖面对账~~ ✅ 已复核(第四十二批:模块×台账逐项对账无盲区;批次产出为文档/本地工具层面的修复,见该批节)。
- ~~长稳/故障注入(首轮)~~ ✅ 已完成(第四十三批:6 轮起停循环 + 3 处注入 + PG 断连 503 + 30 路并发 + 25 分钟持续轮询;见该批节)。
- ~~modpack 规模上下文 + 并发构建~~ ✅ 已完成(第四十四批:200MiB 上下文全链 13s + 并发 ×3 全绿;见该批节)。
- ~~提交 → 装服 全链(含平台底座 FROM)~~ ✅ 已完成(第四十五批:三连修 #70/#71/#72 + capstone 提交→装服→起服;见该批节)。
**队列现已清空。**(真实游戏客户端进服已按决定跳过,用内部 mint/approve hook 链替代;不依赖客户端的最大真机面见第四十批节 + 第四十一批节〔装载器三服起服〕;第四十二批为覆盖面对账复核。)
@@ -873,3 +924,4 @@ IPv6-only 接入(`ssh -6 -i ~/.ssh/id_ed25519 root@fdb2:2c26:f4e4:0:21c:42ff:f
- 第四十三批工具与留档:控制面三处 = `registry.felis.svc:5000/felis/felis:auditfix62`(含 #67;镜像源 `10.43.182.43:5000/felis/felis:auditfix62`,宿主 docker build 后 `docker push 10.43.182.43:5000/...`);`/opt/felis/src` = `2755e41` 快照(上一版 `src.bak42`);owner 会话重铸 = `bash /root/mint-owner-43.sh`(cookie 落 `/tmp/owner-jar43.txt`);直构触发(含 TTL 检查)= `curl -sk -b /tmp/owner-jar43.txt -X POST https://127.0.0.1:30443/api/v1/images/build -H 'Content-Type: application/json' -d '{"image_ref":"registry.felis.svc:5000/e2e/ttl-probe:latest","dockerfile":"FROM scratch\nLABEL felis=x\n","context_ref":"http://felis-api-internal.felis.svc.cluster.local:8081/api/v1/internal/submissions/sub-bf7dc18e9dd97dc2/context"}'` → `kubectl -n felis-build get job build-bld-<id> -o jsonpath='{.spec.ttlSecondsAfterFinished}'` 应为 `604800`;压测编排 `/root/soak43.sh`(日志 `soak43.log`,含 6 轮循环 + 3 注入)、长轮询 `/root/poll43-long.sh`(日志 `poll43-long.log`);镜像构建日志 `/root/felis-image-build43.log`。注意:`lobby`/`login` 是保留名,internal per-server 路由(status/wake 等)对它们**按设计**返回 400,勿作缺陷误报。
- 第四十三批追加(#68)留档:控制面 api/operator/reaper 镜像 + api/operator `FELIS_IMAGE` = `registry.felis.svc:5000/felis/felis:auditfix63`(`felis version` = `v0.0.0+fix63`;升级时 `set image` 与 `FELIS_IMAGE` env 必须成对改,否则构建 Job 的 fetch 容器会悄悄用旧镜像);`/opt/felis/src` = `b76d0ac` 快照(上一版 `src.bak43` = `2755e41`);复刻 Job `/root/job68-new.json`(由红证据 Job `build-bld-1790187851749257160` 派生:换名 `build-retry68`、剥 controller uid 标签与 selector、镜像改 auditfix63、复用 `felis-service-token` Secret);重演验证法:`kubectl -n felis scale deploy/felis-api --replicas=0` → `kubectl -n felis-build create -f /root/job68-new.json` → `kubectl -n felis-build logs <pod> -c context-fetch`(应见 `connection refused; retrying`)→ `scale --replicas=1` → Job 收敛 `Complete`;对照:api 在线直构成功且 fetch 日志无重试行。
- 第四十四批工具与留档:200MiB 上下文构造 = 5×40MiB `head -c 41943040 /dev/urandom` + `Dockerfile`(`FROM scratch` + `COPY payload /payload`),`tar -czf /root/bigctx.tar.gz Dockerfile payload`;上传 = `curl -sk -b /tmp/owner-jar43.txt -X POST -H "Content-Type: application/gzip" --data-binary @/root/bigctx.tar.gz https://127.0.0.1:30443/api/v1/me/submissions/<id>/context`;采样 = `k3s crictl stats`(此版 **无 `--no-trunc`**,列解析取 `$2=NAME $4=MEM`);docker 缓存清理 = `systemctl start docker && docker builder prune -af && systemctl stop docker`;留档 `/root/stats44.log`、`/root/stats44-build.log`、提交 `sub-cc160b3ad19080f9`、镜像 `e2e/conc-b44-{1,2,3}`。
- 第四十五批工具与留档:从平台底座构建的配方 = 提交上下文含 `Dockerfile`(`FROM registry.felis.svc:5000/felis/paper:demo` + `COPY marker.txt /felis-probe-marker.txt`);装服验证 = `PATCH /api/v1/servers/test-one {"image":"registry.felis.svc:5000/user-uploads/<sub>:latest"}` → `POST /servers/test-one/wake` → `kubectl -n minecraft exec test-one-0 -- cat /felis-probe-marker.txt`;trivy 双 DB 镜像 = `mirror/trivy-db:2` + `mirror/trivy-java-db:1`(Java DB digest `5766dfbb…`;两键在 `/etc/felis/felis.{host,pod}.toml` 与 felis-config Secret 双副本);`bootstrap_test.sh` 需在 Linux 跑(VM 留档 `/root/btest72/`,应 140 PASS);本批提交样本 `sub-{b45d416f4af811ef(无镜像),83f677e41acd80c3,171e8f967f0de3bc,c006cbd633317ccb,cc160b3ad19080f9}`;留档 `/root/probe44/`、`/root/probe44.tar.gz`、`/root/probe44*.sid`。