描述: Harbor 用于存储和分发Docker企业级镜像Registry通过增加安全、标识、管理等必要的功能特性,服务器扩展了开源 Docker Distribution。作为企业级私有Registry服务器,Harbor提供更好的性能和安全性。提高用户使用Registry环境传输镜像的施工和运行效率。
-
Harbor企业级私有镜像存储仓库入门实践(https://blog.weiyigeek.top/2020/6/22/510.html)
-
如何使用Skopeo做一个优雅的镜像搬运工(https://blog.weiyigeek.top/2022/1/20/584.html)
由于Harbor是安装在Kubernetes在调整集群内部的网络通信插件时, 工作节点不能通过浏览器访问 nodePort访问集群中的方式Harbor同时,外部不能通过服务ingress来代理转发harbor,因此,为了尽快恢复镜像仓库,采用Skopeo镜像迁移的方式如下。
Kubernetes 版本: v1.22.2 kubeadm version: &version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"clean", BuildDate:"2021-09-15T21:37:34Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"} skopeo 版本: 1.5.3-dev commit: df4d82b960572c19e9333381a203c0ac475766d7 Harbor 版本: v2.1.3-b6de84c5 $ kubectl get deploy -n harbor # NAME READY UP-TO-DATE AVAILABLE AGE # harbor-harbor-chartmuseum 1/1 1 1 300d # harbor-harbor-clair 1/1 1 1 300d # harbor-harbor-core 1/1 1 1 300d # harbor-harbor-jobservice 1/1 1 1 300d # harbor-harbor-notary-server 1/1 1 1 300d # harbor-harbor-notary-signer 1/1 1 1 300d # harbor-harbor-portal 1/1 1 1 300d # harbor-harbor-registry 1/1 1 1 300d
-
Step 1.在工作节点执行以下命令,查看仓库中的镜像信息。
# Harbor 默认用户和认证密钥(必须更改正式环境) USER="admin" TOKEN="Harbor12345" # 通过 Harbor API 检查镜像名称 curl --insecure -u ${USER}:${TOKEN} https://harbor.cloud/v2/_catalog 2>/dev/null|jq .repositories[]|tr -d '"' >> image_names.txt # 查看 image_names.txt 输出结果 devops/bianmin devops/bitnami-redis-cluster devops/bmcx
-
Step 2.利用for循环获取Tags并拼接镜像和tag信息
for name in $(cat image_names.txt);do tags=`curl -u admin:Harbor12345 --insecure https://harbor.cloud/v2/${name}/tags/list 2>/dev/null|jq ".tags[]"|tr -d '"'` for tag in $tags;do echo $name:$tag >>image_tags.txt; done done # 查看 image_tags.txt 输出结果 devops/bianmin:1.0.7-SNAPSHOT devops/bianmin:stress devops/bitnami-redis-cluster:6.0.10-debian-10-r5 devops/bmcx:1.0.7-SNAPSHOT devops/bmcx:1.1.0-SNAPSHOT devops/bmcx:latest
-
Step 例如,我们可以找到一个
devops/bmcx:1.1.0-SNAPSHOT
镜像分析其路径特征。
# 1.环境变量设置 REPO_DIR="docker/registry/v2/repositories" BLOB_DIR="docker/registry/v2/blobs/sha256" cd /storage/pvc/devops/harbor-harbor-harbor-registry-pvc-151479ef-44f1-44dd-960c-afcbf12ba8a8/ # 2.查看repositories目录中存在的所有镜像current路径 for image in $(find ${REPO_DIR} -type d -name "current"); do echo ${image} >> repo_current.txt done # 3.查看指定bmcx:1.1.0-SNAPSHOT镜像的current路径 grep "1.1.0-SNAPSHOT" repo_current.txt # 4.提取路径中镜像的相关信息 echo 'docker/registry/v2/repositories/devops/bmcx/_manifests/tags/1.1.0-SNAPSHOT/current' | awk -F '/' '{print $5"/"$6":"$9}' # devops/bmcx:1.1.0-SNAPSHOT # 5.检查镜像link信息 cat 'docker/registry/v2/repositories/devops/bmcx/_manifests/tags/1.1.0-SNAPSHOT/current/link' | sed 's/sha256://' # 68acf0f6c61b11bb79d6787146ed3bd88850b9071b3b59d86439d55ae5e31928 # 6.检查镜像link中各层 link=68acf0f6c61b11bb79d6787146ed3bd88850b9071b3b59d86439d55ae5e31928 cat docker/registry/v2/blobs/sha256/${link:0:2}/${link}/data { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2 json", "config": { "mediaType": "application/vnd.docker.container.image.v1 json", "size": 2429, "digest": "sha256:b938271c3bd17a187e5c95508adf49093f042cb176a3652c74a76e6d9770eb5b" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 723146, "digest": "sha256:07a152489297fc2bca20be96fab3527ceac5668328a30fd543a160cd689ee548" }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 132, "digest": "sha256:8142e84f0be01a60008360c5d5592e3f02507968b548797513ef7d5080dd5d0c" }, { "mediaType": "application/vnd.docker.imge.rootfs.diff.tar.gzip",
"size": 43984533,
"digest": "sha256:702d51e3f3237c8ffbabeefec12934cc2a9e5b6f01fc414cf17f708ec1c09d0f"
}
]
}
# 7.使用正则匹配出所有的 sha256 值然后排序去重
images_layer=docker/registry/v2/blobs/sha256/${link:0:2}/${link}/data
layers=$(grep -Eo "\b[a-f0-9]{64}\b" ${images_layer} | sort -n | uniq)
b938271c3bd17a187e5c95508adf49093f042cb176a3652c74a76e6d9770eb5b
07a152489297fc2bca20be96fab3527ceac5668328a30fd543a160cd689ee548 # 以此层为例
702d51e3f3237c8ffbabeefec12934cc2a9e5b6f01fc414cf17f708ec1c09d0f
8142e84f0be01a60008360c5d5592e3f02507968b548797513ef7d5080dd5d0c
# 8.查看镜像各层的数据压缩文件
layer=07a152489297fc2bca20be96fab3527ceac5668328a30fd543a160cd689ee548
ls ${BLOB_DIR}/${layer:0:2}/${layer}/data # application/vnd.docker.image.rootfs.diff.tar.gzip
-
Step 4.将registry-v2存储的镜像转换为skopeo工具可以识别的目录架构, 即将 harbor 中的镜像导出为 skopeo dir 的形式。
# 定义生成 skopeo 目录
mkdir ./docker/skopeo/devops/bmcx:1.1.0-SNAPSHOT
ln ./docker/registry/v2/blobs/sha256/${link:0:2}/${link}/data ./docker/skopeo/devops/bmcx:1.1.0-SNAPSHOT/manifest.json
# 创建镜像各层硬链接
ln ./docker/registry/v2/blobs/sha256/b9/b938271c3bd17a187e5c95508adf49093f042cb176a3652c74a76e6d9770eb5b/data ./docker/skopeo/devops/bmcx:1.1.0-SNAPSHOT/b938271c3bd17a187e5c95508adf49093f042cb176a3652c74a76e6d9770eb5b
ln ./docker/registry/v2/blobs/sha256/07/
07a152489297fc2bca20be96fab3527ceac5668328a30fd543a160cd689ee548/data ./docker/skopeo/devops/bmcx:1.1.0-SNAPSHOT/07a152489297fc2bca20be96fab3527ceac5668328a30fd543a160cd689ee548
ln ./docker/registry/v2/blobs/sha256/70/702d51e3f3237c8ffbabeefec12934cc2a9e5b6f01fc414cf17f708ec1c09d0f/data ./docker/skopeo/devops/bmcx:1.1.0-SNAPSHOT/702d51e3f3237c8ffbabeefec12934cc2a9e5b6f01fc414cf17f708ec1c09d0f
ln ./docker/registry/v2/blobs/sha256/81/8142e84f0be01a60008360c5d5592e3f02507968b548797513ef7d5080dd5d0c
-
Step 5.最后利用如下
skopeo copy
命令将将 dir 格式的镜像复制到harbor中。
skopeo sync --insecure-policy --src-tls-verify=false --dest-tls-verify=false --src dir --dest docker ./docker/skopeo/devops/bmcx:1.1.0-SNAPSHOT harbor.weiyigeek.top/devops/bmcx:1.1.0-SNAPSHOT
-
Step 6.最后采用木子提供的shell脚本进行将k8s中harbor的registry数据进行批量同步操作。
#!/bin/bash
# Desc:Harbor v2.x
REGISTRY_DOMAIN="harbor.weiyigeek.top"
REGISTRY_PATH="/storage/pvc/devops/harbor-harbor-harbor-registry-pvc-151479ef-44f1-44dd-960c-afcbf12ba8a8"
# 切换到 registry 存储主目录下
cd ${REGISTRY_PATH}
# - 生成 skopeo sync 同步所需目录格式
gen_skopeo_dir() {
# 定义 registry 存储的 blob 目录 和 repositories 目录,方便后面使用
BLOB_DIR="docker/registry/v2/blobs/sha256"
REPO_DIR="docker/registry/v2/repositories"
# 定义生成 skopeo 目录
SKOPEO_DIR="docker/skopeo"
# 通过 find 出 current 文件夹可以得到所有带 tag 的镜像,因为一个 tag 对应一个 current 目录
for image in $(find ${REPO_DIR} -type d -name "current"); do
# 根据镜像的 tag 提取镜像的名字
# 例如 image 的值为 "docker/registry/v2/repositories/devops/kubectl/_manifests/tags/1.16.6/current"
name=$(echo ${image} | awk -F '/' '{print $5"/"$6":"$9}')
link=$(cat ${image}/link | sed 's/sha256://')
# 判断镜像是否需要同步,如不需则跳过,否则创建skopeo需要的对应目录。
# flag=$(grep -c "${name}" /tmp/image_tags.txt)
# 如果不行进行镜像过滤筛选则可以置为1即可。
flag=1
if [ $flag -ne 1 ];then
echo "${name}" >> /tmp/not_push_image_tags.txt
continue;
else
# 创建镜像的硬链接需要的目录
mkdir -vp "${SKOPEO_DIR}/${name}"
mfs="${BLOB_DIR}/${link:0:2}/${link}/data"
# 硬链接镜像的 manifests 文件到目录的 manifest 文件
ln ${mfs} ${SKOPEO_DIR}/${name}/manifest.json
# 使用正则匹配出manifest.json文件中所有的 sha256 值,然后进行排序去重。
layers=$(grep -Eo "\b[a-f0-9]{64}\b" ${mfs} | sort -n | uniq)
# 遍历镜像各层的sha256编码,按照指定方式进行创建硬链接
for layer in ${layers}; do
# 硬链接 registry 存储目录里的镜像 layer 和 images config 到镜像的 dir 目录
ln ${BLOB_DIR}/${layer:0:2}/${layer}/data ${SKOPEO_DIR}/${name}/${layer}
done
fi
done
}
# - 使用 skopeo sync 将 dir 格式的镜像同步到 harbor
sync_image() {
for project in $(ls ${SKOPEO_DIR}); do
skopeo sync --insecure-policy --src-tls-verify=false --dest-tls-verify=false --src dir --dest docker ${SKOPEO_DIR}/${project} ${REGISTRY_DOMAIN}/${project}
done
}
gen_skopeo_dir
sync_image
执行结果如下:
Step 7.镜像同步完成后,我们可以通过访问harbor前端UI界面进行查看同步后的镜像以及其tags信息。
参考地址: https://blog.k8s.li/select-registry-images.html
本文至此完毕,更多技术文章,尽情期待下一章节!
欢迎各位志同道合的朋友一起学习交流,如文章有误请在下方留下您宝贵的经验知识,个人邮箱地址或者个人公众号联系我。
更多文章来源于【 】,个人首页地址 】
专栏书写不易,如果您觉得这个专栏还不错的,请给这篇专栏 ,这将对我的肯定,谢谢!。
往期相关文章
如何使用Skopeo做一个优雅的镜像搬运工
K9s之Kubernetes集群管理交互工具实践
Kubernetes 映射外部服务到集群内部的场景
↓↓↓ 更多文章,请点击下方阅读原文。