4 种方法将 Docker Registry 迁移至 Harbor
Posted K8sMeetup社区
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4 种方法将 Docker Registry 迁移至 Harbor相关的知识,希望对你有一定的参考价值。
要如何将 docker registry 中的镜像迁移至 harbor?本文介绍了四种具体的思路和想法供大家参考。
编辑:Bach(才云)
Registry
Docker Distribution
假如内网环境中有两台机器,一台机器上运行着 docker registry,域名假设为 registry.k8s.li 。另一台机器运行着 harbor,假设域名为 harbor.k8s.li。现在 docker registry 中存放了五千个镜像。harbor 是刚刚部署的,里面还没有镜像。在磁盘和网络没有限制的情况下,如何高效地将 docker registry 中的镜像迁移到 harbor 中呢?
获取 Registry 所有镜像的列表
首先在迁移之前我们要获取一份 docker registry 中镜像的列表,这样我们才能保证迁移后没有镜像丢失。根据一文中提到的 registry 的存储目录结构。在 registry 存储目录中,每个镜像的 tag 都是由 current/index 这个文件指向该 tag 镜像的 manifests 文件的,由此我们可以通过遍历 registry 存储目录中 current/index 文件的方式来得到所有镜像的 tag,由此得到该 registry 中所有镜像的列表。注意,这样只能得到有 tag 的镜像,其他没 tag 的镜像无法获取到。
Harbor 创建 project
对于新部署的 harbor 来说,上面只会有一个默认的 library 的 project,需要手动在 harbor 上创建 docker registry 中对应的 project。docker registry 中镜像的 project 就是 registry 存储目录中 repositories 下的目录名。
得到了镜像列表,以及在 harbor 上完成了对应 project 的创建,我们就可以做正式的迁移工作啦。根据不同的场景,可使用如下几种方案:
方案一:docker retag
方案一可能是大多数人首先想到的办法,也是最简单粗暴的方法。就是在一台机器上使用 docker pull 下 docker registry 中的所有镜像,然后再 docker retag 一下,再 docker push 到 harbor 中。
为了追求高效,我们不使用 docker retag 方案,下面看一下方案二:
方案二:skopeo
在《镜像搬运工 skopeo 初体验》一文中介绍过可以使用 skopeo copy 直接从一个 registry 中复制镜像原始 blobs 到另一个 registry 中,在此期间不会涉及镜像 layer 解压缩操作。在性能和耗时两个角度上,都比使用 docker 的方式高效很多。
-
使用 skopeo copy
-
使用 skopeo sync
无论是 docker 和 skopeo 本质上都是通过 registry 的 HTTP API 下载和上传镜像的,在这过程中还是多了不少 HTTP 请求的,如果走的是 HTTPS 的话,还涉及了 HTTPS 加密和解密的过程,这期间有很多无用功。那么还有没有更好的办法?
方案三:迁移存储目录
文章开头提到 harbor 的后端镜像存储也是使用的 docker registry,对于一个 registry 来说,只要是使用的是 Docker Distribution V2 ,它后端的存储目录结构都是一模一样的。那为什么不直接将 registry 的存储目录打包复制并解压到 harbor 的 registry 存储目录?这样又能保证所有的镜像都迁移过去,不会落下任何一个。
方案四
对于 harbor 2.x 来讲,由于 harbor 强化了 Artifact 的元数据管理能力,即元数据要在 push 或者 sync 到 harbor 时写入到 harbor 自身的数据库中。在 harbor 看来只要数据库中没有这个 Artifact 的 manifest 信息或者没有这一层 layer 的信息,harbor 都会认为该 Artifact 或者 layer 不存在,返回 404 的错误。按照方案三直接而将 docker registry 存储目录解压到 harbor 的 registry 存储目录的方法行不通的。因为是将镜像解压到 registry 存储中的,虽然在 harbor 的 registry 容器看来是有镜像的,但因为 harbor 的数据库中没有镜像,harbor 就会认为没有镜像。那么现在看来只能通过方案二使用 skopeo 将镜像一个一个地 push 到 harbor 中了。
-
镜像的 config 字段对应的正是 e50c909a8df2,而文件类型正是 image.v1+json 文本文件。 -
镜像的 layer 字段对应的也正是 4c0d98bf9879 而文件类型正是 .tar.gzip gzip 压缩文件。
-
首先要得到镜像的 manifests 文件,从 manifests 文件中可以得到该镜像的所有 blob 文件。例如对于 registry 存储目录中的 library/alpine:latest 镜像来讲,它在 registry 中是这样存放的:
-
使用 skopeo copy
-
使用 skopeo sync 需要注意的是,skopeo sync 的方式是同步 project 级别的,镜像的 name 和 tag 就对应的是目录的名称
对比
-
方案一:上手成本低,适用于镜像数量比较多少,无需安装 skopeo 的情况,缺点是性能较差; -
方案二:适用于两个 registry 之间同步复制镜像,如将 docker hub 中的一些公共镜像复制到公司内网的镜像仓库中。 -
方案三:适用于镜像仓库之间进行迁移,性能是所有方案里最好的,需要额外注意的是如果目的镜像仓库是 harbor 2.x,是无法使用这种方式的。 -
方案四:是方案三的妥协版,为了适配 harbor 2.0 ,因为需要重新将镜像 push 到 harbor ,所以性能上要比方案三差一些。
推荐阅读:
以上是关于4 种方法将 Docker Registry 迁移至 Harbor的主要内容,如果未能解决你的问题,请参考以下文章
有没有一种简单的方法来使用 LDAP 配置 Docker Private Registry 2.0?