Harbor 迁移指南:从 2.6.4 升级到 2.12

目录

迁移说明

本指南介绍如何将 Harbor 从版本 2.6.4 升级到版本 2.12。鉴于版本跨度较大且升级稳定性考虑,我们采用数据迁移的方式进行升级。该方式的优点包括:

  1. 避免多版本中间升级的复杂性
  2. 复用 registry 存储数据,加快升级速度

整体迁移流程如下:

  1. 备份 PostgreSQL 数据库,并恢复到 PostgreSQL 14 实例。
  2. 停止旧的 Harbor 实例。
  3. 使用恢复后的 PostgreSQL 数据库和旧 Harbor 实例的原始 registry 存储部署新的 Harbor 实例。

备份

执行以下命令,使用 pg_dump 备份旧实例的 pg 数据库。

export INSTANCE_NAME=<harbor 实例名称> INSTANCE_NAMESPACE=<harbor 实例命名空间>

kubectl -n ${INSTANCE_NAMESPACE} exec -it ${INSTANCE_NAME}-database-0 -- bash

# 执行备份命令
pg_dump -U postgres -d registry > /tmp/harbor_database.dump

# 将备份文件复制到本地
kubectl -n ${INSTANCE_NAMESPACE} cp ${INSTANCE_NAME}-database-0:/tmp/harbor_database.dump ./harbor_database.dump
Registry 数据备份为可选项

Registry 数据通常非常庞大,备份需要额外存储空间且耗时较长,难以实现完整备份。此外,Harbor 实例升级通常不会改变 registry 存储结构,因此新实例可以直接复用旧实例的存储。

数据库迁移

从 Harbor 2.6 升级到 2.12 时,数据库版本也发生变化,由 PostgreSQL 12 升级到 PostgreSQL 14。因此,需要先将旧实例的数据库备份导入到新数据库(PostgreSQL 14)中,然后使用 Harbor 提供的数据迁移工具,将数据库结构和数据迁移到兼容 Harbor 2.12 的结构。

准备条件

准备一个运行 PostgreSQL 14 版本的新实例。将 Harbor 数据库备份恢复到该实例后,进行数据库结构迁移。

恢复数据库

将备份的数据库导入到新实例使用的数据库中。以下示例使用 psql 演示导入过程,具体导入方式请参考数据库厂商文档。

# 为新 PostgreSQL 实例创建新数据库
# 本示例中数据库名为 `registry`
dropdb -U postgres registry
createdb -U postgres registry

# 旧实例使用 harbor 用户连接数据库,
# 但该用户可能在新实例数据库中不存在,
# 需将用户改为新 PostgreSQL 实例中存在的用户。
# 本示例使用 `postgres` 用户。
sed -i 's/OWNER TO harbor/OWNER TO postgres/g' /tmp/harbor_database.dump
psql -U postgres -d registry -f /tmp/harbor_database.dump
NOTE

由于数据库版本不一致,导入过程中可能会出现关于不存在角色或函数的错误,可忽略。例如:

  • ERROR: role "admin" does not exist
  • ERROR: function metric_helpers.pg_stat_statements(boolean) does not exist

数据库迁移

Harbor 2.6 的数据已导入新实例数据库。接下来运行数据迁移任务,将数据库结构和数据迁移到兼容 Harbor 2.12 的结构。

设置新 PostgreSQL 实例信息,然后创建任务执行数据库迁移:

export POSTGRESQL_HOST=<数据库主机>
export POSTGRESQL_PORT=<数据库端口>
export POSTGRESQL_USERNAME=<数据库用户名>
export POSTGRESQL_PASSWORD=<数据库密码>
# 如果旧实例使用 SSL,设置 SSL 模式为 `require`,否则设置为 `disable`
export POSTGRESQL_SSLMODE="require"
export INSTANCE_NAMESPACE=<harbor 实例命名空间>
# 官方 migrator 镜像地址:https://hub.docker.com/r/mgle/standalone-db-migrator
# 请导入到私有仓库并设置 MIGRATOR_IMAGE 环境变量使用
export MIGRATOR_IMAGE=docker-mirrors.alauda.cn/mgle/standalone-db-migrator:v2.12.0

