mimo v2.6 flash 在docker sidecar启动问题处理过程的审计

审计结论

mimo v2.6 flash 这一轮没有走偏,方向正确,取证链扎实;但在收口前被打断,留下两个关键验证没做。继续用它大概率能自己走到正确答案,但需给一句转向指令,否则它会继续往 moby 源码深处钻,迟迟不交付可操作的修复。

过程复盘

阶段 1 — 现场取证(好)

先读 docker-compose.yml + frpc4060.toml,再看 ps / stats,确认现象:llama-frpc 显示 0B / 0B,但 State.Running=true、无 OOM、无重启。查 cgroup 证实 memory.current=4.7MB:进程活着,配额正常 → 0B/0B 是 stats 采集侧假象,不是容器死了。这个区分很关键,做对了。

阶段 2 — 第一条真线索(好)

frpc 日志全是 lookup openai.atibm.com on 127.0.0.11:53: read: connection refused(每 20 秒一次)。这不是“frps 连不上”,而是容器内 DNS 解析器本身拒绝服务。

阶段 3 — 第二条真线索(全场最有价值)

  • llama-frpc 的 netns(4026533868)≠ llama 的 netns(4026533865);
  • frpc 的 HostConfig.NetworkMode = container:93c9c5c5…,而当前 llama 容器 ID 是 f1be42…——对不上;
  • frpc 的 /proc/net/dev 里只有 lo,没有 eth0;
  • 时间线:frpc 启动于 00:37,llama 启动于 01:22(后于 frpc)。

四条拼起来真相呼之欲出:llama 在 frpc 之后被重建过,frpc 的 network_mode: service:llama 在创建时解析成旧 llama 容器的 ID,旧容器消失后 frpc 困在只剩 lo 的死 netns 里——DNS(127.0.0.11)没了,去往 127.0.0.1:8080 的转发指的也是自己而非 llama。拼图捡齐了,但这句结论没写出来。

阶段 4 — 上游验证(严谨但开始烧 token)

直调 daemon socket 做 one-shot / streaming stats,确认空 memory_stats + 零时间戳;代理拉 moby daemon/stats.go、stats_unix.go、collector.go 源码,定位到 GetContainerStats 的 NotFound/Conflict → 空 stats 分支和 getNetworkSandboxID 的容器链追踪;拉 frp README 确认 healthCheck.* 语义。

命令选择评价

合理:inspect --format、exec cat /proc/net/dev、跨 netns 读 ns 链接、journalctl --user -u docker.service(rootless 路径找对了)、daemon socket 直调。

糙:中间一个 cat /sys/fs/cgroup$(…cut…) 拼凑命令 substitution 写废、输出为空,它没察觉直接换路重查——结果对了,过程有瑕。

漏(两个最大缺口):

工具 / skill 选择评价

skill_view(web-research) 遇到内容缺失后没纠结,切到 curl + GitHub API + 代理直取 raw,符合“出网走代理”成规,应变合理。searxng 连吃 403 后换词又试一轮,属轻微恋战,好在及时收手。没乱拉无关 skill(本机 docker 方向可用 skill 本就处于 disabled),守规矩。中途一次 execute_code 胶水代码解包 bug,已自行修复重试,无后果。

分析细节:已实锤 vs 未闭环

R01frpc 进程活着,0B/0B 是 stats 采集失败实锤(cgroup + streaming 空帧 + collector 源码对上)
R02frpc 被困死 netns(仅 lo、无 eth0、DNS 拒服)实锤
R03service:llama 解析到了已不是当前 llama 的旧容器 ID强证据(ID 对不上 + 启动时间倒挂)
R04旧容器残留状态 / 经历了什么重建未闭环(没查 ps -a)
R05stats 空帧的确切错误分支(daemon 日志没抓到 collecting stats)未闭环
R06转发路径 127.0.0.1:8080 是否真的指错未闭环(没从 frpc 内探测)

潜在走偏点

P01(必须拦):frp 的 healthCheck.* 语义可能被误用。拉到的 README 章节是“Service Health Check”——那是 frps 侧负载均衡摘除不健康 proxy 的机制,单 proxy、无 LB 组时加它基本无感,更救不了“frpc 在死 netns 里”。若下一步建议“给 toml 加 healthCheck.type=http 解决问题”,就是开错药。

P02:继续钻 moby 源码收益递减。stats 为空的机制已定位到错误分支吞掉返回空帧,再往 containerd/shim 跟,对修 compose 无增量价值。修复在编排层,不在 daemon 层。

继续用它会困馅吗

不会困死,但会慢。证据驱动、无幻觉下结论,每步有真实命令输出支撑。风险只是“工程师式恋战”:在源码层求全,不先交付止血方案。转向指令(已给出):先 ① ps -a 确认旧容器状态;② 从 frpc 内探测 8080 定性转发错位;③ 编排层修复:frpc 改走 ghost_net + localIP=llama(嵌入式 DNS 服务名,不共享 netns),或保证两者同生命周期重建;可见性用 admin UI / loginFailExit,LB healthCheck 不适用单 proxy。

穿透 sidecar 公开最佳实践(结论)

社区主流是不用 network_mode: service:xxx 共享 netns(主容器一重建 sidecar 即瞎,且 sidecar 自身 stats/DNS 全随陪葬):sidecar 独立 netns、进同一 user-defined network,localIP 写主容器服务名(重建自愈);frpc 开 client admin UI + compose healthcheck 打 admin 接口;loginFailExit=true 让登录失败直接退出、靠 restart policy 形成可见 crashloop;depends_on: healthy 只管首次启动顺序,不管运行中重建。