PROJECT ID · PRJ-002
MIRROR MESH:内网镜像源与缓存层
给所有内网机器一套可用的软件源:按机架就近命中、未命中才回上游、证书与上游同步。目标是让"装包失败"不再是一个需要人介入的事件。
目标
内网有两百多台机器,其中大部分不能直连外网。在这个前提下,装包失败是最不该 发生的一类故障——它的原因通常在网络策略上,而表现却是编译器报错,排查路径很长。
这个项目把”取包”这件事收敛成一条可控的路径:客户端只配置一个源,剩下的事情 (就近、缓存、回源、证书)都在服务端决定。
数据流
上图是一条请求的完整走向。三个机架各自的客户端都指向哈希层,由它按机架固定到 一个镜像节点;只有缓存里没有的包才会回上游,且回源是串行的、限速的, 不会在发布的瞬间把上游打满。
命中率不是目标,回源的可预测性才是
92% 的命中率是个结果,不是被优化的对象。真正在意的是剩下那 8%:
- 回源带宽有上限。 上游同步的是差分索引,不是全量仓库。
- 回源失败不阻塞客户端。 拿不到就报 502,而不是让连接挂在那里等超时。
- 缓存的淘汰是按大小而不是按时间,因为老版本的包偶尔还会被装回来。
部署
# 容器起停,配置全在仓库里
docker compose -f deploy/mirror-mesh.yml up -d
# 同步状态与最近一次上游时间
curl -s http://mirror.lanunion.example/-/status | jq '{last_sync, packages}'
节点本身的配置由 Ansible 下发,两个镜像节点之间不做副本——它们是互相独立的 缓存,这样任何一台宕机都只影响它自己那份缓存,不会连带。
已知限制
- 不缓存容器镜像。 容器仓库的体积与索引结构差异太大,目前单独一套, 不在这个项目里。
- 证书一年一换,换的时候客户端要一起改。 这一点反复出过问题, 处理办法见 LAB LOG 027。
- 哈希层是单点。 它只是一个 nginx,重启在秒级,但重启期间所有装包都会失败。