因爲阿里雲上的容器服務 ACK 在使用成本、運維成本、方便性、長期穩定性上大大超過公司自建自維護 Kubernets 集羣,有很多公司紛紛想把以前本身維護 Kubernetes 負載遷移到阿里雲 ACK 服務上。在遷移過程當中,每每會碰到一個不大不小的坑:那就是怎麼把已有的容器鏡像平滑的遷移到阿里雲鏡像服務 ACR 上。這個問題看起來很是簡單,若是隻有三五個鏡像,只要作一次 docker pull/docker push 就能完成,但實際生產中涉及到成千上百個鏡像,幾 T 的鏡像倉庫數據時,遷移過程就變的耗時很是漫長,甚至丟失數據。html
阿里云云原生應用平臺的工程師——也就是咱們,發現這是一個通用的需求,用戶會在各類容器鏡像倉庫之間作遷移,或者進一步,指望有同步複製的能力,因此咱們研發了 image-syncer 這個項目來支持遷雲,並同時開源給業界大衆,用來解決通用的容器鏡像批量遷移/同步的問題。linux
這個工具在實際生產中,已經幫助了多家客戶進行鏡像遷移,其中最大鏡像倉庫的總量達到 3T 以上,同步時能跑滿機器帶寬,進行同步任務的機器磁盤容量沒有要求。nginx
如上所述,在 k8s 集羣遷移場景中,鏡像倉庫之間進行鏡像遷移/同步是基本需求,而使用 docker pull/push 結合腳本的傳統方式進行鏡像同步,有以下幾個侷限性:git
image-syncer 的定位是一個簡單、易用的批量鏡像遷移/同步工具,支持幾乎全部目前主流的基於 docker registry V2 搭建的鏡像存儲服務,好比 ACR、Docker Hub、Quay、自建 Harbor 等,目前已經初步通過了 TB 級別的生產環境鏡像遷移驗證,並開源於 https://github.com/AliyunContainerService/image-syncer ,歡迎你們下載使用以及提供寶貴的建議~github
image-syncer 的特性以下:docker
1.支持多對多鏡像倉庫同步 2.支持基於 Docker Registry V2 搭建的 docker 鏡像倉庫服務 (如 Docker Hub、 Quay、 阿里雲鏡像服務 ACR、 Harbor等) 3.同步只通過內存和網絡,不依賴磁盤存儲,同步速度快 4.增量同步, 經過對同步過的鏡像 blob 信息落盤,不重複同步已同步的鏡像 5.併發同步,能夠經過配置文件調整併發數 6.自動重試失敗的同步任務,能夠解決大部分鏡像同步中的網絡抖動問題 7.不依賴 docker 以及其餘程序json
藉助 image-syncer,只須要保證 image-syncer 的運行環境與須要同步的 registry 網絡連通,你能夠快速地完成從鏡像倉庫的遷移、拷貝以及增量同步,而且對硬件資源幾乎沒有要求(由於 image-syncer 嚴格控制網絡鏈接數目=併發數,因此只有在當單個鏡像層過大的狀況下,併發數目過大可能會打滿內存,內存佔用 <= 併發數 x 最大鏡像層大小);除了使用重傳機制規避同步過程當中可能出現的偶發問題以外, image-syncer 會在運行結束時統計最後同步失敗的鏡像個數,而且打印出詳細的日誌,幫助使用者定位同步過程當中出現的問題。api
image-syncer 運行,只須要用戶提供一個配置文件,內容以下:安全
{ "auth": { // 認證字段,其中每一個對象爲一個registry的一個帳號和 // 密碼;一般,同步源須要具備pull以及訪問tags權限, // 同步目標須要擁有push以及建立倉庫權限,若是沒有提供,則默認匿名訪問 "quay.io": { // registry的url,須要和下面images中對應registry的url相同 "username": "xxx", // 用戶名,可選 "password": "xxxxxxxxx", // 密碼,可選 "insecure": true // registry是不是http服務,若是是,insecure 字段須要爲true,默認是false,可選,支持這個選項須要image-syncer版本 > v1.0.1 }, "registry.cn-beijing.aliyuncs.com": { "username": "xxx", "password": "xxxxxxxxx" }, "registry.hub.docker.com": { "username": "xxx", "password": "xxxxxxxxxx" } }, "images": { // 同步鏡像規則字段,其中條規則包括一個源倉庫(鍵)和一個目標倉庫(值) // 同步的最大單位是倉庫(repo),不支持經過一條規則同步整個namespace以及registry // 源倉庫和目標倉庫的格式與docker pull/push命令使用的鏡像url相似(registry/namespace/repository:tag) // 源倉庫和目標倉庫(若是目標倉庫不爲空字符串)都至少包含registry/namespace/repository // 源倉庫字段不能爲空,若是須要將一個源倉庫同步到多個目標倉庫須要配置多條規則 // 目標倉庫名能夠和源倉庫名不一樣(tag也能夠不一樣),此時同步功能相似於:docker pull + docker tag + docker push "quay.io/coreos/kube-rbac-proxy": "quay.io/ruohe/kube-rbac-proxy", "xxxx":"xxxxx", "xxx/xxx/xx:tag1,tag2,tag3":"xxx/xxx/xx" // 當源倉庫字段中不包含tag時,表示將該倉庫全部tag同步到目標倉庫,此時目標倉庫不能包含tag // 當源倉庫字段中包含tag時,表示只同步源倉庫中的一個tag到目標倉庫,若是目標倉庫中不包含tag,則默認使用源tag // 源倉庫字段中的tag能夠同時包含多個(好比"a/b/c:1,2,3"),tag之間經過","隔開,此時目標倉庫不能包含tag,而且默認使用原來的tag // 當目標倉庫爲空字符串時,會將源鏡像同步到默認registry的默認namespace下,而且repo以及tag與源倉庫相同,默認registry和默認namespace能夠經過命令行參數以及環境變量配置,參考下面的描述 } }
用戶能夠根據配置不一樣的鏡像同步規則組合,以匹配不一樣的遷移/同步需求,如將單個鏡像 repo 同步到多個不一樣的鏡像 repo、將多個源鏡像同步到單個鏡像 repo 中(以 tag 區分)、在同一個 registry 中以不一樣的名字拷貝一個鏡像 repo 等等。 使用時須要注意,若是匿名訪問做爲同步源的 registry 地址,可能存在權限問題沒法 pull 鏡像以及沒法獲取 tags,這種狀況下須要在" auth "中加入有對應權限的帳號密碼;而若是匿名訪問做爲同步目標的 registry 地址,可能存在權限問題沒法 push 鏡像,一樣也可能須要用戶提供有對應權限的帳號密碼。 image-syncer 同時支持 insecure 的 registry(類比 docker 的-- insecure - registry 參數,在" auth "的相應條目中添加 " insecure ": true ),能夠同時在 http 和 https 兩種類型的鏡像服務之間遷移。 image-syncer 還提供了一些簡單的參數來控制程序的運行,包括併發數目控制、重傳次數設置等等:網絡
-h --help 使用說明,會打印出一些啓動參數的當前默認值 --config 設置用戶提供的配置文件所在路徑,使用以前須要建立配置文件,默認爲當前工做目錄下的image-syncer.json文件 --log 打印出來的log文件路徑,默認打印到標準錯誤輸出,若是將日誌打印到文件將不會有命令行輸出,此時須要經過cat對應的日誌文件查看 --namespace 設置默認的目標namespace,當配置文件內一條images規則的目標倉庫爲空,而且默認registry也不爲空時有效,能夠經過環境變量DEFAULT_NAMESPACE設置,同時傳入命令行參數會優先使用命令行參數值 --registry 設置默認的目標registry,當配置文件內一條images規則的目標倉庫爲空,而且默認namespace也不爲空時有效,能夠經過環境變量DEFAULT_REGISTRY設置,同時傳入命令行參數會優先使用命令行參數值 --proc 併發數,進行鏡像同步的併發goroutine數量,默認爲5 --records 指定傳輸過程當中保存已傳輸完成鏡像信息(blob)的文件輸出/讀取路徑,默認輸出到當前工做目錄,一個records記錄了對應目標倉庫的已遷移信息,能夠用來進行連續的屢次遷移(會節約大量時間,但不要把以前本身沒執行過的records文件拿來用),若是有unknown blob之類的錯誤,能夠刪除該文件從新嘗試 --retries 失敗同步任務的重試次數,默認爲2,重試會在全部任務都被執行一遍以後開始,而且也會從新嘗試對應次數生成失敗任務的生成。一些偶爾出現的網絡錯誤好比io timeout、TLS handshake timeout,均可以經過設置重試次數來減小失敗的任務數量
在同步結束以後,image-syncer
會統計成功和失敗的同步任務數目(每一個同步任務表明一個鏡像),並在標準輸出和日誌中打印 "Finished, <NUMBER OF FAILED TASKS> sync tasks failed, <NUMBER OF GENERATED FAILED TASKS> tasks generate failed" 的字樣,從而能夠得到同步的結果。更多FAQ參見 FAQs.md
ACR(Alibaba Cloud Container Registry)是阿里雲提供的容器鏡像託管服務,支持全球20個地域的鏡像全生命週期管理,聯合容器服務等雲產品,打造雲原生應用的一站式體驗。這裏經過將自建 harbor 上的鏡像同步到 ACR,提供 image-syncer 的基本使用示例
1.在阿里雲控制檯上開通容器鏡像服務,並進入 ACR 控制檯
2.建立命名空間,默認倉庫類型決定了當倉庫不存在時,docker push 自動建立的倉庫類型是公有的仍是私有的;若是部分須要同步的目標倉庫不存在,須要打開自動建立倉庫按鈕,讓相似" docker push "的操做能自動建立倉庫
3.建立訪問憑證,對應的帳號即爲 docker login 的帳號,以下圖:
4.上面的操做使用的是主帳號,默認擁有所有權限;爲了進行權限管理,咱們也能夠經過建立 RAM 子帳號,並配置對應權限,這裏的場景中咱們只使用到了建立、更新鏡像倉庫相關權限,最小權限設置以下,訪問控制的資源粒度爲 image-syncer 命名空間:
{ "Statement": [ { "Effect": "Allow", "Action": [ "cr:CreateRepository", "cr:UpdateRepository", "cr:PushRepository", "cr:PullRepository" ], "Resource": [ "acs:cr:*:*:repository/image-syncer/*" ] } ], "Version": "1" }
5.一樣,RAM 帳號須要經過 RAM 用戶登錄入口登錄阿里雲控制檯,並進入 ACR 控制檯建立訪問憑證(同3.)
6.而後咱們能夠經過訪問憑證中建立的密碼,完成以下 image-syncer 的同步配置(配置中使用 RAM 子帳號的訪問憑證);這裏咱們將本地搭建的 harbor( http 服務,要設置 insecure,經過 harbor.myk8s.paas.com:32080 訪問)中的 library/nginx 倉庫同步到華北2(經過爲 registry.cn-beijing.aliyuncs.com 訪問)中的 image-syncer 命名空間下,而且保持倉庫名稱爲 nginx,config.json 以下:
{ "auth": { "harbor.myk8s.paas.com:32080": { "username": "admin", "password": "xxxxxxxxx", "insecure": true }, "registry.cn-beijing.aliyuncs.com": { "username": "acr_pusher@1938562138124787", "password": "xxxxxxxx" } }, "images": { "harbor.myk8s.paas.com:32080/library/nginx": "" } }
7.下載最新的 image-syncer 可執行文件(目前只支持 linux amd64 版本,能夠自行編譯),解壓,並運行工具
執行命令:
# 設置默認目標registry爲registry.cn-beijing.aliyuncs.com,默認目標namespace爲image-syncer # 併發數爲10,重試次數爲10 # 日誌輸出到./log文件下,不存在會自動建立,不指定的話默認會將日誌打印到Stderr # 指定配置文件爲harbor-to-acr.json,內容如上所述 ./image-syncer --proc=10 --config=./harbor-to-acr.json --registry=registry.cn-beijing.aliyuncs.com --namespace=image-syncer --retries=10 --log=./log
一次同步會經歷三個階段:生成同步任務、執行同步任務以及重試失敗任務;其中,每一個同步任務都表明了一個須要同步的 tag (鏡像),若是配置文件中某條規則沒有指定 tag,在「生成同步任務」階段會自動 list 源倉庫全部 tag,並生成對應的同步任務,若是生成同步任務失敗,也會在重試階段進行重試,(故意配錯帳號密碼時)執行輸出以下:
正常運行的輸出:
在運行時,image-syncer 會打印出以下的日誌信息:
ACR 企業版提供企業級容器鏡像、Helm Chart 安全託管能力,擁有企業級安全獨享特性,具有千節點鏡像分發、全球多地域同步能力。提供雲原生應用交付鏈,實現一次應用變動,全球化多場景自動交付。強烈推薦安全需求高、業務多地域部署、擁有大規模集羣節點的企業級客戶使用。
同步到 ACR 企業版和 ACR 普通版所需的操做基本相同:
2.建立命名空間,並對默認倉庫類型進行設置,並打開自動建立倉庫的功能
3.配置公網的訪問控制,須要打開 ACR 企業版的訪問入口,並添加公網白名單,使外部能訪問鏡像服務
4.配置訪問憑證,這部分和 ACR 普通版相同
5.使用訪問憑證中建立的密碼,完成以下 image-syncer 的同步配置;與以前同步到ACR共享版不一樣的是,每一個ACR企業版實例有本身單獨的域名(一個公網可見,一個僅專有網絡可見,若是鏡像同步工具運行在我的環境上須要使用公網域名;若是要使用僅專有網絡可見的域名,則將鏡像同步工具運行在阿里雲ECS實例上,而且經過配置使域名對該ECS所在的專有網絡可見;這裏使用的是公網域名 ruohe-test-registry.cn-shanghai.cr.aliyuncs.com),而且namespace對於每一個不一樣企業版實例之間來講都是隔離的。咱們一樣將本地搭建的 harbor(http 服務,要設置i nsecure,經過 harbor.myk8s.paas.com:32080 訪問)中的 library/nginx 倉庫同步到 ACR 企業版實例中 image-syncer 命名空間下,而且保持倉庫名稱爲 nginx,config.json 以下:
{ "auth": { "harbor.myk8s.paas.com:32080": { "username": "admin", "password": "xxxxxxxxx", "insecure": true }, "ruohe-test-registry.cn-shanghai.cr.aliyuncs.com": { "username": "ruohehhy", "password": "xxxxxxxx" } }, "images": { "harbor.myk8s.paas.com:32080/library/nginx": "" } }
7.運行工具 執行命令
# 設置默認目標registry爲ruohe-test-registry.cn-shanghai.cr.aliyuncs.com,默認目標namespace爲image-syncer # 併發數爲10,重試次數爲10 # 日誌輸出到./log文件下,不存在會自動建立,不指定的話默認會將日誌打印到Stderr # 指定配置文件爲harbor-to-acr.json,內容如上所述 ./image-syncer --proc=10 --config=./harbor-to-acr.json --registry=ruohe-test-registry.cn-shanghai.cr.aliyuncs.com --namespace=image-syncer --retries=10
輸出與前述相同
以上的 image-syncer 知足了你的容器鏡像遷移同步的全部訴求嗎?若是有更多的需求、甚至想共建更多的能力,歡迎訪問 https://github.com/AliyunContainerService/image-syncer 留下 issue,也歡迎加入 Kubernetes 釘釘羣討論
【 Kubernetes 釘釘羣二維碼】
開源不易,長期的維護項目更不容易,你們以爲好就請給這個項目點個 star,公司內的老闆會看這個項目的 star 數量來決定後續能不能投更多的研發資源來維護這個項目,萬分感謝:)
那麼,鏡像倉庫能順利遷移,是否遷雲就能順利進行呢?答案是——並無那麼簡單,倉庫只是遷雲過程當中碰到的問題之一,還須要解決其餘痛點。
對於已經在私有云/公有云上已經把業務應用跑在 k8s 上的用戶來講,如何讓業務在遷雲過程當中不受影響是頭等大事。阿里云云原生應用平臺的解決方案架構師對此已經有了完善的考慮,力助用戶應用高效穩定的遷移到 ACK 服務上。在幫助這些用戶落實遷雲方案的同時,咱們也在不斷思考如何把這些案例中共性的東西作一些沉澱,總結出一些優秀的解決方案、最佳實踐以及開發一些工具來幫助用戶快速完成遷雲的這件事情,這是咱們遷移過程當中爲用戶考慮到的點
若是你有遷移上阿里雲 ACK 的需求,請點擊我!期待你的留言~