“要如何將 docker registry 中的鏡像遷移至 harbor?本文介紹了四種具體的思路和想法供大家參考。
Registry
Docker Distribution
Docker Distribution 是第一個(gè)是實(shí)現(xiàn)了打包、發(fā)布、存儲(chǔ)和鏡像分發(fā)的工具,起到 docker registry 的作用。(目前 Distribution 已經(jīng)捐贈(zèng)給了 CNCF)。其中 Docker Distribution 中的 spec 規(guī)范后來(lái)也就成為了 OCI distribution-spec 規(guī)范。可以認(rèn)為 Docker Distribution 實(shí)現(xiàn)了大部分 OCI 鏡像分發(fā)的規(guī)范,二者在很大程度上也是兼容的。OCI 的指導(dǎo)思想時(shí)先有工業(yè)界的實(shí)踐,再將這些實(shí)踐總結(jié)成技術(shù)規(guī)范,因此盡管 OCI 的 distribution-spec 規(guī)范還沒(méi)有正式發(fā)布(目前版本是 v1.0.0-rc1),但以 Docker Distribution 作為基礎(chǔ)的鏡像倉(cāng)庫(kù)已經(jīng)成為普遍采用的方案,docker registry http api v2 也就成為了事實(shí)上的標(biāo)準(zhǔn)。
Harborharbor 也是采用了 Docker Distribution (docker registry)作為后端鏡像存儲(chǔ)服務(wù),在 harbor 2.0 之前的版本,鏡像相關(guān)的功能大部分是由 Docker Distribution 來(lái)處理,鏡像和 OCI 等制品的元數(shù)據(jù)是 harbor 組件從 docker registry 中提取出來(lái)的;harbor 在 2.0 版本之后,鏡像等 OCI 制品相關(guān)的元數(shù)據(jù)由 harbor 自己來(lái)維護(hù),而且元數(shù)據(jù)是在 PUSH 這些制品時(shí)寫(xiě)入到 harbor 的數(shù)據(jù)庫(kù)中的。正因得益于此,harbor 不再僅僅是個(gè)用來(lái)存儲(chǔ)和管理鏡像的服務(wù),而一個(gè)云原生倉(cāng)庫(kù)服務(wù),能夠存儲(chǔ)和管理符合 OCI 規(guī)范的 Helm Chart、CNAB、OPA Bundle 等多種 Artifact。Docker Registry to Harbor回到本文主題:如何將 docker registry 中的鏡像遷移至 harbor?
假如內(nèi)網(wǎng)環(huán)境中有兩臺(tái)機(jī)器,一臺(tái)機(jī)器上運(yùn)行著 docker registry,域名假設(shè)為 registry.k8s.li 。另一臺(tái)機(jī)器運(yùn)行著 harbor,假設(shè)域名為 harbor.k8s.li。現(xiàn)在 docker registry 中存放了五千個(gè)鏡像。harbor 是剛剛部署的,里面還沒(méi)有鏡像。在磁盤(pán)和網(wǎng)絡(luò)沒(méi)有限制的情況下,如何高效地將 docker registry 中的鏡像遷移到 harbor 中呢?
獲取 Registry 所有鏡像的列表
首先在遷移之前我們要獲取一份 docker registry 中鏡像的列表,這樣我們才能保證遷移后沒(méi)有鏡像丟失。根據(jù)《 深入淺出容器鏡像的一生》一文中提到的 registry 的存儲(chǔ)目錄結(jié)構(gòu)。在 registry 存儲(chǔ)目錄中,每個(gè)鏡像的 tag 都是由 current/index 這個(gè)文件指向該 tag 鏡像的 manifests 文件的,由此我們可以通過(guò)遍歷 registry 存儲(chǔ)目錄中 current/index 文件的方式來(lái)得到所有鏡像的 tag,由此得到該 registry 中所有鏡像的列表。注意,這樣只能得到有 tag 的鏡像,其他沒(méi) tag 的鏡像無(wú)法獲取到。
可通過(guò)如下命令在 registry 存儲(chǔ)目錄下獲取鏡像列表:
Harbor 創(chuàng)建 project
對(duì)于新部署的 harbor 來(lái)說(shuō),上面只會(huì)有一個(gè)默認(rèn)的 library 的 project,需要手動(dòng)在 harbor 上創(chuàng)建 docker registry 中對(duì)應(yīng)的 project。docker registry 中鏡像的 project 就是 registry 存儲(chǔ)目錄中 repositories 下的目錄名。
得到了鏡像列表,以及在 harbor 上完成了對(duì)應(yīng) project 的創(chuàng)建,我們就可以做正式的遷移工作啦。根據(jù)不同的場(chǎng)景,可使用如下幾種方案:
方案一:docker retag
方案一可能是大多數(shù)人首先想到的辦法,也是最簡(jiǎn)單粗暴的方法。就是在一臺(tái)機(jī)器上使用 docker pull 下 docker registry 中的所有鏡像,然后再 docker retag 一下,再 docker push 到 harbor 中。
如果之前看過(guò)我寫(xiě)的《深入淺出容器鏡像的一生》和 《鏡像搬運(yùn)工 skopeo 初體驗(yàn)》,并且已經(jīng)在日常生活中使用 skopeo ,一定會(huì)覺(jué)得這并不是個(gè)聰明的方案,因?yàn)?docker pull –》 docker tag –》 docker pull 的過(guò)程中會(huì)對(duì)鏡像的 layer 進(jìn)行解壓縮。對(duì)于只是將鏡像從一個(gè) registry 復(fù)制到另一個(gè) registry 來(lái)說(shuō),這些 docker 在這些過(guò)程中做了很多無(wú)用功。詳細(xì)的原理可以參考上述兩篇文章,在此不再贅述。
為了追求高效,我們不使用 docker retag 方案,下面看一下方案二:
方案二:skopeo
在《鏡像搬運(yùn)工 skopeo 初體驗(yàn)》一文中介紹過(guò)可以使用 skopeo copy 直接從一個(gè) registry 中復(fù)制鏡像原始 blobs 到另一個(gè) registry 中,在此期間不會(huì)涉及鏡像 layer 解壓縮操作。在性能和耗時(shí)兩個(gè)角度上,都比使用 docker 的方式高效很多。
使用 skopeo copy
使用 skopeo sync
無(wú)論是 docker 和 skopeo 本質(zhì)上都是通過(guò) registry 的 HTTP API 下載和上傳鏡像的,在這過(guò)程中還是多了不少 HTTP 請(qǐng)求的,如果走的是 HTTPS 的話(huà),還涉及了 HTTPS 加密和解密的過(guò)程,這期間有很多無(wú)用功。那么還有沒(méi)有更好的辦法?
方案三:遷移存儲(chǔ)目錄
文章開(kāi)頭提到 harbor 的后端鏡像存儲(chǔ)也是使用的 docker registry,對(duì)于一個(gè) registry 來(lái)說(shuō),只要是使用的是 Docker Distribution V2 ,它后端的存儲(chǔ)目錄結(jié)構(gòu)都是一模一樣的。那為什么不直接將 registry 的存儲(chǔ)目錄打包復(fù)制并解壓到 harbor 的 registry 存儲(chǔ)目錄?這樣又能保證所有的鏡像都遷移過(guò)去,不會(huì)落下任何一個(gè)。
對(duì)于 harbor 1.x 版本來(lái)講,將 docker registry 的存儲(chǔ)目錄直接遷移到 harbor 的 registry 存儲(chǔ)目錄,然后刪除 harbor 的 redis 數(shù)據(jù)(因?yàn)?harbor 的 redis 緩存了鏡像的元數(shù)據(jù)信息),重啟 harbor 就好了。重啟 harbor 之后,harbor 會(huì)調(diào)用后端的 registry 去提取鏡像的元數(shù)據(jù)信息并存儲(chǔ)到 redis 中。這樣就完成了遷移的工作。在 docker registry 機(jī)器上備份 registry 存儲(chǔ)目錄
備份完成之后將 docker.tar scp 到 harbor 機(jī)器上,然后在 harbor 機(jī)器上恢復(fù) registry 存儲(chǔ)目錄
這樣遷移之后可能會(huì)遇到無(wú)法往 harbor push 鏡像的問(wèn)題。因?yàn)?docker registry 容器內(nèi) registry 存儲(chǔ)目錄的所屬和所屬組為 root,而 harbor registry 容器內(nèi) registry 存儲(chǔ)目錄的所屬和所屬組為 10000:10000,二者權(quán)限并不相同,會(huì)導(dǎo)致 harbor 無(wú)法 push 鏡像。因此在遷移完成之后需要修改一下 harbor registry 目錄的所屬和所屬組。
方案四
對(duì)于 harbor 2.x 來(lái)講,由于 harbor 強(qiáng)化了 Artifact 的元數(shù)據(jù)管理能力,即元數(shù)據(jù)要在 push 或者 sync 到 harbor 時(shí)寫(xiě)入到 harbor 自身的數(shù)據(jù)庫(kù)中。在 harbor 看來(lái)只要數(shù)據(jù)庫(kù)中沒(méi)有這個(gè) Artifact 的 manifest 信息或者沒(méi)有這一層 layer 的信息,harbor 都會(huì)認(rèn)為該 Artifact 或者 layer 不存在,返回 404 的錯(cuò)誤。按照方案三直接而將 docker registry 存儲(chǔ)目錄解壓到 harbor 的 registry 存儲(chǔ)目錄的方法行不通的。因?yàn)槭菍㈢R像解壓到 registry 存儲(chǔ)中的,雖然在 harbor 的 registry 容器看來(lái)是有鏡像的,但因?yàn)?harbor 的數(shù)據(jù)庫(kù)中沒(méi)有鏡像,harbor 就會(huì)認(rèn)為沒(méi)有鏡像。那么現(xiàn)在看來(lái)只能通過(guò)方案二使用 skopeo 將鏡像一個(gè)一個(gè)地 push 到 harbor 中了。
但對(duì)于某些特定的場(chǎng)景下,不能像方案二那樣擁有一個(gè) docker registry 的 HTTP 服務(wù),只有一個(gè) docker registry 的壓縮包,這如何將 docker registry 的存儲(chǔ)目錄中的鏡像遷移到 harbor 2.0 中呢?在《鏡像搬運(yùn)工 skopeo 初體驗(yàn)》中提到過(guò) skopeo 支持的鏡像格式有如下幾種:
需要注意的是,這幾種鏡像的名字,對(duì)應(yīng)著鏡像存在的方式,不同存在的方式對(duì)鏡像的 layer 處理的方式也不一樣,比如 docker:// 這種方式是存在 registry 上的;docker-daemon: 是存在本地 docker pull 下來(lái)的;再比如 docker-archive 是通過(guò) docker save 出來(lái)的鏡像;而 dir: 是鏡像以文件夾的形式保存的。同一個(gè)鏡像有這幾種存在的方式就像水有氣體、液體、固體一樣。可以這樣去理解,他們表述的都是同一個(gè)鏡像,只不過(guò)是存在的方式不一樣而已。既然鏡像是存放在 registry 存儲(chǔ)目錄里的,那么使用 dir 的形式直接從文件系統(tǒng)讀取鏡像,理論上來(lái)講會(huì)比方案二要好一些。雖然 skopeo 支持 dir 格式的鏡像,但 skopeo 目前并不支持直接使用 registry 的存儲(chǔ)目錄,所以還是需要想辦法將 docker registry 存儲(chǔ)目錄里的每一個(gè)鏡像轉(zhuǎn)換成 skopeo dir 的形式。skopeo dir那么先來(lái)看一下 skopeo dir 是什么樣子的?為了方便測(cè)試方案的可行性,先使用 skopeo 命令先從 docker hub 上拉取一個(gè)鏡像,并保存為 dir,命令如下:
使用 tree 命令查看一下 alpine 文件夾的目錄結(jié)構(gòu),如下:
從文件名和大小以及文件的內(nèi)省我們可以判斷出,manifest 文件對(duì)應(yīng)的就是鏡像的 manifests 文件;類(lèi)型為 ASCII text 的文件正是鏡像的 image config 文件,里面包含著鏡像的元數(shù)據(jù)信息。而另一個(gè) gzip compressed data 文件不就是經(jīng)過(guò) gzip 壓縮過(guò)的鏡像 layer 嘛。看一下 manifest 文件的內(nèi)容也再次印證了這個(gè)結(jié)論:
鏡像的 config 字段對(duì)應(yīng)的正是 e50c909a8df2,而文件類(lèi)型正是 image.v1+json 文本文件。
鏡像的 layer 字段對(duì)應(yīng)的也正是 4c0d98bf9879 而文件類(lèi)型正是 .tar.gzip gzip 壓縮文件。
從 registry 存儲(chǔ)目錄中撈鏡像出來(lái)接下來(lái)到本文的較為精彩的地方了。如何從 registry 存儲(chǔ)里“撈”鏡像出來(lái),轉(zhuǎn)換成 skopeo 所支持的 dir 格式。
首先要得到鏡像的 manifests 文件,從 manifests 文件中可以得到該鏡像的所有 blob 文件。例如對(duì)于 registry 存儲(chǔ)目錄中的 library/alpine:latest 鏡像來(lái)講,它在 registry 中是這樣存放的:
1.通過(guò) repositories/library/alpine/_manifests/tags/latest/current/link 文件得到 alpine 鏡像 lasts 這個(gè) tag 的 manifests 文件的 sha256 值,然后根據(jù)這個(gè) sha256 值去 blobs 找到鏡像的 manifests 文件;2.根據(jù) current/link 文件中的 sha256 值在 blobs 目錄下找到與之對(duì)應(yīng)的文件,blobs 目錄下對(duì)應(yīng)的 manifests 文件為 blobs/sha256/39/39eda93d15866957feaee28f8fc5adb545276a64147445c64992ef69804dbf01/data;
3.使用正則匹配,過(guò)濾出 manifests 文件中的所有 sha256 值,這些 sha256 值就對(duì)應(yīng)著 blobs 目錄下的 image config 文件和 image layer 文件;
4.根據(jù) manifests 文件就可以得到 blobs 目錄中鏡像的所有 layer 和 image config 文件,然后將這些文件拼成一個(gè) dir 格式的鏡像,在這里使用 cp 的方式將鏡像從 registry 存儲(chǔ)目錄里復(fù)制出來(lái),過(guò)程如下:
最終得到的鏡像格式如下:
和上面的 skopeo copy 出來(lái)的 dir 文件夾對(duì)比一下,除了一個(gè)無(wú)關(guān)緊要的 version 文件,其他的都一摸一樣。5.再優(yōu)化一下,將步驟 4 中的 cp 操作修改成硬鏈接操作,能極大減少磁盤(pán)的 IO 操作。需要注意:硬鏈接文件不能跨分區(qū),所以要和 registry 存儲(chǔ)目錄在同一個(gè)分區(qū)下才行。
然后使用 skopeo copy 或者 skopeo sync 將撈出來(lái)的鏡像 push 到 harbor
使用 skopeo copy
使用 skopeo sync 需要注意的是,skopeo sync 的方式是同步 project 級(jí)別的,鏡像的 name 和 tag 就對(duì)應(yīng)的是目錄的名稱(chēng)
實(shí)現(xiàn)腳本
其實(shí)修改一下 skopeo 的源碼應(yīng)該也是可以無(wú)縫支持 registry 存儲(chǔ)目錄的。
對(duì)比
對(duì)比總結(jié)一下以上幾種方案:
方案一:上手成本低,適用于鏡像數(shù)量比較多少,無(wú)需安裝 skopeo 的情況,缺點(diǎn)是性能較差;
方案二:適用于兩個(gè) registry 之間同步復(fù)制鏡像,如將 docker hub 中的一些公共鏡像復(fù)制到公司內(nèi)網(wǎng)的鏡像倉(cāng)庫(kù)中。
方案三:適用于鏡像倉(cāng)庫(kù)之間進(jìn)行遷移,性能是所有方案里最好的,需要額外注意的是如果目的鏡像倉(cāng)庫(kù)是 harbor 2.x,是無(wú)法使用這種方式的。
方案四:是方案三的妥協(xié)版,為了適配 harbor 2.0 ,因?yàn)樾枰匦聦㈢R像 push 到 harbor ,所以性能上要比方案三差一些。
責(zé)任編輯:haq
-
代碼
+關(guān)注
關(guān)注
30文章
4891瀏覽量
70306 -
Docker
+關(guān)注
關(guān)注
0文章
512瀏覽量
12754
原文標(biāo)題:4 種方法將 Docker Registry 遷移至 Harbor
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
如何將項(xiàng)目從IAR遷移到Embedded Studio

Flexusx 實(shí)例與 Harbor 私有鏡像倉(cāng)庫(kù)的完美結(jié)合

從TMS320VC5509遷移到TMS320VC5509A

從TMS320DM6467遷移到TMS320DM6467T

從TMS320DM6446 594MHz遷移到810MHz

從TMS320C5515遷移到TMS320C5517

IT資源遷移到云服務(wù)器的關(guān)鍵因素
從遷移到基于Arm STM32的MSPMO指南

ARM平臺(tái)實(shí)現(xiàn)Docker容器技術(shù)
ARM平臺(tái)實(shí)現(xiàn)Docker容器技術(shù)
Jtti:Docker會(huì)替代調(diào)虛機(jī)嗎

評(píng)論