kubectl -n ${INSTANCE_NAMESPACE}  apply -f - << EOF
apiVersion: batch/v1
kind: Job
metadata:
  name: harbor-db-migrate
spec:
  backoffLimit: 5
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: harbor-migrate
        image: ${MIGRATOR_IMAGE}
        command: ["/harbor/migrate"]
        env:
        - name: POSTGRESQL_HOST
          value: "${POSTGRESQL_HOST}"
        - name: POSTGRESQL_PORT
          value: "${POSTGRESQL_PORT}"
        - name: POSTGRESQL_USERNAME
          value: "${POSTGRESQL_USERNAME}"
        - name: POSTGRESQL_PASSWORD
          value: "${POSTGRESQL_PASSWORD}"
        - name: POSTGRESQL_DATABASE
          value: "registry"
        - name: POSTGRESQL_SSLMODE
          value: "${POSTGRESQL_SSLMODE}"
EOF

任务完成后,可在任务日志中查看详细的迁移进度和结果:

2024-12-23T02:43:05Z [INFO] [/cmd/standalone-db-migrator/main.go:53]: Migrating the data to latest schema...
2024-12-23T02:43:05Z [INFO] [/cmd/standalone-db-migrator/main.go:54]: DB info: postgres://harbor@test-6-database:5432/registry?sslmode=require
2024-12-23T02:43:05Z [INFO] [/common/dao/base.go:67]: Registering database: type-PostgreSQL host-test-6-database port-5432 database-registry sslmode-"require"
2024-12-23T02:43:05Z [INFO] [/common/dao/base.go:72]: Register database completed
2024-12-23T02:43:05Z [INFO] [/common/dao/pgsql.go:135]: Upgrading schema for pgsql ...
2024-12-23T02:43:05Z [INFO] [/go/pkg/mod/github.com/golang-migrate/migrate/v4@v4.18.1/migrate.go:765]: 100/u 2.7.0_schema (184.508549ms)
2024-12-23T02:43:05Z [INFO] [/go/pkg/mod/github.com/golang-migrate/migrate/v4@v4.18.1/migrate.go:765]: 110/u 2.8.0_schema (275.019668ms)
2024-12-23T02:43:05Z [INFO] [/go/pkg/mod/github.com/golang-migrate/migrate/v4@v4.18.1/migrate.go:765]: 111/u 2.8.1_schema (286.508359ms)
2024-12-23T02:43:05Z [INFO] [/go/pkg/mod/github.com/golang-migrate/migrate/v4@v4.18.1/migrate.go:765]: 120/u 2.9.0_schema (357.027979ms)
2024-12-23T02:43:05Z [INFO] [/go/pkg/mod/github.com/golang-migrate/migrate/v4@v4.18.1/migrate.go:765]: 130/u 2.10.0_schema (378.349099ms)
2024-12-23T02:43:05Z [INFO] [/go/pkg/mod/github.com/golang-migrate/migrate/v4@v4.18.1/migrate.go:765]: 140/u 2.11.0_schema (399.407785ms)
2024-12-23T02:43:05Z [INFO] [/go/pkg/mod/github.com/golang-migrate/migrate/v4@v4.18.1/migrate.go:765]: 150/u 2.12.0_schema (408.831695ms)
2024-12-23T02:43:05Z [INFO] [/cmd/standalone-db-migrator/main.go:63]: Migration done.  The data schema in DB is now update to date.

停止旧 Harbor 实例

从 Operator Hub 页面卸载 harbor operator,然后执行以下命令缩容旧 Harbor 实例:

