- 資訊首頁(yè) > 互聯(lián)網(wǎng) > 經(jīng)驗分享 >
- 如何將docker registry中的鏡像遷移至harbor?四種具
要如何將docker registry中的鏡像遷移至harbor?本文介紹了四種具體的思路和想法供大家參考。
Registry
Docker DistributionDocker Distribution 是第一個(gè)是實(shí)現了打包、發(fā)布、存儲和鏡像分發(fā)的工具,起到 docker registry 的作用。(目前 Distribution 已經(jīng)捐贈給了 CNCF)。其中 Docker Distribution 中的 spec 規范后來(lái)也就成為了 OCI distribution-spec 規范??梢哉J為 Docker Distribution 實(shí)現了大部分 OCI 鏡像分發(fā)的規范,二者在很大程度上也是兼容的。OCI 的指導思想時(shí)先有工業(yè)界的實(shí)踐,再將這些實(shí)踐總結成技術(shù)規范,因此盡管 OCI 的 distribution-spec 規范還沒(méi)有正式發(fā)布(目前版本是 v1.0.0-rc1),但以 Docker Distribution 作為基礎的鏡像倉庫已經(jīng)成為普遍采用的方案,docker registry http api v2 也就成為了事實(shí)上的標準。Harborharbor 也是采用了 Docker Distribution (docker registry)作為后端鏡像存儲服務(wù),在 harbor 2.0 之前的版本,鏡像相關(guān)的功能大部分是由 Docker Distribution 來(lái)處理,鏡像和 OCI 等制品的元數據是 harbor 組件從 docker registry 中提取出來(lái)的;harbor 在 2.0 版本之后,鏡像等 OCI 制品相關(guān)的元數據由 harbor 自己來(lái)維護,而且元數據是在 PUSH 這些制品時(shí)寫(xiě)入到 harbor 的數據庫中的。正因得益于此,harbor 不再僅僅是個(gè)用來(lái)存儲和管理鏡像的服務(wù),而一個(gè)云原生倉庫服務(wù),能夠存儲和管理符合 OCI 規范的 Helm Chart、CNAB、OPA Bundle 等多種 Artifact。Docker Registry to Harbor回到本文主題:如何將 docker registry 中的鏡像遷移至 harbor?
假如內網(wǎng)環(huán)境中有兩臺機器,一臺機器上運行著(zhù) docker registry,域名假設為 registry.k8s.li 。另一臺機器運行著(zhù) harbor,假設域名為 harbor.k8s.li?,F在 docker registry 中存放了五千個(gè)鏡像。harbor 是剛剛部署的,里面還沒(méi)有鏡像。在磁盤(pán)和網(wǎng)絡(luò )沒(méi)有限制的情況下,如何高效地將 docker registry 中的鏡像遷移到 harbor 中呢?
獲取 Registry 所有鏡像的列表
首先在遷移之前我們要獲取一份 docker registry 中鏡像的列表,這樣我們才能保證遷移后沒(méi)有鏡像丟失。根據《 深入淺出容器鏡像的一生》一文中提到的 registry 的存儲目錄結構。在 registry 存儲目錄中,每個(gè)鏡像的 tag 都是由 current/index 這個(gè)文件指向該 tag 鏡像的 manifests 文件的,由此我們可以通過(guò)遍歷 registry 存儲目錄中 current/index 文件的方式來(lái)得到所有鏡像的 tag,由此得到該 registry 中所有鏡像的列表。注意,這樣只能得到有 tag 的鏡像,其他沒(méi) tag 的鏡像無(wú)法獲取到。
可通過(guò)如下命令在 registry 存儲目錄下獲取鏡像列表:
Harbor 創(chuàng )建 project
對于新部署的 harbor 來(lái)說(shuō),上面只會(huì )有一個(gè)默認的 library 的 project,需要手動(dòng)在 harbor 上創(chuàng )建 docker registry 中對應的 project。docker registry 中鏡像的 project 就是 registry 存儲目錄中 repositories 下的目錄名。
得到了鏡像列表,以及在 harbor 上完成了對應 project 的創(chuàng )建,我們就可以做正式的遷移工作啦。根據不同的場(chǎng)景,可使用如下幾種方案:
方案一:docker retag
方案一可能是大多數人首先想到的辦法,也是最簡(jiǎn)單粗暴的方法。就是在一臺機器上使用 docker pull 下 docker registry 中的所有鏡像,然后再 docker retag 一下,再 docker push 到 harbor 中。
如果之前看過(guò)我寫(xiě)的《深入淺出容器鏡像的一生》和 《鏡像搬運工 skopeo 初體驗》,并且已經(jīng)在日常生活中使用 skopeo ,一定會(huì )覺(jué)得這并不是個(gè)聰明的方案,因為 docker pull –> docker tag –> docker pull 的過(guò)程中會(huì )對鏡像的 layer 進(jìn)行解壓縮。對于只是將鏡像從一個(gè) registry 復制到另一個(gè) registry 來(lái)說(shuō),這些 docker 在這些過(guò)程中做了很多無(wú)用功。詳細的原理可以參考上述兩篇文章,在此不再贅述。
為了追求高效,我們不使用 docker retag 方案,下面看一下方案二:
方案二:skopeo
在《鏡像搬運工 skopeo 初體驗》一文中介紹過(guò)可以使用 skopeo copy 直接從一個(gè) registry 中復制鏡像原始 blobs 到另一個(gè) registry 中,在此期間不會(huì )涉及鏡像 layer 解壓縮操作。在性能和耗時(shí)兩個(gè)角度上,都比使用 docker 的方式高效很多。
無(wú)論是 docker 和 skopeo 本質(zhì)上都是通過(guò) registry 的 HTTP API 下載和上傳鏡像的,在這過(guò)程中還是多了不少 HTTP 請求的,如果走的是 HTTPS 的話(huà),還涉及了 HTTPS 加密和解密的過(guò)程,這期間有很多無(wú)用功。那么還有沒(méi)有更好的辦法?
方案三:遷移存儲目錄
文章開(kāi)頭提到 harbor 的后端鏡像存儲也是使用的 docker registry,對于一個(gè) registry 來(lái)說(shuō),只要是使用的是 Docker Distribution V2 ,它后端的存儲目錄結構都是一模一樣的。那為什么不直接將 registry 的存儲目錄打包復制并解壓到 harbor 的 registry 存儲目錄?這樣又能保證所有的鏡像都遷移過(guò)去,不會(huì )落下任何一個(gè)。對于 harbor 1.x 版本來(lái)講,將 docker registry 的存儲目錄直接遷移到 harbor 的 registry 存儲目錄,然后刪除 harbor 的 redis 數據(因為 harbor 的 redis 緩存了鏡像的元數據信息),重啟 harbor 就好了。重啟 harbor 之后,harbor 會(huì )調用后端的 registry 去提取鏡像的元數據信息并存儲到 redis 中。這樣就完成了遷移的工作。
在 docker registry 機器上備份 registry 存儲目錄
備份完成之后將 docker.tar scp 到 harbor 機器上,然后在 harbor 機器上恢復 registry 存儲目錄
這樣遷移之后可能會(huì )遇到無(wú)法往 harbor push 鏡像的問(wèn)題。因為 docker registry 容器內 registry 存儲目錄的所屬和所屬組為 root,而 harbor registry 容器內 registry 存儲目錄的所屬和所屬組為 10000:10000,二者權限并不相同,會(huì )導致 harbor 無(wú)法 push 鏡像。因此在遷移完成之后需要修改一下 harbor registry 目錄的所屬和所屬組。
方案四
對于 harbor 2.x 來(lái)講,由于 harbor 強化了 Artifact 的元數據管理能力,即元數據要在 push 或者 sync 到 harbor 時(shí)寫(xiě)入到 harbor 自身的數據庫中。在 harbor 看來(lái)只要數據庫中沒(méi)有這個(gè) Artifact 的 manifest 信息或者沒(méi)有這一層 layer 的信息,harbor 都會(huì )認為該 Artifact 或者 layer 不存在,返回 404 的錯誤。按照方案三直接而將 docker registry 存儲目錄解壓到 harbor 的 registry 存儲目錄的方法行不通的。因為是將鏡像解壓到 registry 存儲中的,雖然在 harbor 的 registry 容器看來(lái)是有鏡像的,但因為 harbor 的數據庫中沒(méi)有鏡像,harbor 就會(huì )認為沒(méi)有鏡像。那么現在看來(lái)只能通過(guò)方案二使用 skopeo 將鏡像一個(gè)一個(gè)地 push 到 harbor 中了。但對于某些特定的場(chǎng)景下,不能像方案二那樣擁有一個(gè) docker registry 的 HTTP 服務(wù),只有一個(gè) docker registry 的壓縮包,這如何將 docker registry 的存儲目錄中的鏡像遷移到 harbor 2.0 中呢?在《鏡像搬運工 skopeo 初體驗》中提到過(guò) skopeo 支持的鏡像格式有如下幾種:
需要注意的是,這幾種鏡像的名字,對應著(zhù)鏡像存在的方式,不同存在的方式對鏡像的 layer 處理的方式也不一樣,比如 docker:// 這種方式是存在 registry 上的;docker-daemon: 是存在本地 docker pull 下來(lái)的;再比如 docker-archive 是通過(guò) docker save 出來(lái)的鏡像;而 dir: 是鏡像以文件夾的形式保存的。同一個(gè)鏡像有這幾種存在的方式就像水有氣體、液體、固體一樣??梢赃@樣去理解,他們表述的都是同一個(gè)鏡像,只不過(guò)是存在的方式不一樣而已。
既然鏡像是存放在 registry 存儲目錄里的,那么使用 dir 的形式直接從文件系統讀取鏡像,理論上來(lái)講會(huì )比方案二要好一些。雖然 skopeo 支持 dir 格式的鏡像,但 skopeo 目前并不支持直接使用 registry 的存儲目錄,所以還是需要想辦法將 docker registry 存儲目錄里的每一個(gè)鏡像轉換成 skopeo dir 的形式。
skopeo dir
那么先來(lái)看一下 skopeo dir 是什么樣子的?為了方便測試方案的可行性,先使用 skopeo 命令先從 docker hub 上拉取一個(gè)鏡像,并保存為 dir,命令如下:
使用 tree 命令查看一下 alpine 文件夾的目錄結構,如下:
從文件名和大小以及文件的內省我們可以判斷出,manifest 文件對應的就是鏡像的 manifests 文件;類(lèi)型為 ASCII text 的文件正是鏡像的 image config 文件,里面包含著(zhù)鏡像的元數據信息。而另一個(gè) gzip compressed data 文件不就是經(jīng)過(guò) gzip 壓縮過(guò)的鏡像 layer 嘛??匆幌?manifest 文件的內容也再次印證了這個(gè)結論:
從 registry 存儲目錄中撈鏡像出來(lái)
接下來(lái)到本文的較為精彩的地方了。如何從 registry 存儲里“撈”鏡像出來(lái),轉換成 skopeo 所支持的 dir 格式。
1.通過(guò) repositories/library/alpine/_manifests/tags/latest/current/link 文件得到 alpine 鏡像 lasts 這個(gè) tag 的 manifests 文件的 sha256 值,然后根據這個(gè) sha256 值去 blobs 找到鏡像的 manifests 文件;
2.根據 current/link 文件中的 sha256 值在 blobs 目錄下找到與之對應的文件,blobs 目錄下對應的 manifests 文件為 blobs/sha256/39/39eda93d15866957feaee28f8fc5adb545276a64147445c64992ef69804dbf01/data;
3.使用正則匹配,過(guò)濾出 manifests 文件中的所有 sha256 值,這些 sha256 值就對應著(zhù) blobs 目錄下的 image config 文件和 image layer 文件;
4.根據 manifests 文件就可以得到 blobs 目錄中鏡像的所有 layer 和 image config 文件,然后將這些文件拼成一個(gè) dir 格式的鏡像,在這里使用 cp 的方式將鏡像從 registry 存儲目錄里復制出來(lái),過(guò)程如下:
最終得到的鏡像格式如下:
和上面的 skopeo copy 出來(lái)的 dir 文件夾對比一下,除了一個(gè)無(wú)關(guān)緊要的 version 文件,其他的都一摸一樣。
5.再優(yōu)化一下,將步驟 4 中的 cp 操作修改成硬鏈接操作,能極大減少磁盤(pán)的 IO 操作。需要注意:硬鏈接文件不能跨分區,所以要和 registry 存儲目錄在同一個(gè)分區下才行。
然后使用 skopeo copy 或者 skopeo sync 將撈出來(lái)的鏡像 push 到 harbor
使用 skopeo sync 需要注意的是,skopeo sync 的方式是同步 project 級別的,鏡像的 name 和 tag 就對應的是目錄的名稱(chēng)
實(shí)現腳本
其實(shí)修改一下 skopeo 的源碼應該也是可以無(wú)縫支持 registry 存儲目錄的。
對比
對比總結一下以上幾種方案:
參考資料:《harbor權威指南》《深入淺出容器鏡像的一生》:https://blog.k8s.li/Exploring-container-image.html《鏡像搬運工 skopeo 初體驗》:https://blog.k8s.li/skopeo.htmlHarbor 2.0 takes a giant leap in expanding supported artifacts with OCI support:https://goharbor.io/blog/harbor-2.0/
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站