本文将介绍 Harbor 从 v1.10.7 升级到 v2.10.0,以及如何将 Harbor 从 v2.10 回滚到 v1.10.7。

升级条件

  • Linux服务器
  • 4 个 CPU 和 8 GB 内存(强要求),100G可用空间(跨多版本时存放备份文件以及镜像文件,这部分要求)
  • Docker-compose > 1.19.0+
  • 备份现有的 Harbor /data/database 目录

本次升级主要是使用了 harbor 内置的数据库,所以升级步骤比较容易。

官方升级路线

harbor 的升级,是不能跨很多版本进行升级,官方对此有详细说明 [1] ,可以看到路线为:

1.10.0 [1] => 2.4.0 [2] => 2.6.0 [3] => 2.8.0 [4] => 2.10.0 [5]

模拟升级步骤

github release 页下载对应的安装包

解压

bash
1
2
# 命令主要为将harbor压缩包内文件解压到指定目录中,由于 harbor 解压后文件名无论版本如何都为“harbor”
$ mkdir ./harbor-v1.10 && tar -xf harbor-offline-installer-v1.10.0.tgz -C ./harbor-v1.10 --strip-components 1

备份默认的配置文件(仅限于 v1.10.x,v2.x均为 harbor.tmpl)

bash
1
cp harbor.yml harbor.yaml.backup

清除注释

bash
1
grep -Ev '^#|^$|^\s*(#|//)' harbor.yml.tmpl > harbor.yml.clean_annotation

修改一些默认配置

bash
1
2
3
4
5
6
7
\cp -a harbor.yml.clean_annotation harbor.yml
# 如果需要则关闭https
sed -i  '/https:/,+3s/.*/# &/' harbor.yml
# 替换默认harbor郁闷
sed -i "s@hostname: reg.mydomain.com@hostname: img.test.com@g" harbor.yml
# 修改默认目录
sed -i "s@data_volume: /data@data_volume: /data/harbor@g" harbor.yml

启动服务

bash
1
./install.sh

升级步骤

在升级前首先要缕清升级的内容,官方在升级时存在两个步骤,配置文件升级与数据库 schema 升级;并且需要知道升级的路线图,这里是从 1.10.0 升级至本文撰写时最新版本 2.10.0,所以查看官方升级路线为 1.10.0 => 2.4.0 => 2.6.0 => 2.8.0 => 2.10.0。总结升级所需变更如下:

  • harbor的配置文件升级
  • 数据库 schema 升级,由 harbor-core 组件自动完成
  • 升级路线:1.10.0 => 2.4.0 => 2.6.0 => 2.8.0 => 2.10.0

备份当前 harbor 版本

备份当前版本是为了如果需要回滚的话,可以快速的回滚到所需的版本

bash
1
2
cd harbor 
docker-compose down 

备份 Harbor 的当前文件,以便您可以在必要时回滚到当前版本。

备份数据库文件

我们知道了,升级主要是对数据库 schema 进行reschema,Harbor 的每次新版本发布时新的功能及对老功能、代码的重构都会导致数据库模型的变更,因此几乎每次升级都需要升级数据库模式。配置文件数据,是指 Harbor 组件的配置文件,在部分新功能或者新的组件出现时,都需要在配置文件中新增其参数;在老功能、组件重构或者废弃时,也会对配置文件进行更新。

bash
1
cp -r /data/database /my_backup_dir/

reschema的工作是由 harbor-core 完成的,所以我们只需要备份即可,当新版本在启动时,第一次会 reschema,这个步骤的时间会随着 harbor 的使用量而增加,这里数据库目录为 13G,1.10.7 => 2.4.0 时间大概在20分钟左右。

harbor的配置文件升级

harbor 配置的升级是需要手动执行的,命令是包含在 offline 安装包中,被包含在 “goharbor/prepare:v2.x.0” 镜像中。用户可以在 Harbor 的离线安装包中找到它,也可以在 Docker Hub 上获取,官方给出升级指南中的命令如下

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 1.10
docker run -it --rm -v ./harbor.yml:/harbor-migration/harbor-cfg/harbor.yml goharbor/harbor-migrator:v1.10.0 --cfg up


