Zot 镜像同步实战:从定时到按需,3种方式打通跨区域镜像分发
【免费下载链接】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 Distribution Specification 的容器镜像/制品仓库,内置的 sync 扩展可以让它充当远程仓库的镜像网关:远程仓库里有新镜像时,Zot 按你定的规则拉过来存到本地。读完这篇文章,你能独立写出一份同步配置,在定时、按需、流式三种模式之间做选择,并用前缀和标签规则精确控制同步范围,避免把整个上游仓库无脑搬进本地存储。
同步扩展如何启用:最小配置长什么样
这一节解决"配置从哪开始写"的问题。Zot 的同步逻辑挂在extensions.sync节点下,一份最小可用的同步配置如下:
{ "extensions": { "sync": { "enable": true, "credentialsFile": "./examples/sync-auth-filepath.json", "registries": [ { "urls": ["https://registry1:5000"], "pollInterval": "6h" } ] } } }它解决的是三件事:打开开关(enable)、指向上游凭证文件(credentialsFile)、声明要同步哪些上游仓库(registries)。凭证文件是普通的 JSON,key 为仓库地址,value 是账号密码:
{ "registry2:5000": { "username": "user2", "password": "pass2" } }⚠️ 如果上游仓库需要鉴权,漏配凭证会导致同步静默失败。完整示例可以对照 config-sync.json,配置结构定义在 pkg/extensions/config/sync/ 里,字段名以那里的类型为准。
定时同步还是按需同步:两种触发机制怎么选
这一节解决"什么时候拉镜像"的问题。Zot 支持三种模式,可以按场景组合:
- 定时同步(Periodic):默认行为。设置
pollInterval后,Zot 周期性轮询上游仓库,把新增的镜像拉下来。适合镜像集相对稳定、要求本地随时可拉取的场景。 - 按需同步(On-Demand):设置
"onDemand": true。客户端请求本地没有的镜像时,Zot 才临时去上游取。存储只会被实际拉过的镜像占用,适合上游镜像数量巨大但访问稀疏的场景。 - 流式同步(Stream):在按需基础上更进一步,Zot 边从上游下载边把数据转发给客户端,不等本地落盘完成。首次拉取就更快,代价是与按需同步的某些重试参数互斥,详细约束见 流式同步说明。
还有一个折中选项:onDemandInBackground。开启后,请求缺失镜像时 Zot 立即返回 404,同步在后台进行,镜像就绪后的请求才成功。适合不希望请求方长时间等待、可以接受短暂 404 的网关场景。
| 模式 | 触发时机 | 存储占用 | 适用场景 |
|---|---|---|---|
| 定时 | pollInterval 轮询 | 全量(受过滤规则约束) | 镜像集小、要求本地秒拉 |
| 按需 | 客户端首次请求 | 仅被拉过的镜像 | 上游镜像多、访问稀疏 |
| 流式 | 客户端首次请求,边下边传 | 同步完成后落盘 | 对首次拉取延迟敏感 |
只同步需要的仓库和标签:content 规则怎么写
这一节解决"怎么不把上游整个搬空"的问题。content数组是过滤规则的核心,每条规则由prefix(仓库前缀,支持**通配)、tags(标签规则)和可选的路径转换参数组成:
"content": [ { "prefix": "/repo1/repo", "tags": { "regex": "4.*", "semver": true } }, { "prefix": "/repo4/**", "tags": { "excludeRegex": ".*-(amd64|arm64)$" } } ]它解决的是"白名单 + 标签过滤":只有prefix命中的仓库会被同步,标签再经过regex(匹配才保留)、excludeRegex(匹配则剔除)、semver(只保留语义化版本 tag)三道筛选。规则由 ContentManager 统一解释,前缀匹配用的是 glob 语法,所以**可以覆盖整个命名空间下的所有子路径。
同步路径与上游不一致:destination 和 stripPrefix 怎么配
这一节解决"本地仓库名想和上游不一样"的问题。上游的命名空间往往带着环境或团队前缀,直接同步过来会让本地路径又长又乱。下面这段配置把上游repo2/repo改写成本地的repo:
{ "prefix": "/repo2/repo", "destination": "/repo", "stripPrefix": true }- 不设置
stripPrefix时,destination作为前缀拼在原始仓库名前面,等于加一层命名空间。 - 设置
stripPrefix: true后,prefix部分会被剥掉,上游repo2/repo落到本地repo,层级关系保持不变。
📌 按需同步也复用同一套规则:本地仓库名会被反向映射回上游仓库名,所以两种模式必须用同一份content规则,定时和按需的改写行为才一致。
重试与限速:让同步在网络抖动时不翻车
这一节解决"上游不稳定、限流、大镜像拉不动"的问题。上游仓库(尤其是 index.docker.io 这类公共仓库)经常限流,参数集中在registries每个条目上:
| 参数 | 作用 |
|---|---|
maxRetries/retryDelay | 失败重试次数与基础间隔 |
maxRetryDelay | 重试退避上限 |
syncTimeout | 单次同步操作的总超时 |
reqConcurrent | 每个上游主机的在途请求数上限 |
reqPerSec | 每个上游主机的请求速率上限 |
disableHTTP2/maxIdleConnsPerHost | 控制连接复用与 HTTP/1.1 并发 |
⚠️ 按需同步做高并发代理拉取时,reqConcurrent和disableHTTP2通常要一起调:只调前者,请求仍挤在同一条 HTTP/2 连接上;只调后者,并发数还会被默认的 3 个连接卡住。
进阶:多架构镜像只拉要的平台
这一节解决"multi-arch 镜像白白占满磁盘"的问题。给 registry 或 content 规则配platforms白名单,定时同步 multi-arch index 时只会复制列表中声明的子镜像,index 的 digest 保持不变,未选中的平台保持缺失(sparse 状态):
{ "prefix": "/repo4/**", "platforms": ["linux/amd64"] }如果业务只跑 x86,这样配置就能省掉一半以上的存储空间。content 级设置会覆盖 registry 级默认值;按需同步则不受该列表限制,客户端要哪个平台才补哪个平台。更多机制细节可以看 稀疏 multi-arch 同步说明。
下一步
- 从零跑通:参考 examples/README.md 里的同步示例逐个验证。
- 云端鉴权:需要 ECR/GCP 这类凭证助手时,看 sync 扩展配置 中
credentialHelper与oauth2CredentialHelper的定义,示例配置在 config-sync.json 同目录的 sync 相关配置文件中。 - 行为验证:端到端的同步测试在 test/blackbox/sync.bats 里,可以作为配置正确性的对照。
【免费下载链接】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),仅供参考