docs(audit): night-2 ledger — default-install backup/reaper verified live, eviction shield re-drilled, OOM + k3s SIGKILL chaos, and the prioritized remaining-work list

This commit is contained in:
Lemon-miaow committed 2026-09-22 22:15:38 +08:00
1 parent 87a9f4eb25
commit edefc34a5b
1 file changed
+17
+17
View File
@@ -47,6 +47,23 @@ IPv6-only 接入(`ssh -6 -i ~/.ssh/id_ed25519 root@fdb2:2c26:f4e4:0:21c:42ff:f
- 并发:OTP 风暴 8 路 = 1×202 + 7×429 且仅铸 1 码;绑定码并发(同码/双码)见 #18 ✅ - 并发:OTP 风暴 8 路 = 1×202 + 7×429 且仅铸 1 码;绑定码并发(同码/双码)见 #18 ✅
- **reaper 全链路真机演练**(修复 #19 后):绑定挂载假世界 → `felis reaper` 一 pass:归档 tar 落盘(内容含标记文件)、`world_backups` 行 `inactive_15d`+90d 过期、**PVC 删除且宿主目录回收**、servers 行保留且 activity 时钟重置(红线②)、CRD 保留;第二 pass:伪造过期归档被驱逐(`expired=1`,文件删、行转 `deleted`),合法归档未动;`evaluated=2 reaped=1` 只动到期的世界 ✅ - **reaper 全链路真机演练**(修复 #19 后):绑定挂载假世界 → `felis reaper` 一 pass:归档 tar 落盘(内容含标记文件)、`world_backups` 行 `inactive_15d`+90d 过期、**PVC 删除且宿主目录回收**、servers 行保留且 activity 时钟重置(红线②)、CRD 保留;第二 pass:伪造过期归档被驱逐(`expired=1`,文件删、行转 `deleted`),合法归档未动;`evaluated=2 reaped=1` 只动到期的世界 ✅
### 本轮新增真机证据(第二日)
- **默认安装的备份闭环**:apply 新 bundle → 归档 PVC 自动创建(WaitForFirstConsumer,被首个 backup Job 拉绑定)→ `POST /backup` 202 → `GET /jobs` running→succeeded → 漂移 marker → `restore-backup` → 读回备份前内容 ✅
- **回收闭环(真实 k3s 布局 + 权限)**:resolvecheck(20d idle)→ CronJob 派 Job:`evaluated=2 reaped=1`;归档含 marker、PVC+宿主目录回收、`world_backups` 记 `inactive_15d`;期间先经历 `lstat /worlds/…: permission denied`(k3s storage root 0700)→ 修 ACL/root 权限后通过 ✅
- **磁盘压力三连 drill**:①1e6 自定义类:游戏 pod 先走、控制面随后仍被逐(kubelet ranked/evicted 日志)→ 镜像 GC → ErrImagePull;②改内建 `system-cluster-critical` 后:`cannot evict a critical pod` × felis-api/operator/registry,全部保持 Running;③恢复阶段实测 `DiskPressure` 条件 ~5min(eviction-pressure-transition-period)转 False,被 GC 的游戏镜像按 runbook 重导入后 25s 恢复 ✅
- **混沌**:SIGKILL k3s 主进程 → kubectl 与 felis-api ready 均在 **10s** 内恢复(api pod 本身未被重启)✅;内存压力(2.6G tmpfs 满写):无 OOM kill、无人被逐(swap 5.9G 吸收 + 内核回收),控制面不受影响 ✅
- **构建链路定位(未修,见下一节)**:Kaniko/Trivy 默认镜像是外部的 → 已加 `[registry] kaniko_image/trivy_image/build_cpu_limit/build_mem_limit` 覆写;上下文跨 ns 不可挂载(PVC 不能跨 ns)是设计级缺口,s3 lane 也缺凭据注入 ✅(证据:`internal/submit/blobstore.go:40`、`cmd/felis/api.go` contextBase 分支、jobspec 无 volumes/env)
## 结论:离"生产可用"还差什么(按优先级)
1. **构建链路的上下文通道(唯一的功能级缺口)**。用户模组提交 → 审批 → Kaniko 构建这条 lane 需要跨命名空间传递 context 的机制;PVC 不能跨 ns,s3 lane 又缺 build pod 侧凭据注入。两条候选:a) 官方走对象存储(在 bundle 里加 MinIO 或让 operator 配外部 S3 + 为每次构建挂 per-build Secret + netpol 放行 endpoint);b) 在 felis-build 里做 context handoff(一个控制面任务把 blob 落到 build ns 的 PVC)。做 a) 时顺带把 kaniko/trivy 镜像推入内建 registry。
2. **镜像耐久**:kubelet 仍可能 GC 掉"当前无人使用"的镜像(游戏镜像已实测发生)。把控制面与游戏镜像推入内建 registry 并让 Deployment/StatefulSet 引用 registry 路径,可免去"事故后人工重导入"。本轮已用 runbook(troubleshooting §13b)兜住。
3. **PG 级契约测试**:PGRepo 与接口/fake 漂移已抓到 3 例(#16/#17/#18)且单测全绿也发现不了;建议对"注释承诺了字段/错误码/生命周期"的方法加 Postgres 集成测试。
4. **面板把 /jobs 显示出来**:API 已有出口(#7),`ServerBackups` 页加一块"最近操作"即可让普通用户看见失败原因。
5. **多节点回收**:reaper CronJob 无 nodeSelector,多节点需按卷所在节点加 selector(代码与文档均已标注,未实现调度约束)。
6. **告警**:felis_* 指标已全有生产者,但无非告警;磁盘/内存阈值告警建议随部署一并给出。
## 系统性观察 ## 系统性观察
- **PGRepo 与接口契约/fake 漂移**(#16/#17/#18):`fakeRepo` 与接口注释是对的、PG 实现在细节上落后,单测全绿也发现不了。建议后续引入 PG 级契约测试(testcontainers 或针对关键写路径的集成测试),重点覆盖「接口注释承诺了字段/错误码/生命周期」的方法。 - **PGRepo 与接口契约/fake 漂移**(#16/#17/#18):`fakeRepo` 与接口注释是对的、PG 实现在细节上落后,单测全绿也发现不了。建议后续引入 PG 级契约测试(testcontainers 或针对关键写路径的集成测试),重点覆盖「接口注释承诺了字段/错误码/生命周期」的方法。