Harbor 迁移指南:从 2.6.4 到 2.12
目录
迁移说明
本指南描述了如何将 Harbor 从版本 2.6.4 升级到版本 2.12。考虑到版本差距较大和升级的稳定性,我们采用数据迁移的方法进行升级。此方法的优点包括:
- 避免了多个中间版本升级的复杂性
- 在最小修改的情况下重用现有的数据库、Redis 和存储
I. 数据备份
数据库备份
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 数据通常较大,不建议从 Pod 中复制。您需要根据对应的存储类型定位存储目录。
您可以通过以下方式从 harbor 实例的 yaml 中获取 Registry 配置:
export INSTANCE_NAME=<harbor 实例名称> INSTANCE_NAMESPACE=<harbor 实例命名空间>
helm -n ${INSTANCE_NAMESPACE} get values ${INSTANCE_NAME}
主机路径存储
如果原始实例使用主机路径存储,配置如下:
persistence:
hostPath:
registry:
host:
nodeName: <节点名称>
path: <registry 存储路径>
进入节点上的目录以备份数据。
PVC 或存储类
如果原始实例使用存储类,则 PVC 的名称固定为:<实例名称>-harbor-registry
。
如果原始实例使用 PVC 存储,配置如下:
helmValues:
persistence:
persistentVolumeClaim:
registry:
existingClaim: <registry pvc 名称>
您可以使用以下命令查看 PVC 的具体信息:
export INSTANCE_NAMESPACE=<harbor 实例命名空间>
kubectl -n ${INSTANCE_NAMESPACE} get pvc <registry pvc 名称> -o yaml
您需要参考 PVC 存储类的文档来寻找数据目录。
II. 停止旧的 Harbor 服务
首先,从 Operator Hub 页面卸载 harbor 操作员,然后按以下命令缩减旧的 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
注意:请勿停止数据库组件,因为我们需要对其进行迁移
III. 数据库迁移
首先,通过以下命令获取实例的 yaml 配置:
export INSTANCE_NAME=<harbor 实例名称> INSTANCE_NAMESPACE=<harbor 实例命名空间>
helm -n ${INSTANCE_NAMESPACE} get values ${INSTANCE_NAME}
数据库配置如下:
database:
type: external
external:
existingSecret: <数据库密码秘密>
host: <数据库主机>
port: <数据库端口>
username: <数据库用户名>
然后创建一个任务来执行数据库迁移:
export POSTGRESQL_HOST=<数据库主机> POSTGRESQL_PORT=<数据库端口> POSTGRESQL_USERNAME=<数据库用户名> POSTGRESQL_PASSWORD=<数据库密码> POSTGRESQL_SSLMODE="require"
export INSTANCE_NAMESPACE=<harbor 实例命名空间>
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: docker-mirrors.alauda.cn/mgle/standalone-db-migrator:v2.12.0
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]: 正在将数据迁移到最新的模式...
2024-12-23T02:43:05Z [INFO] [/cmd/standalone-db-migrator/main.go:54]: 数据库信息: postgres://harbor@test-6-database:5432/registry?sslmode=require
2024-12-23T02:43:05Z [INFO] [/common/dao/base.go:67]: 注册数据库: type-PostgreSQL host-test-6-database port-5432 database-registry sslmode-"require"
2024-12-23T02:43:05Z [INFO] [/common/dao/base.go:72]: 注册数据库完成
2024-12-23T02:43:05Z [INFO] [/common/dao/pgsql.go:135]: 正在为 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]: 迁移完成。数据库中的数据模式现在是最新的。
IV. 部署新的 Harbor 服务
新实例需要挂载原始实例的存储,因此需要在与原始实例相同的命名空间中。
获取原始实例配置
我们需要从原始实例获取配置并将其转换为新实例的配置,如下所示:
export INSTANCE_NAME=<harbor 实例名称> INSTANCE_NAMESPACE=<harbor 实例命名空间>
helm -n ${INSTANCE_NAMESPACE} get values ${INSTANCE_NAME}
转换数据库配置
# 原始实例配置
database:
type: external
external:
existingSecret: <数据库密码秘密>
host: <数据库主机>
port: <数据库端口>
sslmode: <是否启用 SSL>
username: <数据库用户名>
# 新实例配置
helmValues:
database:
type: external
external:
existingSecret: <数据库密码秘密>
host: <数据库主机>
port: <数据库端口>
sslmode: <是否启用 SSL>
username: <数据库用户名>
注意:数据库密码秘密键在旧实例和新实例之间是不同的。新实例需要使用 POSTGRES_PASSWORD 字段
data:
POSTGRES_PASSWORD: <密码 base64>
转换 Redis 配置
# 原始实例配置
redis:
type: external
external:
addr: rfr-harbor-test-5-redis:6379
existingSecret: test-5-redis-password
# 新实例配置
helmValues:
redis:
type: external
external:
addr: <redis 主机>:<redis 端口>
existingSecret: <redis 密码秘密>
注意:Redis 密码秘密键在旧实例和新实例之间是不同的。新实例需要使用 REDIS_PASSWORD 字段
data:
REDIS_PASSWORD: <密码 base64>
转换主机路径存储配置
如果原始实例使用主机路径存储,配置如下:
# 原始实例配置
persistence:
hostPath:
jobservice:
host:
nodeName: <节点名称>
path: <jobservice 存储路径>
registry:
host:
nodeName: <节点名称>
path: <registry 存储路径>
trivy:
host:
nodeName: <节点名称>
path: <trivy 存储路径>
# 新实例配置
helmValues:
persistence:
enabled: true
hostPath:
registry:
path: <registry 存储路径>
jobservice:
path: <jobservice 存储路径>
trivy:
path: <trivy 存储路径>
registry:
nodeSelector:
kubernetes.io/hostname: <节点名称>
jobservice:
nodeSelector:
kubernetes.io/hostname: <节点名称>
trivy:
nodeSelector:
kubernetes.io/hostname: <节点名称>
转换存储类存储配置
如果原始实例使用存储类,则 PVC 名称固定为:
- jobservice:
<实例名称>-harbor-jobservice
- registry:
<实例名称>-harbor-registry
- trivy:
data-<实例名称>-harbor-trivy-0
# 新实例配置
helmValues:
persistence:
enabled: true
persistentVolumeClaim:
registry:
existingClaim: <实例名称>-harbor-jobservice
jobservice:
jobLog:
existingClaim: <实例名称>-harbor-registry
trivy:
existingClaim: data-<实例名称>-harbor-trivy-0
如果原始实例使用 PVC,配置如下:
# 原始实例配置
persistence:
persistentVolumeClaim:
registry:
existingClaim: <registry pvc 名称>
jobservice:
existingClaim: <jobservice pvc 名称>
trivy:
existingClaim: <trivy pvc 名称>
# 新实例配置
helmValues:
persistence:
enabled: true
persistentVolumeClaim:
registry:
existingClaim: <registry pvc 名称>
jobservice:
jobLog:
existingClaim: <jobservice pvc 名称>
trivy:
existingClaim: <trivy pvc 名称>
转换 NodePort 配置
如果原始实例使用 NodePort,配置如下:
# 新实例配置
helmValues:
expose:
type: nodePort
nodePort:
name: harbor
ports:
http:
port: 80
nodePort: <节点端口号>
externalURL: http://<节点端口 ip>:<节点端口号>
转换 Ingress 配置
如果原始实例使用域名,配置如下:
# 新实例 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 证书秘密>
ingress:
hosts:
core: <域名>
externalURL: https://<域名>
V. 验证
- 检查所有 Pod 状态:
export INSTANCE_NAME=<harbor 实例名称> INSTANCE_NAMESPACE=<harbor 实例命名空间>
kubectl get pods -n ${INSTANCE_NAMESPACE} -l release=${INSTANCE_NAME}
-
验证 Harbor 服务是否可访问:
- 访问 Harbor Web UI,验证现有项目和镜像是否可见。
- 测试 Docker 登录。
-
测试推送和拉取镜像。
-
在确认迁移正常后,您可以手动删除旧的 Harbor 实例。