# 2.4
# 后的yaml文件必须是旧版本的
# 这步骤是将旧的 harbor.yaml 配置文件升级到新版本
# 升级后旧版本的配置文件就没有了,如果需要需要自行备份
# docker run -it --rm -v /:/hostfs goharbor/prepare:[tag] migrate -i ${path to harbor.yml}
docker run -it --rm -v /:/hostfs goharbor/prepare:v2.4.0 migrate -i ./harbor.yml

“-v /:/hostfs” 是将主机的根目录 “/” 挂载到容器中的 “/hostfs” 目录中。因为命令是运行在容器中的,而文件是在宿主机上的,为了能在容器中访问到指定的文件,需要这样挂载,之后 prepare 会对 “/hostfs” 这个文件做特殊处理,使得在容器里也能访问主机上的指定文件。

”-i“ 是指定旧版本的 harbor 配置文件

migrate 命令有如下3个参数。

​ –input(缩写形式为“-i”):是输入文件的绝对路径,也就是需要升级的原配置文件。

​ –output(缩写形式为“-o”):是输出文件的绝对路径,也是升级后的配置文件,是可选参数,如果取默认值,则升级后的文件会被写回输入文件中。

​ –target(缩写形式为“-t”):是目标版本,也就是打算升级到的版本,也是可选参数,如果取默认值,则版本为此工具发布时所支持的最新版本。

这里我们可以使用如下命令

bash
1
docker run -v :/hostfs goharbor/prepare:v2.4.0 migrate -i home/harbor/upgrade/harbor.yml

升级成功会有如下输出

bash
1
2
3
4
5
6
migrating to version 2.0.0
migrating to version 2.1.0
migrating to version 2.2.0
migrating to version 2.3.0
migrating to version 2.4.0
Written new values to home/harbor/upgrade/harbor.yml

启动新服务

在新版本 harbor 目录中,运行 ./install.sh 脚本来安装新的 Harbor 实例,这里会导入离线安装包,生成配置文件,启动服务等操作

替换 docker-compose 文件

docker-compose 的生成是在 prepare 脚本中执行的,可以看出,是调用的 prepare 镜像

bash
1
2
3
4
5
6
7
8
# Run prepare script
docker run --rm -v $input_dir:/input \
                    -v $data_path:/data \
                    -v $harbor_prepare_path:/compose_location \
                    -v $config_dir:/config \
                    -v /:/hostfs \
                    --privileged \
                    goharbor/prepare:dev prepare $@

这种情况下,如果我们需要自定义的 docker-compose.yaml 就可以挂在到对应目录即可,模板文件可以在 photon/prepare/templates/docker_compose 处下载进行替换。

替换后,使用 sed 命令,替换 prepare 脚本中的启动命令即可。

bash
1
sed -i "/-v \/:\/hostfs/a \\\t\\t -v /root/docker_compose/docker-compose.yml.jinjia.${version}:/usr/src/app/templates/docker_compose/dockercompose.yml.jinjia \\\\" ./prepare

批量升级脚本

bash
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
#!/bin/bash

# 根据当前版本和目标版本选择对应的下载地址
declare -A harbor_versions=(
  ["v1.10.0"]="https://github.com/goharbor/harbor/releases/download/v1.10.0/harbor-offline-installer-v1.10.0.tgz"
  ["v2.4.0"]="https://github.com/goharbor/harbor/releases/download/v2.4.0/harbor-offline-installer-v2.4.0.tgz"
  ["v2.6.1"]="https://github.com/goharbor/harbor/releases/download/v2.6.1/harbor-offline-installer-v2.6.1.tgz"
  ["v2.8.0"]="https://github.com/goharbor/harbor/releases/download/v2.8.0/harbor-offline-installer-v2.8.0.tgz"
  ["v2.10.0"]="https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz"
)

#
# Set Colors
#

bold=$(tput bold)
underline=$(tput sgr 0 1)
reset=$(tput sgr0)

red=$(tput setaf 1)
green=$(tput setaf 76)
white=$(tput setaf 7)
tan=$(tput setaf 202)
blue=$(tput setaf 25)

#
# Headers and Logging
#

underline() { printf "${underline}${bold}%s${reset}\n" "$@"
}
h1() { printf "\n${underline}${bold}${blue}%s${reset}\n" "$@"
}
h2() { printf "\n${underline}${bold}${white}%s${reset}\n" "$@"
}
debug() { printf "${white}%s${reset}\n" "$@"
}
info() { printf "${white}➜ %s${reset}\n" "$@"
}
success() { printf "${green}✔ %s${reset}\n" "$@"
}
error() { printf "${red}✖ %s${reset}\n" "$@"
}
warn() { printf "${tan}➜ %s${reset}\n" "$@"
}
bold() { printf "${bold}%s${reset}\n" "$@"
}
note() { printf "\n${underline}${bold}${blue}Note:${reset} ${blue}%s${reset}\n" "$@"
}

