kubesphere生产环境落地实践(三)镜像管理
镜像管理部分,我们分以下三个章节进行讨论:
- 镜像构建
- 镜像清理
- 镜像迁移
镜像构建
这里举个我们后台应用镜像构建的例子,来论述整个流程
方便起见,我们将该应用命名应用A
,并且应用A
为java
应用。
应用A
的构建流程主要分为以下几个部分:
- 应用编译打包
- 应用构建为镜像
- 推送至镜像库
整个流程我们以gitlab-runner
作为CI
工具串联(因为足够简单),gitlab-ci
配置如下
variables:
IMAGE_TAG: "harbor.wl.io/archive/backend"
PRESERVE_PATH: "/download"
stages:
- print
- build
print:
stage: print
script:
- echo "CI_PIPELINE_SOURCE -> $CI_PIPELINE_SOURCE"
- echo "CI_COMMIT_BRANCH -> $CI_COMMIT_BRANCH"
build:
stage: build
script:
- docker build --tag $IMAGE_TAG .
- docker tag $IMAGE_TAG $IMAGE_TAG:$CI_COMMIT_SHORT_SHA
- docker push $IMAGE_TAG
- docker push $IMAGE_TAG:$CI_COMMIT_SHORT_SHA
tags:
- runner-vm-91
rules:
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
需要说明的是,我们以$CI_COMMIT_SHORT_SHA
(gitlab commit id)作为镜像的tag
,保证每次构建镜像tag的唯一性。
镜像清理
由于每次触发构建后,都将生成新的镜像并推送至私有镜像库harbor中,随着时间的推移,镜像库内的镜像呈线性堆积,所以对于私有镜像库内镜像的清理工作尤为重要。(尽管基础镜像层级可以复用,但镜像占用的存储空间依然很大,主要与jar包大小有直接关系)
对于镜像的清理,我们使用habror原生的GC功能,具体配置如下:
- 配置全局GC策略
- 配置repo级GC策略
通过以上两条配置,基本满足我们对镜像清理的需求
镜像迁移
这里所说的镜像迁移,指的是实际投产时,需要将镜像发布至现场(第一次全量)。实际就是将所需镜像导出,传输至现场,导入现场私有库内。
开始阶段我们使用原生docker进行镜像的导出,整个流程如下:
- 获取所需镜像tag列表
- 按行读取列表进行导出(docker pull + docker save)
- 对镜像压缩(gzip)
在实操过程中,我们发现docker批量对镜像导出的效率是及其低的。对几百个镜像拉取、导出、压缩的操作耗时往往为小时级别。
后续我们参考了镜像搬运工具 Skopeo 使用 - 云+社区 - 腾讯云 (tencent.com) 这篇文章,选用skopeo替代docker作为镜像导出、导入工具。效果显著,耗时降为分钟级。
以下为我们使用skopeo导出镜像的样例
variables:
OCI_IMAGE_PATH: "/download"
stages:
- export
export:
stage: export
before_script:
- make download
- sed -i "s#ddd#${CI_COMMIT_BRANCH}#g" harbor.yaml
script:
- ./easyctl export image-list --server-list=harbor.yaml
- sh sync.sh ${CI_COMMIT_BRANCH}
- cp load.sh ${CI_COMMIT_BRANCH}
- tar cvf ${CI_COMMIT_BRANCH}.tar ${CI_COMMIT_BRANCH}
- sudo mv ${CI_COMMIT_BRANCH}.tar $OCI_IMAGE_PATH
after_script:
- rm -rf ${BRANCH_NAME}
tags:
- runner-vm-91
sync.sh
#!/bin/bash
GREEN_COL="\\033[32;1m"
RED_COL="\\033[1;31m"
NORMAL_COL="\\033[0;39m"
SOURCE_REGISTRY=harbor.chs.neusoft.com
REGISTRY_USER=admin
REGISTRY_PASS=Harbor-12345
TARGET_REGISTRY=""
PROJECT_NAME=$1
IMAGES_DIR=$PROJECT_NAME/images
: ${IMAGES_DIR:="images"}
: ${IMAGES_LIST_FILE:="$PROJECT_NAME/image-list.txt"}
: ${TARGET_REGISTRY:="hub.k8s.li"}
: ${SOURCE_REGISTRY:="harbor.chs.neusoft.com"}
BLOBS_PATH="docker/registry/v2/blobs/sha256"
REPO_PATH="docker/registry/v2/repositories"
set -eo pipefail
CURRENT_NUM=0
TOTAL_NUMS=$(cat "$IMAGES_LIST_FILE" | wc -l)
skopeo_sync() {
mkdir -p $2/$1
if skopeo copy --all --insecure-policy --src-tls-verify=false --dest-tls-verify=false \
--override-arch amd64 --override-os linux docker://$1 oci:$2/$1 > /dev/null; 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
}
if [ -d $IMAGES_DIR ];then
rm -rf $IMAGES_DIR
fi
mkdir -p $IMAGES_DIR
while read line
do
let CURRENT_NUM=${CURRENT_NUM}+1
skopeo_sync ${line} $IMAGES_DIR
done < ${IMAGES_LIST_FILE}
load.sh
#!/bin/bash
GREEN_COL="\\033[32;1m"
RED_COL="\\033[1;31m"
NORMAL_COL="\\033[0;39m"
SOURCE_REGISTRY=$1
TARGET_REGISTRY=$2
IMAGES_DIR=$2
: ${IMAGES_DIR:="images"}
: ${IMAGES_LIST_FILE:="image-list.txt"}
: ${TARGET_REGISTRY:="hub.k8s.li"}
: ${SOURCE_REGISTRY:="harbor.chs.neusoft.com"}
BLOBS_PATH="docker/registry/v2/blobs/sha256"
REPO_PATH="docker/registry/v2/repositories"
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)
skopeo_sync() {
echo "skopeo copy --insecure-policy --src-tls-verify=false --dest-tls-verify=false \
--override-arch amd64 --override-os linux oci:$2/$1 docker://$1"
if skopeo copy --insecure-policy --src-tls-verify=false --dest-tls-verify=false \
--override-arch amd64 --override-os linux oci:$2/$1 docker://$1 > /dev/null; 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
}
while read line
do
let CURRENT_NUM=${CURRENT_NUM}+1
skopeo_sync ${line} $IMAGES_DIR
done < $IMAGES_LIST_FILE
harbor.yml
harbor:
address: 192.168.1.1
domain: harbor.wl.io
user: admin
password: 123456
export-all: false
preserve-dir: ./
projects:
- ddd
值得说明的是,我们使用easyctl 从harbor库中导出镜像tag列表(按repo导出)
镜像tag列表如下:
images/images-list.txt
harbor.wl.io/apache/skywalking-java-agent:8.6.0-alpine
harbor.wl.io/apache/skywalking-oap-server:8.6.0-es7
harbor.wl.io/apache/skywalking-ui:8.6.0
harbor.wl.io/b2i/binary-nginx-builder:latest
harbor.wl.io/b2i/nginx-centos7-s2ibuilder:latest
harbor.wl.io/b2i/java-8-runtime:base-alpha
harbor.wl.io/b2i/java-8-runtime:base
harbor.wl.io/b2i/java-8-runtime:advance
harbor.wl.io/b2i/java-8-centos7:base
harbor.wl.io/b2i/java-8-centos7:advance
harbor.wl.io/b2i/tomcat9-java8-runtime:latest
harbor.wl.io/b2i/tomcat8-java8-runtime:latest
harbor.wl.io/b2i/tomcat8-java8-centos7:latest
harbor.wl.io/b2i/tomcat9-java8-centos7:latest
以上内容就是我们在使用kubepshere过程中,对于镜像制品的管理。