Zot 高可用部署实操:三节点集群从零搭到上线
【免费下载链接】zotzot - A scale-out production-ready vendor-neutral OCI-native container image/artifact registry (purely based on OCI Distribution Specification)项目地址: https://gitcode.com/GitHub_Trending/zo/zot
单机 Zot(基于 OCI 规范的容器镜像仓库)跑在生产上,最终会撞上两堵墙:一台节点挂了就是整库不可用,单机的磁盘和带宽有上限。Zot 高可用部署的核心,是把"一台机器"换成"三个节点 + 共享会话层 + 统一入口"。下文按"会话层 → 计算层 → 接入层"的依赖顺序搭建一个三节点 Zot 集群,每层收尾都留了一个可验证的检查点。
单机扛不住的两个信号
结论:出现下面任一信号,就该考虑上集群,而不是继续加单机配置。
- 峰值推/拉流量逼近单机网卡或磁盘上限,扩容空间已经很小;
- 节点一次计划内重启就让整库中断几十秒,CI 流水线无法容忍。
规模上,三台是最小可用配置:两节点既没有冗余去维护,也没有仲裁可用。硬件按每台 4C8G、50GB 以上可用磁盘、节点间延迟 10ms 以内准备即可。
架构总览:接入、计算、存储三层分工
结论:整体拆成三层。接入层(HAProxy)负责流量分发与坏节点摘除;计算层(三个 zot 进程)无状态,任意节点都能处理任意请求;存储与会话层(共享对象存储 + Redis)承载数据和共享的登录状态。
常见做法有两类。一类是各节点同构配置、会话和缓存全部外置,入口轮询全部分发请求,这是本文主线。另一类是仓库级亲和路由:在配置里声明members与hashKey,同一仓库的请求固定落到同一节点,路由逻辑见 pkg/cluster/cluster.go(用 SipHash 防哈希碰撞攻击),完整配置模板可对照 examples/scale-out-cluster-cloud/config-cluster-member0.json。
前置:三台机器、Redis、HAProxy
结论:动手前先确认三样依赖就位——Docker 20.10+、Redis 6.0+、HAProxy 2.0+。
先拉一份样例配置,后文所有 json 都基于它改,只动端口和路径:
git clone https://gitcode.com/GitHub_Trending/zo/zot cd zot拿到 examples/ 下的配置模板后,后续每步只需替换地址类字段。
第一层:Zot Redis 会话存储,先把登录状态搬出本地
结论:会话与缓存不外置,节点越多越互相打架,这是第一步,也是最容易漏的一步。
单机跑时,zot 把登录会话放在本机内存里,请求被轮询到别的节点就掉认证。把会话驱动指到 Redis,所有节点共享同一份登录态。以 examples/config-remote-session-store-redis.json 为底,关键字段如下:
{ "distSpecVersion": "1.1.1", "http": { "address": "127.0.0.1", "port": "8080", "auth": { "sessionDriver": { "name": "redis", "url": "redis://127.0.0.1:6379", "keyprefix": "zotsession" } } }, "storage": { "rootDirectory": "/var/lib/zot" } }sessionDriver指向同一台 Redis,keyprefix用于和同实例上的其他业务键隔离。改完这处,登录态就不再绑定任何单个节点。
把 Redis 拉起来并确认可用:
docker run -d --name redis -p 6379:6379 redis:6 docker exec redis redis-cli ping输出PONG即通过;如果开了密码,url里带上认证串即可。
第二层:计算节点,三台同构启动
结论:三个节点的配置是同构的,仅监听端口不同(8081/8082/8083),存储必须指向同一份共享后端。
单节点配置如下(顺序按 版本 → http → storage 排列):
{ "distSpecVersion": "1.1.1", "http": { "address": "0.0.0.0", "port": "8081" }, "storage": { "rootDirectory": "/var/lib/zot", "cacheDriver": { "name": "redis", "url": "redis://redis-host:6379", "keyprefix": "zot" } }, "log": { "level": "info" } }缓存驱动同样挂到 Redis,三个节点共享一份元数据缓存,避免重复回源。注意rootDirectory要指向同一个共享目录(如 NFS)或同一个 S3 bucket,否则后文的跨节点拉取测试必挂。同一份文件复制三份、把端口分别改成 8081/8082/8083,在三台机器上启动:
for p in 8081 8082 8083; do docker run -d --name zot-$p -p $p:8080 \ -v /var/lib/zot/$p:/var/lib/zot \ -v /etc/zot/node-$p.json:/etc/zot/config.json \ ghcr.io/project-zot/zot-linux-amd64:latest done每个容器内部固定监听 8080,宿主机侧映射到不同端口。检查点:逐台执行curl http://<节点IP>:8081/v2/,返回 200 即节点健康。
第三层:HAProxy 轮询后端与节点健康检查
结论:轮询后端加check指令,是 Zot HAProxy 负载均衡的最后一块——流量均摊,坏节点自动摘除,客户端只记一个地址。
配置以 examples/cluster/haproxy.cfg 为底,保留必要部分:
defaults mode http timeout connect 5000 timeout client 50000 timeout server 50000 frontend zot bind *:8080 default_backend zot-cluster backend zot-cluster balance roundrobin server zot1 127.0.0.1:8081 check server zot2 127.0.0.1:8082 check server zot3 127.0.0.1:8083 checkcheck按默认 2s 间隔探活,连续 3 次失败后 HAProxy 停止向该节点转发,单点故障不会拖住入口。要摘得更快,可给server行追加inter 1000。
启动接入层:
docker run -d --name haproxy -p 8080:8080 \ -v /etc/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg \ haproxy:2.4此后 8080 就是客户端唯一需要记住的地址。
验收清单:上线前跑四组测试
结论:四组测试全过,集群才算可用;任何一项不过,先回查对应层再谈上线。
- 摘除:
docker stop zot-8081,入口侧curl http://<lb>:8080/v2/_catalog仍返回 200,stats 页面对应节点显示 DOWN。 - 均摊:连续发 30 个请求,stats 页里三个后端的
sess_tot各在 10 左右。 - 一致性:向入口推一个镜像,再分别从另外两个节点直接拉取,digest 一致。
- 会话:登录一次后,被路由到不同节点的请求依然带认证通过——这一步验证的就是 Redis 会话层。
想把这些动作固化成回归,可参考 test/blackbox/sync_replica_cluster.bats 里的多实例推拉用例,改造后纳入 CI。
生产环境搭建:上线后的三个动作
结论:集群"跑起来"只是上线,要"跑得久"还差监控、扩节点路径和告警阈值。
- 监控:打开 metrics 扩展,把 Prometheus 指向各节点的
/metrics,现成的 exporter 配置见 examples/metrics/,重点盯后端摘除次数和会话层延迟。 - 扩节点:HAProxy 的 backend 里加一行
server并重载即可,新节点带同构配置上线,存量节点不需要重启。 - 切亲和路由:仓库规模上来后,可把入口从纯轮询换成 members/hashKey 模式,同一仓库流量固定落到固定节点,缓存命中率会更稳定。
最后一句可执行的建议:上线前把健康检查保持inter 2000并开启stats socket,摘除行为可观测、可接口化,故障时才有操作空间。
【免费下载链接】zotzot - A scale-out production-ready vendor-neutral OCI-native container image/artifact registry (purely based on OCI Distribution Specification)项目地址: https://gitcode.com/GitHub_Trending/zo/zot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考