export INSTANCE_NAME=<harbor 实例名称> INSTANCE_NAMESPACE=<harbor 实例命名空间>

kubectl -n ${INSTANCE_NAMESPACE} scale deployment -l release=${INSTANCE_NAME} --replicas=0
kubectl -n ${INSTANCE_NAMESPACE} scale statefulset -l release=${INSTANCE_NAME} --replicas=0
kubectl -n ${INSTANCE_NAMESPACE} delete service -l release=${INSTANCE_NAME}
kubectl -n ${INSTANCE_NAMESPACE} delete ingress -l release=${INSTANCE_NAME}

部署新 Harbor 实例

TIP

新实例需要挂载原实例的存储,因此需与原实例处于同一命名空间

请根据部署文档部署新实例,但需注意以下几点:

  1. 新实例需连接迁移后的 PG 数据库(PostgreSQL 14)
  2. 不复用旧 Harbor 实例的 Redis,需新建 Redis
  3. registry 存储需使用旧实例的存储
  4. 访问方式需与旧实例保持一致,避免迁移完成后影响业务使用

以下章节介绍旧实例与新实例的配置迁移。

获取原实例配置

需获取原实例配置并转换为新实例配置,命令如下:

export INSTANCE_NAME=<harbor 实例名称> INSTANCE_NAMESPACE=<harbor 实例命名空间>

helm -n ${INSTANCE_NAMESPACE} get values ${INSTANCE_NAME}

转换 Registry 存储配置

如果原实例使用 Host Path 存储,配置如下:

# 原实例配置
persistence:
  hostPath:
    registry:
      host:
        nodeName: <节点名称>
        path: <registry 存储路径>

迁移为新实例配置:

# 新实例配置
helmValues:
  persistence:
    enabled: true
    hostPath:
      registry:
        path: <registry 存储路径>

  registry:
    nodeSelector:
      kubernetes.io/hostname: <节点名称>

如果原实例使用存储类,PVC 名称固定:

  • registry PVC 名称:<旧实例名称>-harbor-registry

新实例直接使用旧 PVC。

# 新实例配置
helmValues:
  persistence:
    enabled: true
    persistentVolumeClaim:
      registry:
        existingClaim: <旧实例名称>-harbor-registry

如果原实例使用 PVC,配置如下:

# 原实例配置
persistence:
  persistentVolumeClaim:
    registry:
      existingClaim: <registry pvc 名称>

新实例配置:

# 新实例配置
helmValues:
  persistence:
    enabled: true
    persistentVolumeClaim:
      registry:
        existingClaim: <registry pvc 名称>

转换访问方式配置

如果原实例使用 NodePort,设置如下配置:

# 新实例配置
helmValues:
  expose:
    type: nodePort
    nodePort:
      name: harbor
      ports:
        http:
          port: 80
          nodePort: <node port 端口号>

  externalURL: http://<node port IP>:<node port 端口号>

如果原实例使用域名,设置如下配置:

# 新实例 http 配置
helmValues:
  expose:
    type: ingress
    tls:
      enabled: false
    ingress:
      hosts:
        core: <域名>

  externalURL: http://<域名>
# 新实例 https 配置
helmValues:
  expose:
    type: ingress
    tls:
      enabled: true
      certSource: "secret"
      secret:
        secretName: <tls 证书 secret>
    ingress:
      hosts:
        core: <域名>

  externalURL: https://<域名>

验证

  1. 检查所有 Pod 状态:

    export INSTANCE_NAME=<harbor 实例名称> INSTANCE_NAMESPACE=<harbor 实例命名空间>
    kubectl get pods -n ${INSTANCE_NAMESPACE} -l release=${INSTANCE_NAME}
  2. 验证 Harbor 服务可访问:

    • 访问 Harbor Web UI,确认已有项目和镜像可见
    • 测试 Docker 登录
  3. 测试镜像推送和拉取

  4. 确认迁移成功后,可手动删除旧 Harbor 实例。