set -e
# 设置根目录和工作目录
ROOT_DIR=$(cd $(dirname $0); pwd)
export ROOT_DIR
# 设置步骤变量

usage()
{
cat <<EOF
Usage: ${CMD} [ OPTION ]
Commands:
   Some commands take arguments or -h for usage.
     -d        download harbor rolling dependencies offline installer package
     -u        upgrade harbor to latest
     -r        rollback to old version
     -h        this message
EOF
    return 0
}

compare_versions()
{
  local current_version=$1
  local target_version=$2

  if [[ $current_version == v* ]]; then
    current_version=${current_version#v}
  fi

  if [[ $target_version == v* ]]; then
    target_version=${target_version#v}
  fi

  if [[ $current_version == "$target_version" ]]; then
    return 2
  fi

  IFS='.' read -ra current_version_parts <<< "$current_version"
  IFS='.' read -ra target_version_parts <<< "$target_version"

  for (( i=0; i<${#current_version_parts[@]}; i++ )); do
    if (( ${target_version_parts[$i]} > ${current_version_parts[$i]} )); then
      return 0
    elif (( ${target_version_parts[$i]} < ${current_version_parts[$i]} )); then
      return 1
    fi
  done

  return 2
}

set_env()
{
	# 设置工作目录
	WORK_DIR="${ROOT_DIR}/_work"
	
	# 获取当前版本和目标版本
	read -p "Please input current version [1.10.0]: " CURRENT_VERSION
	CURRENT_VERSION=${CURRENT_VERSION:-v1.10.0}

	if [[ ${CURRENT_VERSION:0:1} != "v" ]]; then
		CURRENT_VERSION="v${CURRENT_VERSION}" 
	fi

	read -p "Please input target version [2.10.0]: " TARGET_VERSION
	TARGET_VERSION=${TARGET_VERSION:-v2.10.0}

	if [[ ${TARGET_VERSION:0:1} != "v" ]]; then
		TARGET_VERSION="v${TARGET_VERSION}" 
	fi

	read -p "Please input harbor path [/root/harbor-v1.10]: " CURR_HARBOR_PATH
	CURR_HARBOR_PATH=${CURR_HARBOR_PATH:-/root/harbor-v1.10}

	read -p "Please input harbor database [/data/harbor]: " DATA_DIR
	DATA_DIR=${DATA_DIR:-/data/harbor}
	
	# 设置备份目录
	BACKUP_DIR="${ROOT_DIR}/harbor_backup"
	
	# 当前版本的备份路径
	CURRENT_VERSION_BACKUP_PATH="$BACKUP_DIR/${CURRENT_VERSION}"
	
	export WORK_DIR CURRENT_VERSION TARGET_VERSION CURR_HARBOR_PATH DATA_DIR BACKUP_DIR CURRENT_VERSION_BACKUP_PATH

    versions=""
    sorted_versions=""
    export versions sorted_versions
}

set_env_rollback()
{
	# 设置工作目录
	WORK_DIR="${ROOT_DIR}/_work"
	
	# 获取当前版本和目标版本
	read -p "Please input current version [2.10.0]: " CURRENT_VERSION
	CURRENT_VERSION=${CURRENT_VERSION:-v2.10.0}

	if [[ ${CURRENT_VERSION:0:1} != "v" ]]; then
		CURRENT_VERSION="v${CURRENT_VERSION}" 
	fi

	read -p "Please input target version [1.10.0]: " TARGET_VERSION
	TARGET_VERSION=${TARGET_VERSION:-v1.10.0}

	if [[ ${TARGET_VERSION:0:1} != "v" ]]; then
		TARGET_VERSION="v${TARGET_VERSION}" 
	fi

	read -p "Please input old harbor dirname [harbor-v1.10.0]: " CURR_HARBOR_PATH
	CURR_HARBOR_PATH=${CURR_HARBOR_PATH:-harbor-v1.10.0}

	read -p "Please input harbor database [/data/harbor]: " DATA_DIR
	DATA_DIR=${DATA_DIR:-/data/harbor}
	
	# 设置备份目录
	BACKUP_DIR="${ROOT_DIR}/harbor_rollback_backup"
	
	# 当前版本的备份路径
	CURRENT_VERSION_BACKUP_PATH="$BACKUP_DIR/${CURRENT_VERSION}"
	
	export WORK_DIR CURRENT_VERSION TARGET_VERSION CURR_HARBOR_PATH DATA_DIR BACKUP_DIR CURRENT_VERSION_BACKUP_PATH
}

initialize_workspace()
{
	# 创建工作目录(如果不存在)
	[ -d ${WORK_DIR} ] || mkdir -pv ${WORK_DIR}
	
	# 创建备份目录(如果不存在)
	[ -d ${BACKUP_DIR} ] || mkdir -pv ${BACKUP_DIR}
}

clean_annotation()
{
    find ${WORK_DIR}/${version}/ \
        -name "harbor.yml.*" \
        ! -name "harbor.yml.clean_annotation" \
        ! -name "harbor.yml.tmpl" -type f -exec \
        grep -Ev '^#|^$|^\s*(#|//)' {} + > ${WORK_DIR}/${version}/harbor.yml.clean_annotation
}

replace_configuration()
{
    cp -a ${WORK_DIR}/${version}/harbor.yml.clean_annotation ${WORK_DIR}/${version}/harbor.yml
    sed -i "s@hostname: reg.mydomain.com@hostname: your-harbor-domain.com@g" ${WORK_DIR}/${version}/harbor.yml
    sed -i "s@data_volume: /data@data_volume: ${DATA_DIR}@g" harbor.yml
}

compare_versions() 
{
    local current_version=$1
    local target_version=$2

    if [[ $current_version == v* ]]; then
        current_version=${current_version#v}
    fi

    if [[ $target_version == v* ]]; then
        target_version=${target_version#v}
    fi

    if [[ $current_version == $target_version ]]; then
        return 2
    fi

    IFS='.' read -ra current_version_parts <<< "$current_version"
    IFS='.' read -ra target_version_parts <<< "$target_version"

    for (( i=0; i<${#current_version_parts[@]}; i++ )); do
        if (( ${target_version_parts[$i]} > ${current_version_parts[$i]} )); then
            return 0
        elif (( ${target_version_parts[$i]} < ${current_version_parts[$i]} )); then
            return 1
        fi
    done

    return 2
}

check_version_number()
{
	set +e
	# 校验版本号
	compare_versions "$version" "${CURRENT_VERSION}"

	if [ $? -eq 0 ]; then
		warn "${CURRENT_VERSION} Greater than ${version}."
		continue
	fi

	compare_versions "$version" "$CURRENT_VERSION"
	if [ $? -eq 2 ]; then
		warn "${TARGET_VERSION} equal ${version}."
		continue
	fi
	set -e
}

swtich_version()
{
    CURRENT_VERSION=${version:-$CURRENT_VERSION}
    # 当前版本的备份路径
    CURRENT_VERSION_BACKUP_PATH="${BACKUP_DIR}/${CURRENT_VERSION}"
    # 当前harbor的启动路径
    CURR_HARBOR_PATH="${WORK_DIR}/${CURRENT_VERSION}"
    export CURRENT_VERSION CURRENT_VERSION_BACKUP_PATH CURR_HARBOR_PATH
}

pause() 
{
    success "Press enter to continue..."
    read -r
}

sorted_version()
{
	# 获取harbor版本列表
	versions=("${!harbor_versions[@]}")

	# 对版本列表进行排序
	sorted_versions=($(printf '%s\n' "${versions[@]}" | sort -V))
	export versions sorted_versions
}

initial_backup_dir()
{
    h2 "[Backup initialization]: Starting backup ${CURRENT_VERSION} ..."
    # 创建备份目录(如果不存在)
    [ -d ${CURRENT_VERSION_BACKUP_PATH} ] || mkdir -pv ${CURRENT_VERSION_BACKUP_PATH}
    [ -d ${CURRENT_VERSION_BACKUP_PATH}"_database" ] || mkdir -pv ${CURRENT_VERSION_BACKUP_PATH}"_database"
    [ -d ${CURRENT_VERSION_BACKUP_PATH}"_redis" ] || mkdir -pv ${CURRENT_VERSION_BACKUP_PATH}"_redis"
    note "backup dir is: ${CURRENT_VERSION_BACKUP_PATH} is checked." 
    note "backup database dir ${CURRENT_VERSION_BACKUP_PATH}_database is checked." 
}

backup_current_version()
{
    h2 "[Backup progess]: starting backup harbor ${CURRENT_VERSION} ..."
    # 备份harbor
    cp -r ${CURR_HARBOR_PATH} ${CURRENT_VERSION_BACKUP_PATH}/
    # 备份harbor数据目录的database
    cp -Rpf ${DATA_DIR}/database ${CURRENT_VERSION_BACKUP_PATH}"_database"
    cp -Rpf ${DATA_DIR}/redis ${CURRENT_VERSION_BACKUP_PATH}"_redis"
    # 备份 harbor.yml 防止升级被覆盖从而无法回滚
    cp ${CURR_HARBOR_PATH}/harbor.yml ${CURRENT_VERSION_BACKUP_PATH}/harbor.yml.$(date +%F)
    note "harbor ${CURRENT_VERSION} is backup completed, in ${CURRENT_VERSION_BACKUP_PATH}"
}

stop_old_harbor_progress()
{
    # 停止旧版容器组
    h2 "[Progress stop]: stopping ${CURRENT_VERSION} ..."
    cd ${CURR_HARBOR_PATH} && docker-compose down && cd ${ROOT_DIR} && note "harbor ${CURRENT_VERSION} is stopped ..."
}

upgrade_configfile()
{   
    h2 "[Upgrade]: upgrade ${CURRENT_VERSION} to ${version} ..."
    docker run -v /:/hostfs goharbor/prepare:${version} migrate -i ${CURRENT_VERSION_BACKUP_PATH}/harbor.yml.$(date +%F) -o ${WORK_DIR}/${version}/harbor.yml
    note "harbor config version is ${version}"
}

rollback()
{
    step=0
    h2 "[Step $step]: set up rollback env ..."; let step+=1
    set_env_rollback

    # 停止容器
    h2 "[Progress stop]: stopping ${CURRENT_VERSION} ..."
    cd ${WORK_DIR}/${CURRENT_VERSION}/ && docker-compose down && cd ${ROOT_DIR} && note "harbor ${CURRENT_VERSION} is stopped ..."

    # 备份当前版本
    initial_backup_dir
    backup_current_version

    FILE_NAME=${WORK_DIR}/${CURRENT_VERSION}

    # 检查工作目录是否存在已下载文件
    if [ ! -d ${FILE_NAME} ]; then
        error "${CURRENT_VERSION} not found"
        exit 1
    fi

    h2 "[Step $step]: starting switch harbor ${TARGET_VERSION} ..." ; let step+=1
    rm -fr ${DATA_DIR}/database && rm -fr ${DATA_DIR}/redis && \
        cp -Rpf "${ROOT_DIR}/harbor_backup/${TARGET_VERSION}_database/database" ${DATA_DIR}/database
        cp -Rpf "${ROOT_DIR}/harbor_backup/${TARGET_VERSION}_redis/redis" ${DATA_DIR}/redis
    note "Switch database to ${TARGET_VERSION} is completed."

    sleep $((RANDOM % 6 + 10))
    h2 "[Step $step]: starting harbor ${TARGET_VERSION} ..."
    cd "${ROOT_DIR}/harbor_backup/${TARGET_VERSION}/${CURR_HARBOR_PATH}" && ./install.sh
    success $"----Harbor ${CURRENT_VERSION} to ${TARGET_VERSION} has been rollback.----"

}

download()
{   
    sorted_version
	# 更新harbor
    for version in "${sorted_versions[@]}"; do
        DOWNLOAD_URL=${harbor_versions[$version]}
        FILE_NAME=$(basename $DOWNLOAD_URL)
        FOLDER_NAME=${FILE_NAME%.*}
        ARCHIVE_FILE="${ROOT_DIR}/$FILE_NAME"

        if [ -f ${ARCHIVE_FILE} ]; then
            warn "${FILE_NAME} existed, skip download.."
            continue
        fi

        note "[Downloader]: ${harbor_versions[$version]}"
        wget "${harbor_versions[$version]}"
    done
}

rotate_upgrade_harbor_versions()
{
	# 获取harbor版本列表
    sorted_version

	# 更新harbor
    for version in "${sorted_versions[@]}"; do
        # 向下传递变量
        export version
        
        h2 "[Install ${version}]: starting upgrade ..." 
        
        # 检查更新是否合法
        # 如果当前版本等于要更新的版本,则不更新
        check_version_number

        # 停止旧版本的服务
        stop_old_harbor_progress

        # 备份当前版本 harbor
        initial_backup_dir
        backup_current_version
        
        h2 "[install checking]: Starting install checking ..."
        # 检查offline安装包是否下载
        DOWNLOAD_URL=${harbor_versions[$version]}
        FILE_NAME=$(basename $DOWNLOAD_URL)
        FOLDER_NAME=${FILE_NAME%.*}
        ARCHIVE_FILE="${ROOT_DIR}/$FILE_NAME"

        # 检查工作目录是否存在已下载文件
        if [ ! -f ${ARCHIVE_FILE} ]; then
            error "Offline installer ${FILE_NAME} not found,Please download first ${DOWNLOAD_URL}"
            exit 1
        fi
        
        # 创建对应版本的工作目录(如果不存在)

        [ -d "${WORK_DIR}"/"${version}" ] || mkdir -pv "${WORK_DIR}"/"${version}"
        note "install checked"

        h2 "[Uncompress]: starting uncompress harbor offline installer ..."
        # 解压对应版本安装包
        mkdir -pv "${WORK_DIR}"/"${version}" && tar -xf "${ROOT_DIR}"/"${FILE_NAME}" -C "${WORK_DIR}"/"${version}"/ --strip-components 1
        note "harbor ${version}: ${WORK_DIR}/${version}"

        # 导入镜像
        set +e
        h2 "[Load image]: starting load harbor ${version} ..."
        cd "${WORK_DIR}/${version}" && docker image load -i harbor."${version}".tar.gz
        note "harbor image loaded"
        set -e
        
        h2 "[Replace configration]: start replace default config file ..."
        
        # 清除 harbor.yml 中的注释
        clean_annotation
        # 替换为所需的config
        replace_configuration
        note "replaced"
        
        # 更新操作
        upgrade_configfile

        h2 "[Installer]: start install harbor ${version} ..."
        # 如果使用了定制化 docker-compose 则开启这行
        # 使用准备好的模板来更换容器内部的模板
        # 这样保证了可以随意定制 docker-compose的文件
        cd "${WORK_DIR}/${version}" && sed -i "/-v \/:\/hostfs/a \\\t\\t -v /root/docker_compose/docker-compose.yml.jinjia.${version}:/usr/src/app/templates/docker_compose/dockercompose.yml.jinjia \\\\" ./prepare
        cd "${WORK_DIR}/${version}" && ./install.sh
        note "${version} installed"

        success $"----Harbor ${CURRENT_VERSION} to ${version} has been upgraded.----"
        # 切换变量,把这次更新好的版本作为下次要更新的旧版本进行传递
        swtich_version
        pause
    done

    # 完成升级
    success $"----Harbor ${TARGET_VERSION} has been installed and started successfully.----"
}

upgrade()
{
    step=0
    h2 "[Step $step]: set up env ..."; (( step+1 ))
    set_env

    # 初始化目录
    h2 "[Step $step]: initailizaion workspace ..."; (( step+1 ))
    initialize_workspace

    # 滚动版本更新harbor
    h2 "[Step $step]: Starting upgrade gradually ..."; (( step+1 ))
    rotate_upgrade_harbor_versions
}

MAIN(){

    if [ $# -eq 0 ]; then
        warn "Non option ..."
        usage
        exit 1
    fi

    while getopts "duhr" option; do
        case ${option} in
            d)
                download
                R=$?
                ;;
            u)
                upgrade
                R=$?
                ;;
            r)
                rollback
                R=$?
                ;;
            h)
                usage
                R=$?
                ;;
            \?)
                usage
                ;;
        esac
    done
    exit ${R}
}

MAIN ${@}

Reference

[1] Upgrade Harbor and Migrate Data - v1.10.0

[2] Upgrade Harbor and Migrate Data - v2.4.0

[3] Upgrade Harbor and Migrate Data - v2.6.0

[4] Upgrade Harbor and Migrate Data - v2.8.0

[5] Upgrade Harbor and Migrate Data - v2.10.0

[6] Prepare 脚本

[6] 生产系统中升级 Harbor 的完整流程

[6] Upgrade Harbor from v1.10.7 to v2.4.0 then 2.6.0