天天看點

阿裡雲開源 image-syncer 工具,容器鏡像遷移同步的終極利器

為什麼要做這個工具?

由于阿裡雲上的容器服務 ACK 在使用成本、運維成本、友善性、長期穩定性上大大超過公司自建自維護 Kubernets 叢集,有不少公司紛紛想把之前自己維護 Kubernetes 負載遷移到阿裡雲 ACK 服務上。在遷移過程中,往往會碰到一個不大不小的坑:那就是怎麼把已有的容器鏡像平滑的遷移到阿裡雲鏡像服務 ACR 上。這個問題看起來非常簡單,如果隻有三五個鏡像,隻要做一次 docker pull/docker push 就能完成,但實際生産中涉及到成千上百個鏡像,幾 T 的鏡像倉庫資料時,遷移過程就變的耗時非常漫長,甚至丢失資料。

阿裡雲雲原生應用平台的工程師——也就是我們,發現這是一個通用的需求,使用者會在各種容器鏡像倉庫之間做遷移,或者進一步,期望有同步複制的能力,是以我們研發了 image-syncer 這個項目來支援遷雲,并同時開源給業界大衆,用來解決通用的容器鏡像批量遷移/同步的問題。

這個工具在實際生産中,已經幫助了多家客戶進行鏡像遷移,其中最大鏡像倉庫的總量達到 3T 以上,同步時能跑滿機器帶寬,進行同步任務的機器磁盤容量沒有要求。

image-syncer 簡介

如上所述,在 k8s 叢集遷移場景中,鏡像倉庫之間進行鏡像遷移/同步是基本需求,而使用 docker pull/push 結合腳本的傳統方式進行鏡像同步,有如下幾個局限性:

  1. 依賴磁盤存儲,需要及時進行本地鏡像的清理,并且落盤造成多餘的時間開銷,難以勝任生産場景中大量鏡像的遷移
  2. 依賴 docker 程式,docker daemon 對 pull/push 的并發數進行了嚴格的限制,無法進行高并發同步
  3. 一些功能隻能通過 HTTP api 進行操作,單純使用 docker cli 無法做到,使腳本變得複雜

image-syncer 的定位是一個簡單、易用的批量鏡像遷移/同步工具,支援幾乎所有目前主流的基于 docker registry V2 搭建的鏡像存儲服務,比如 ACR、Docker

Hub、Quay、自建 Harbor 等,目前已經初步經過了 TB 級别的生産環境鏡像遷移驗證,并開源于

https://github.com/AliyunContainerService/image-syncer

,歡迎大家下載下傳使用以及提供寶貴的建議~

工具特性

image-syncer 的特性如下:

1.支援多對多鏡像倉庫同步

2.支援基于 Docker Registry V2 搭建的 docker 鏡像倉庫服務 (如 Docker Hub、 Quay、 阿裡雲鏡像服務 ACR、 Harbor等)

3.同步隻經過記憶體和網絡,不依賴磁盤存儲,同步速度快

4.增量同步, 通過對同步過的鏡像 blob 資訊落盤,不重複同步已同步的鏡像

5.并發同步,可以通過配置檔案調整并發數

6.自動重試失敗的同步任務,可以解決大部分鏡像同步中的網絡抖動問題

7.不依賴 docker 以及其他程式

借助 image-syncer,隻需要保證 image-syncer 的運作環境與需要同步的 registry 網絡連通,你可以快速地完成從鏡像倉庫的遷移、拷貝以及增量同步,并且對硬體資源幾乎沒有要求(因為 image-syncer 嚴格控制網絡連接配接數目=并發數,是以隻有在當單個鏡像層過大的情況下,并發數目過大可能會打滿記憶體,記憶體占用 <= 并發數 x 最大鏡像層大小);除了使用重傳機制規避同步過程中可能出現的偶發問題之外, image-syncer 會在運作結束時統計最後同步失敗的鏡像個數,并且列印出詳細的日志,幫助使用者定位同步過程中出現的問題。

使用指南

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, FAILED TASKS> sync tasks failed, TASKS> tasks generate failed" 的字樣,進而可以獲得同步的結果。更多FAQ參見

FAQs.md

使用示例

ACR(Alibaba Cloud Container Registry)是阿裡雲提供的容器鏡像托管服務,支援全球20個地域的鏡像全生命周期管理,聯合容器服務等雲産品,打造雲原生應用的一站式體驗。這裡通過将自建 harbor 上的鏡像同步到 ACR,提供 image-syncer 的基本使用示例

從自建 harbor 同步鏡像到 ACR

1.在阿裡雲控制台上開通容器鏡像服務,并進入 ACR 控制台

2.

建立命名空間

,預設倉庫類型決定了當倉庫不存在時,docker push 自動建立的倉庫類型是公有的還是私有的;如果部分需要同步的目标倉庫不存在,需要打開自動建立倉庫按鈕,讓類似" docker push "的操作能自動建立倉庫

3.建立通路憑證,對應的賬号即為 docker login 的賬号,如下圖:

阿裡雲開源 image-syncer 工具,容器鏡像遷移同步的終極利器

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 工具,容器鏡像遷移同步的終極利器

正常運作的輸出:

阿裡雲開源 image-syncer 工具,容器鏡像遷移同步的終極利器

在運作時,image-syncer 會列印出如下的日志資訊:

阿裡雲開源 image-syncer 工具,容器鏡像遷移同步的終極利器

從自建 harbor 同步鏡像到 ACR 企業版

ACR 企業版提供企業級容器鏡像、Helm Chart 安全托管能力,擁有企業級安全獨享特性,具備千節點鏡像分發、全球多地域同步能力。提供雲原生應用傳遞鍊,實作一次應用變更,全球化多場景自動傳遞。強烈推薦安全需求高、業務多地域部署、擁有大規模叢集節點的企業級客戶使用。

同步到 ACR 企業版和 ACR 普通版所需的操作基本相同:

1.

建立 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": ""
    }
}           

6.運作工具

執行指令

# 設定預設目标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 滿足了你的容器鏡像遷移同步的所有訴求嗎?如果有更多的需求、甚至想共建更多的能力,歡迎通路

留下 issue,也歡迎加入 Kubernetes 釘釘群讨論

阿裡雲開源 image-syncer 工具,容器鏡像遷移同步的終極利器

【 Kubernetes 釘釘群二維碼】

開源不易,長期的維護項目更不容易,大家覺得好就請給這個項目點個 star,公司内的老闆會看這個項目的 star 數量來決定後續能不能投更多的研發資源來維護這個項目,萬分感謝:)

One More Thing

那麼,鏡像倉庫能順利遷移,是否遷雲就能順利進行呢?答案是——并沒有那麼簡單,倉庫隻是遷雲過程中碰到的問題之一,還需要解決其他痛點。

對于已經在私有雲/公有雲上已經把業務應用跑在 k8s 上的使用者來說,如何讓業務在遷雲過程中不受影響是頭等大事。阿裡雲雲原生應用平台的解決方案架構師對此已經有了完善的考慮,力助使用者應用高效穩定的遷移到 ACK 服務上。在幫助這些使用者落實遷雲方案的同時,我們也在不斷思考如何把這些案例中共性的東西做一些沉澱,總結出一些優秀的解決方案、最佳實踐以及開發一些工具來幫助使用者快速完成遷雲的這件事情,這是我們遷移過程中為使用者考慮到的點

阿裡雲開源 image-syncer 工具,容器鏡像遷移同步的終極利器

如果你有遷移上阿裡雲 ACK 的需求,

請點選我

!期待你的留言~

繼續閱讀