迁移流程
- 两个不同的Harbor实例迁移数据(含镜像数据和数据库数据)
迁移方式
| Harbor 镜像 | skopeo | image-syncer | 手工 |
---|
机制 | 基于策略的内容机制:支持多种过滤器(镜像库、tag和标签)与多种触发模式(手动,基于时间以及定时)且实现对推送和拉或模式的支持 | 直接将 registry 上的 blob 复制到另一个 registry | 1. 同步只经过内存和网络,不依赖磁盘存储,同步速度快 2. 增量同步, 通过对同步过的镜像blob信息落盘,不重复同步已同步的镜像 3. 并发同步,可以通过配置文件调整并发数 4. 自动重试失败的同步任务,可以解决大部分镜像同步中的网络抖动问题 不依赖docker以及其他程序 | 拷贝镜像数据+导入导出PG数据库数据 |
官方文档 | https://goharbor.io/docs/2.2.0/administration/configuring-replication/create-replication-endpoints/ | https://github.com/containers/skopeo/blob/main/docs/skopeo-sync.1.md | https://github.com/AliyunContainerService/image-syncer/blob/master/README-zh_CN.md | |
优点 | 界面配置,无需编码 | 1. 单机和高可用Harbor都可用 2. 传输效率高,不依赖docker
| 1.单机Harbor可用 2.传输效率高 | 耗时短 |
缺点 | 失败率较高 | 但centos 7自带版本是0.14,版本低,没有sync命令,新版本需要自己打包 | 高可用Harbor不可用 | 数据环境数据几百G, 命令cp不可靠 |
Skopeo 使用
什么是Skopeo?
skopeo 使用 API V2 Registry,例如 Docker Registry、Atomic Registry、私有Registry、本地目录和本地 OCI 镜像目录。skopeo 不需要运行守护进程,它可以执行的操作包括:
- 通过各种存储机制复制镜像,例如,可以在不需要特权的情况下将镜像从一个Registry复制到另一个Registry
- 检测远程镜像并查看其属性,包括其镜像层,无需将镜像拉到本地
- 从镜像库中删除镜像
- 当存储库需要时,skopeo 可以传递适当的凭据和证书进行身份验证
镜像存储特点
根据 Robin 大佬在 《镜像仓库中镜像存储的原理解析》文章里得出的结论:
- 通过 Registry API 获得的两个镜像仓库中相同镜像的 manifest 信息完全相同。
- 两个镜像仓库中相同镜像的 manifest 信息的存储路径和内容完全相同。
- 两个镜像仓库中相同镜像的 blob 信息的存储路径和内容完全相同
skopeoo 安装
源码编译(静态)
描述: 要构建 skopeo 二进制文件您至少需要 Go 1.12 版本以上, 其次构建 skopeo 有两种方法,即在容器中
或者在本地环境中构建(安装环境较为复杂), 此处为了方便演示将采用容器方式进行编译构建。
# 1.拉取skopeo源码到本地
$ git clone --depth=1 https://github.com/containers/skopeo.git # https://github.com/containers/skopeo.git
$ cd skopeo
$ sed -i 's#proxy.golang.org#https://goproxy.cn#g' skopeo/Makefile
# 2.下载镜像构建依赖
$ sudo apt-get install go-md2man # 构建手册依赖于 go-md2man。
$ whereis go-md2man # 获得本机中go-md2man路径。
# 3.构建静态二进制文件
$ BUILD_IMAGE="golang:latest"
$ docker run --name skopeo-build -v $PWD:/src -v /usr/bin/go-md2man:/go/bin/go-md2man -w /src -e CGO_ENABLED=0 -e GOPROXY=https://goproxy.cn,direct ${BUILD_IMAGE} \
sh -c 'make BUILDTAGS=containers_image_openpgp GO_DYN_FLAGS='
# CGO_CFLAGS="" CGO_LDFLAGS="" GO111MODULE=on go build -mod=vendor -ldflags '-X main.gitCommit=df4d82b960572c19e9333381a203c0ac475766d7 ' -gcflags "" -tags "containers_image_openpgp" -o bin/skopeo ./cmd/skopeo
# 4.运行编译生成的skopeo可执行文件
$ cd ./bin # /opt/software/skopeo/bin
$ ./skopeo --help
# Various operations with container images and container image registries
# .......
# Use "skopeo [command] --help" for more information about a command.
构建关键参数解析:
- CGO_ENABLED=0 : 设置该环境变量, 禁用 CGO 会导致 Go 在可能的情况下更喜欢静态连接库,而不是动态链接到系统库 (解决可以在Ubuntu或者其它linux发行版中执行编译后二进制文件)。
- GOPROXY=https://goproxy.cn,direct : Golong 依赖下载镜像站,加快go get依赖拉拉取。
- BUILDTAGS=containers_image_openpgp : 设置该make参数消除了对libgpgme 及其配套库的依赖, Skopeo 的一些特性依赖于非 Go 库,例如 libgpgme 和 libdevmapper。
- GO_DYN_FLAGS= : 清空该make参数 (否则会强制创建动态可执行文件)
2.分发包安装
描述: skopeo 可能已经打包在您的发行版中,此处以ubuntu 20.04为例进行安装。
在线方式
sudo apt-get -y update
sudo apt-get -y install skopeo
sudo yum makecache
sudo yum -y install skopeo
sudo dnf makecache
sudo dnf -y install skopeo
CentOS 7 默认下载的skopeo是0.1.40,如果需要使用最新的版本,需要自己通过源码构建
安装 dnf文档
离线方式
. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" |
sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key | sudo apt-key add -
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y install skopeo
Skopeo centos7 RPM 存档位置
https://centos.pkgs.org/7/centos-extras-x86_64/skopeo-0.1.40-11.el7_8.x86_64.rpm.html
3.容器安装运行
Skopeo 容器镜像可在 quay.io/skopeo/stable:latest 获得, 例如我们采用podman命令进行如下操作:
podman run docker://quay.io/skopeo/stable:latest copy --help
我们可以使用yum
或dnf
安装skopeo
在 CentOS 7 上。在本教程中,我们讨论了这两种方法,但你只需要选择一种方法来安装 skopeo。
skopeoo 命令
描述: skopeoo 是操作各种容器镜像和容器镜像仓库的工具,其使用方法及其可用命令如下:
./skopeo --help
Usage:
skopeo [flags]
skopeo [command]
Available Commands:
copy
delete
help
inspect
list-tags
login
logout
manifest-digest
standalone-sign
standalone-verify
sync
Flags:
--command-timeout duration
--debug
--insecure-policy
--override-arch ARCH
--override-os OS
--override-variant VARIANT
--policy string
--registries.d DIR
--tmpdir string
-h, --help help for skopeo
-v, --version Version for Skopeo
skopeo初体验
描述: 在使用体验skopeo之前,我们需要了解一哈 Skopeo 可以在哪些镜像和存储库类型上执行镜像操作(官网文档走一波):
Repository types | Describe | Example |
---|
containers-storage:docker-reference | 适用于后端是 Podman, CRI-O, Buildah 的情况 | containers-storage: |
dir:path | 适用于将manifest, layer tarballs 和 signatures 存储为单独文件的现有本地目录路径的情况 | dir:/tmp/alpine:latest |
docker://docker-reference | 适用于Registry中实现"Docker Registry HTTP API V2"的镜像的情况 | docker://harbor.fly.com/mysql:v5.6 |
docker-archive:path[:docker-reference] | 适用于采用docker save 命令导出镜像以tar格式存储的文件的情况 | docker-archive:alpine.tar |
docker-daemon:docker-reference | 适用于存储在 docker 守护进程内部存储中的图像的情况 | docker-daemon:alpine:latest |
oci:path:tag | 适用于符合"Open Container Image Layout Specification"的目录中的图像标记 | oci:alpine:latest |
温馨提示: 同一个镜像存在的方式有可能不同,不同类型方式存储对镜像的 layer 处理的方式也不一样。
skopeo批量同步Harbor镜像
1. 生成待同步的镜像列表文件
#!/bin/bash
if [[ -z $1 || -z $2 ]]; then
echo "SOURCE_REGISTRY OR TARGET_REGISTRY is missing"
echo "please execute the script in the following format,case: sh list_harbor_image.sh HARBOR_ADDR HARBOR_ADMIN_PASSWORD"
echo "Example: sh list_harbor_image.sh 10.0.135.26:5000 Harbor123 "
exit
fi
HARBOR_ADDR=$1
HARBOR_AUTH=admin:$2
IMAGES_FILE=harbor-images-list.txt
Project_List=$(curl -s -u ${HARBOR_AUTH} -H "Content-Type: application/json" -X GET http://${HARBOR_ADDR}/api/v2.0/projects?page_size=100 | python -m json.tool | grep name | awk '/"name": /' | awk -F '"' '{print $4}')
echo -e "【Harbor<${HARBOR_ADDR}>项目列表】: \n ${Project_List}"
for Project in $Project_List;do
PAGE_NUM=1
while true; do
Image_Names=$(curl -s -u ${HARBOR_AUTH} -X GET "http://${HARBOR_ADDR}/api/v2.0/projects/$Project/repositories?page_size=100&page=${PAGE_NUM}" | python -m json.tool | grep name | awk '/"name": /' | awk -F '"' '{print $4}')
Image_Size=`echo "${Image_Names}" | wc -l`
echo -e "【Harbor<${HARBOR_ADDR}>, 项目<${Project}>镜像列表大小<${Image_Size}>, 详情】: \n ${Image_Names}"
for Image in $Image_Names;do
Image_Tags=$(curl -s -u ${HARBOR_AUTH} -H "Content-Type: application/json" -X GET http://${HARBOR_ADDR}/v2/$Image/tags/list | awk -F '"' '{print $8,$10,$12}')
for Tag in $Image_Tags;do
if [ ! -z "${Tag}" ] || [[ ! ${Tag} =~ 400 ]] ||[[ ! ${Tag} =~ 404 ]];then
echo "$Image:$Tag" >> ${IMAGES_FILE}
fi
done
done
if [ "${Image_Size}" -lt "100" ]; then
break
else
let PAGE_NUM=${PAGE_NUM}+1
fi
done
done
2. 基于 skopeo copy机制同步
#!/bin/bash
GREEN_COL="\\033[32;1m"
RED_COL="\\033[1;31m"
NORMAL_COL="\\033[0;39m"
if [[ -z $1 || -z $2 ]]; then
echo " SOURCE_REGISTRY OR TARGET_REGISTRY OR HARBOR_ADMIN_PASSWORD is missing"
echo "please execute the script in the following format,case: sh skopeo_transfer_image.sh SOURCE_REGISTRY TARGET_REGISTRY HARBOR_ADMIN_PASSWORD"
echo "Example: sh skopeo_transfer_image.sh 10.0.135.126:5000 10.16.16.215:5000 Harbor123 "
exit
fi
SOURCE_REGISTRY=$1
TARGET_REGISTRY=$2
HARBOR_AUTH=admin:$3
IMAGES_LIST_FILE="harbor-images-list.txt"
set -eo pipefail
CURRENT_NUM=0
ALL_IMAGES="$(sed -n '/#/d;s/:/:/p' ${IMAGES_LIST_FILE} | sort -u)"
TOTAL_NUMS=$(echo "${ALL_IMAGES}" | wc -l)
echo -e "$GREEN_COL Starting 【Image Trasfer】: sync $1 to $2 ,\n 【Image Total Nums】: ${TOTAL_NUMS}, \n 【Image List】:\n ${ALL_IMAGES} "
skopeo_copy() {
if skopeo copy docker://$1 docker://$2 \
--src-tls-verify=false --dest-tls-verify=false --dest-creds ${HARBOR_AUTH}; then
echo -e "$GREEN_COL Progress: ${CURRENT_NUM}/${TOTAL_NUMS} sync $1 to $2 successful $NORMAL_COL"
else
echo -e "$RED_COL Progress: ${CURRENT_NUM}/${TOTAL_NUMS} sync $1 to $2 failed $NORMAL_COL"
exit 2
fi
}
for image in ${ALL_IMAGES}; do
let CURRENT_NUM=${CURRENT_NUM}+1
skopeo_copy ${SOURCE_REGISTRY}/${image} ${TARGET_REGISTRY}/${image}
done
3. 一键执行
#!/bin/bash
if [[ -z $1 || -z $2 || -z $3 ]]; then
echo " SOURCE_REGISTRY OR TARGET_REGISTRY is missing"
echo "please execute the script in the following format,case: sh harbor_transfer.sh SOURCE_REGISTRY HARBOR_ADMIN_PASSWORD TARGET_REGISTRY"
echo "Example: sh harbor_transfer.sh 10.0.135.126:5000
Harbor123 10.16.16.215:5000 "
exit
fi
SOURCE_REGISTRY=$1
HARBOR_ADMIN_PASSWORD=$2
TARGET_REGISTRY=$3
echo -e "【 1/2 Harbor迁移-导出镜像列表】:存放 harbor-images-list.txt"
sh -v list_harbor_image.sh ${SOURCE_REGISTRY} ${HARBOR_ADMIN_PASSWORD}
echo -e "【 2/2 Harbor迁移-迁移镜像】:遍历 harbor-images-list.txt"
sh -v skopeo_transfer_image.sh ${SOURCE_REGISTRY} ${TARGET_REGISTRY} ${HARBOR_ADMIN_PASSWORD}
执行效果
一键执行
阿里image-syncer使用
下载和安装
在releases页面可下载源码以及二进制文件
手动编译
go get github.com/AliyunContainerService/image-syncer
cd $GOPATH/github.com/AliyunContainerService/image-syncer
make
使用用例
./image-syncer -h
./image-syncer --proc=6 --auth=./auth.json --images=./images.json --namespace=ruohe \
--registry=registry.cn-beijing.aliyuncs.com --retries=3
配置文件
在 v1.2.0 版本之后,image-syncer 的配置文件支持JSON和YAML两种格式,并且支持将原config文件替换为一个认证信息文件和一个镜像同步文件。详细的配置文件示例可在目录 example 下找到,旧版本的配置文件格式(auth 和 images 字段放在一起的版本,通过 --config 参数指定)也是兼容的,目录下 config.json
为示例。
认证信息
auth.json
包含了所有仓库的认证信息
{
"quay.io": {
"username": "xxx",
"password": "xxxxxxxxx",
"insecure": true
},
"registry.cn-beijing.aliyuncs.com": {
"username": "xxx",
"password": "xxxxxxxxx"
},
"registry.hub.docker.com": {
"username": "xxx",
"password": "xxxxxxxxxx"
},
"quay.io/coreos": {
"username": "abc",
"password": "xxxxxxxxx",
"insecure": true
}
}
镜像同步文件
{
"quay.io/coreos/kube-rbac-proxy": "quay.io/ruohe/kube-rbac-proxy",
"xxxx":"xxxxx",
"xxx/xxx/xx:tag1,tag2,tag3":"xxx/xxx/xx"
}
更多参数
image-syncer
的使用比较简单,但同时也支持多个命令行参数的指定:
-h --help 使用说明,会打印出一些启动参数的当前默认值
--config 设置用户提供的配置文件路径,使用之前需要创建此文件,默认为当前工作目录下的config.json文件。这个参数与 --auth和--images 的
作用相同,分解成两个参数可以更好地区分认证信息与镜像仓库同步规则。建议使用 --auth 和 --images.
--auth 设置用户提供的认证文件所在路径,使用之前需要创建此认证文件,默认为当前工作目录下的auth.json文件
--images 设置用户提供的镜像同步规则文件所在路径,使用之前需要创建此文件,默认为当前工作目录下的images.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之类的错误,可以删除该文件重新尝试,image-syncer 在 >= v1.1.0 版本中移除了对于records文件的依赖
--retries 失败同步任务的重试次数,默认为2,重试会在所有任务都被执行一遍之后开始,并且也会重新尝试对应次数生成失败任务的生成。一些偶尔出现的网络错误比如io timeout、TLS handshake timeout,都可以通过设置重试次数来减少失败的任务数量
--os 用来过滤源 tag 的 os 列表,为空则没有任何过滤要求,只对非 docker v2 schema1 media 类型的镜像格式有效
--arch 用来过滤源 tag 的 architecture 列表,为空则没有任何过滤要求
参考链接:
https://github.com/containers/skopeo
https://github.com/containers/skopeo/blob/main/docs/skopeo-sync.1.md
https://goharbor.io/docs/2.2.0/administration/configuring-replication/create-replication-endpoints/
https://github.com/AliyunContainerService/image-syncer/blob/master/README-zh_CN.md
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)