本文只保留通用执行逻辑。地址、节点、域名、容量和 Secret 均为占位符,执行时必须按官方版本矩阵和自己的恢复演练结果重新确认。
系列导航:Kubernetes 重建迁移教程系列。本篇用于正式迁移窗口中的逐项执行与验收。
上一篇文章解释了 Nexus2 → Nexus3 → PostgreSQL 的整体设计。这一篇把迁移收敛成一份执行清单,重点回答“每一步什么时候能继续”。
固定设计
迁移前冻结以下决策:
- Nexus2 已升级到官方支持的最终版本。
- Nexus3 使用经过验证的中转版本接收 Upgrade Wizard 数据。
- Nexus3 在 H2 模式升级到最终目标版本。
- Database Migrator 与目标版本严格匹配。
- Nexus 和迁移器 Java 版本符合目标版本要求。
- Blob Store 使用独立持久卷,回收策略为
Retain。 - PostgreSQL 使用独立数据库、角色和 schema。
/nexus上下文路径保持不变。- 旧域名或 VIP 只在最终验证后切换。
不可跳过的顺序
Nexus2 最终版与完整备份
→ Nexus3 中转版 H2
→ Upgrade Wizard + Finalize
→ Nexus3 目标版 H2
→ H2 备份与 Blob Store 恢复点
→ 停止 Nexus
→ Database Migrator
→ PostgreSQL VACUUM
→ Nexus3 目标版 PostgreSQL
→ Browse/Search 完成
→ 真实构建与上传
→ VIP/域名切换
不要在中转版上提前迁移 PostgreSQL,也不要让 Nexus 在数据库迁移期间运行。
一、创建 Kubernetes 基础资源
先创建:
- StorageClass、PV、PVC。
- 非敏感 ConfigMap。
- Nexus Service。
- PostgreSQL 数据库和 schema 初始化 Job。
- 数据库 Secret。
Secret 使用命令创建,不写 YAML 明文:
kubectl -n repository create secret generic nexus-db \
--from-literal=username=nexus \
--from-literal=password="$(openssl rand -base64 36)"
存储验收:
- PVC Bound。
- PV 为
Retain。 - 目标节点目录容量充足。
- Nexus 容器 UID/GID 有写权限。
- Blob Store 与数据库临时文件空间需分别评估。
二、以 H2 启动中转版 Nexus3
kubectl -n repository apply -f nexus3-migration.yaml
kubectl -n repository rollout status statefulset/nexus --timeout=15m
curl -fsS \
http://<migration-address>:8081/nexus/service/rest/v1/status
启动探针建议使用状态接口,并为首次升级预留足够时间:
startupProbe:
httpGet:
path: /nexus/service/rest/v1/status
port: http
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 60
如果探针提示 connection refused,先检查 nexus.log,不要无限增加等待时间。
三、执行 Nexus2 Upgrade Wizard
- 备份 Nexus2 程序和工作目录。
- 在 Nexus2 上创建 Upgrade Agent。
- 在 Nexus3 上创建 Upgrade Capability。
- 迁移 repository content。
- 迁移 server configuration。
- 等待同步队列归零。
- 冻结上传并停止 Nexus2。
- 执行 Finalize 和 Done。
Finalize 前必须确认:
- Hosted 最新制品存在。
- Proxy 能重新拉取。
- Group 成员和顺序正确。
- 用户、角色和匿名访问正确。
- 现代 URL 与需要兼容的旧 URL 均可用。
- 至少一次真实 Maven 构建通过。
四、升级目标版本,继续使用 H2
先创建 H2 官方备份并记录 SHA256,同时备份 Blob Store:
sha256sum /backup/nexus-h2-* /backup/nexus-blob-* > /backup/SHA256SUMS
再升级 StatefulSet 镜像。启动后等待内部 schema 和 upgrade 任务全部完成,再重新生成 H2 恢复点。
禁止在内部任务运行时重启 Pod。
五、准备 PostgreSQL
CREATE ROLE nexus LOGIN PASSWORD '<random-password>';
CREATE DATABASE nexus OWNER nexus;
\connect nexus
CREATE SCHEMA nexus AUTHORIZATION nexus;
GRANT USAGE, CREATE ON SCHEMA nexus TO nexus;
ALTER ROLE nexus SET search_path TO nexus;
验证应用角色可以:
- 连接数据库。
- 在目标 schema 创建和删除临时表。
- 使用预期的
search_path。
如果只做数据库级授权、不授予 schema 的 USAGE 和 CREATE,迁移器仍会失败。
六、运行 Database Migrator
下载与 Nexus 目标版本匹配的迁移器并校验:
curl -fLO https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-<version>.jar
curl -fLO https://download.sonatype.com/nexus/nxrm3-migrator/nexus-db-migrator-<version>.jar.sha256
test "$(sha256sum nexus-db-migrator-<version>.jar | awk '{print $1}')" = \
"$(cat nexus-db-migrator-<version>.jar.sha256)"
完全停止 Nexus:
kubectl -n repository scale statefulset/nexus --replicas=0
kubectl -n repository wait --for=delete pod/nexus-0 --timeout=180s
迁移器从受控 Secret 中读取连接参数。若密码包含 URL 保留字符,先做 URL 编码,同时不要把 JDBC URL 打到日志。
继续条件:
- Job 状态为
Complete。 - 迁移汇总中 skipped 为 0。
- 没有 failed、constraint、schema permission 或认证错误。
- PostgreSQL 表、组件、资产和 Blob 引用数量与汇总一致。
迁移失败时,不要直接对已有目标 schema 重跑迁移器。先定位原因,再恢复或重建确认干净的空 schema。
七、整理 PostgreSQL 并启动最终版本
Nexus 仍停止时执行:
VACUUM (FULL, ANALYZE);
然后用最终 StatefulSet 连接 PostgreSQL:
env:
- name: NEXUS_DATASTORE_NEXUS_JDBCURL
value: jdbc:postgresql://postgresql.repository.svc.cluster.local:5432/nexus?currentSchema=nexus
- name: NEXUS_DATASTORE_NEXUS_USERNAME
value: nexus
- name: NEXUS_DATASTORE_NEXUS_PASSWORD
valueFrom:
secretKeyRef:
name: nexus-db
key: password
启动后等待:
Rebuild repository browseRebuild repository search
这些一次性任务完成前,不要重启实例或切流量。
八、验证矩阵
运行时
- Pod Ready,Restart 次数不增长。
- 状态接口正常。
- 日志无数据库、Blob、索引错误。
- Nexus 和 Java 版本符合计划。
仓库
- Hosted releases 可下载。
- Hosted snapshots 可下载。
- Third-party 可下载。
- Proxy 命中和未命中都成功。
- Group 按成员顺序解析。
- Search 能找到已知组件。
权限
- 用户、角色和 Realm 正常。
- 匿名下载符合预期。
- Hosted 上传权限正确。
客户端
- Maven 使用真实 settings 完整构建。
- Jenkins 可下载依赖。
- 使用临时版本上传并清理。
- 需要保留的旧
/content/URL 已验证或重写。
九、入口切换
切换前:
- 旧 Nexus2 已停止。
- 旧节点不再持有 VIP。
- 新 Nexus3 已通过内部地址验证。
- 备份和回滚命令仍可用。
切换后立即验证状态、下载、上传和真实构建。任何时刻都不能让两台机器同时持有同一 VIP。
回滚:
- 冻结新 Nexus3 上传。
- 从新节点移除 VIP。
- 确认 ARP 和路由已经收敛。
- 启动旧 Nexus2。
- 恢复旧入口。
十、凭据与备份收尾
- 删除只在迁移期使用的 Secret。
- 如果密码可能进入日志,轮换 PostgreSQL 角色和 Kubernetes Secret。
- 两边密码必须同时更新。
- 保留 Nexus2、两个 H2 恢复点、PostgreSQL 备份和 Blob Store 备份。
- 经过稳定观察和恢复演练后,才能释放旧服务器。
社区版组件数维护
对 Proxy 和 Hosted 分别设置策略:
- Proxy:删除长期未使用的缓存组件。
- Hosted:按发布和合规要求保留。
- 清理前执行 PostgreSQL 备份。
- 先软删除,观察后再对 Blob Store 执行 Compact。
Usage Center 可能延迟刷新,历史峰值也不会立即下降。不要因为页面短时间内仍显示旧数量而反复执行清理。
完成定义
迁移器无跳过
+ PostgreSQL 数据与 Blob 引用一致
+ Browse/Search 完成
+ 仓库和权限正确
+ Maven/Jenkins 下载上传通过
+ 入口切换成功
+ 回滚和备份仍可用
一份好的 Runbook 不追求“命令越多越专业”,而是让每个不可逆步骤都有清晰的输入、继续条件和回滚边界。
DISCUSSION
讨论与反馈