跳转至

GitLab 迁移到 server 命名空间 —— 方案与风险

交付物目录:ns_migration/ 状态:待确认,尚未执行 关联工程:gitlab-deploy-v2/(chart 10.3.2 / GitLab 19.3.2)


1. 背景与现状

本次要求把含 "deploy" 的目录对应的命名空间统一为 server。Traefik(已完成)与 LDAP(仅文件)都属轻量变更;GitLab 是其中唯一带持久化数据的多命名空间应用,因此单独成文。

集群现状(实测):

命名空间 承载内容 数据卷
gitlab GitLab 主体(webservice / sidekiq / gitaly / registry / kas / toolbox / shell)+ Envoy Gateway(GitLab 19.x 走 Gateway API) pv-gitaly-ssd(local PV,/mnt/ssd/k8s/gitaly)
gitlab-pg CloudNativePG 的 Cluster gitlab-pg(1 实例,healthy) pv-postgres-ssd(local PV,/mnt/ssd/k8s/postgres)
gitlab-redis Redis StatefulSet pv-redis-ssd(local PV,/mnt/ssd/k8s/redis)
gitlab-minio MinIO(对象存储:artifacts / LFS / uploads / packages / registry) minio-data(nfs-csi 动态卷,50G,回收策略 Delete)
  • 三个 local PV 的回收策略均为 Retain,数据落在 k8s-node-01 的 /mnt/ssd/k8s/ 下 → 删 PVC 不会删数据。
  • MinIO 的卷由 nfs-csi 动态供给,回收策略是 Delete → 删 PVC 即删数据,这是本次最大的单点风险。
  • gitlab 命名空间内有 20 个 Secret(gitlab-rails-secret、gitlab-gitaly-secret、gitlab-gitlab-initial-root-password、gitlab-object-storage、gitlab-pg-app、gitlab-redis 等),承载数据库口令、组件密钥、root 初始口令,必须逐一搬迁且内容一致。

2. 目标

GitLab 全栈(含 PG / Redis / MinIO)运行在 server 命名空间,数据零丢失,登录与 CI 功能验证通过。

3. 为什么这是"重装级"变更

约束 后果
Helm release 的命名空间安装即固定,无法迁移 必须 helm uninstall 后在新 ns 重装
local PV 的 claimRef 绑定在旧 ns 的 PVC 上 必须停机 → 释放 claimRef → 在新 ns 重绑,否则新 PVC 无法 Bound
MinIO 卷是 Delete 策略的动态卷 换 ns 等于换卷,数据必须显式复制,否则全部对象丢失
CNPG 的 Cluster CR 是命名空间级资源 重建后需以现有数据引导(复用 PV 或走 recovery),否则 PG 起不来
GitLab chart 重装会重跑 migrations Secret 必须完整迁移,任何密钥不一致都会导致启动失败或数据不可读
GitLab 19.x 依赖 Gateway API + Envoy Gateway envoy-gateway、Gateway、TCPRoute 等资源需一并迁移

4. 影响范围

  • 停机:GitLab 全栈不可用,预计 1–3 小时(含镜像、migrations、验证);期间 gitlab.rainchen.com 不可访问、CI 不可用、Git push 不可用、registry 不可用。
  • 主机:k8s-node-01(local PV 所在地,数据不动)、NFS 服务器 192.168.31.249(MinIO 数据复制)。
  • 集群:新增 server ns 内的 GitLab 全套对象;旧 4 个 ns 在验证通过后删除(删除前必须确认数据已迁移)。
  • 不影响:Traefik(已迁至 server,与 GitLab 的 Gateway API 路径互不干扰)、监控栈(明确排除在本次范围外)。

5. 建议步骤(8 步)

下列为方案骨架,实际执行前会逐条核对并补充预期输出;涉及数据的步骤必须先备份。

# ① 全量备份(不可跳过)
helm get values gitlab -n gitlab -o yaml > ns_migration/backup/gitlab-values-before.yaml
kubectl -n gitlab get secret -o yaml                > ns_migration/backup/gitlab-secrets-before.yaml
kubectl -n gitlab-pg get cluster gitlab-pg -o yaml  > ns_migration/backup/cnpg-cluster-before.yaml
kubectl get pv,pvc -o yaml                          > ns_migration/backup/pv-pvc-before.yaml
# GitLab 侧逻辑备份(应用级):toolbox 里跑 gitlab-backup / pg_dump,产出落到 NFS 或宿主机

# ② 停止写入(先摘流量,再停组件)
#    - 暂停 GitLab 写入口(scale webservice/sidekiq/registry/kas 到 0)
#    - CNPG:停 Cluster 实例;Redis:scale 0
#    - MinIO:scale 0

# ③ 备份 MinIO 数据(Delete 策略,必须先复制)
#    在 NFS 服务器上把旧卷目录整体复制一份(保留原目录不动,便于回滚)

# ④ 释放 local PV 的 claimRef
kubectl -n gitlab      delete pvc repo-data-gitlab-gitaly-0
kubectl -n gitlab-pg   delete pvc gitlab-pg-1
kubectl -n gitlab-redis delete pvc redis-data
# 逐个清空 claimRef,使 PV 回到 Available(数据仍在 /mnt/ssd/k8s/ 下)
kubectl patch pv pv-gitaly-ssd   -p '{"spec":{"claimRef":null}}'
kubectl patch pv pv-postgres-ssd -p '{"spec":{"claimRef":null}}'
kubectl patch pv pv-redis-ssd    -p '{"spec":{"claimRef":null}}'

# ⑤ 在 server 命名空间重建命名空间级资源
#    - 20 个 Secret(从 ① 的备份还原,改名空间)
#    - 三个 PVC(同名,spec.volumeName 指向对应 PV,storageClassName: local-ssd)
#    - MinIO 的新 PVC 及其数据(从 ③ 的副本恢复)

# ⑥ 改 values 并重装
#    values-gitlab.yaml 中 4 处跨命名空间引用须同步改为 server:
#      gitlab-pg-rw.gitlab-pg.svc.cluster.local -> gitlab-pg-rw.server.svc.cluster.local
#      redis.gitlab-redis.svc.cluster.local     -> redis.server.svc.cluster.local
helm upgrade --install gitlab gitlab-deploy-v2/gitlab-10.3.2.tgz \
  -n server -f gitlab-deploy-v2/values-gitlab.yaml \
  --wait --timeout 30m

# ⑦ 验证(见第 6 节)

# ⑧ 清理旧命名空间(高危:确认数据已迁移且备份可用后再删)
kubectl delete namespace gitlab gitlab-pg gitlab-redis gitlab-minio

6. 验证

kubectl -n server get pods                        # gitlab-* 全部 Running 且 Ready
kubectl -n server get cluster gitlab-pg           # Cluster in healthy state
kubectl -n server get job | grep migrations       # migrations Job 成功
curl -s -o /dev/null -w '%{http_code}\n' http://<GitLab 入口>/users/sign_in   # 200
# 业务验证:登录、浏览既有仓库、git clone、CI 跑一次、push/pull 一个镜像

7. 回滚

  • 数据侧:PV 为 Retain,节点本地数据未被触碰;把 claimRef 指回旧命名空间的 PVC 名即可复原。
  • MinIO 侧:旧 NFS 卷目录保留未动,回滚时把旧 PVC 的 volumeHandle/目录还原即可。
  • 应用侧:重新在旧命名空间 helm upgrade --install 并挂回原 PVC。
  • 触发条件:migrations 失败、PG 引导失败、MinIO 数据不一致、验证项任一不过 → 立即回滚。

8. 风险说明

风险 等级 缓解
MinIO 对象数据丢失(Delete 策略) 高 步骤 ③ 先复制数据;旧目录保留不删
Gitaly 仓库数据受损 高 local PV Retain + 停机操作;操作前确认 /mnt/ssd/k8s/gitaly 可读
CNPG 重建后无法以现有数据引导 中 备份 Cluster CR;必要时改走 bootstrap.recovery 指向原备份
停机时间超预期(migrations 慢) 中 安排在无 CI 任务的时间窗;预留 3 小时
Secret 迁移不完整导致组件起不来 中 用 ① 的 Secret 全量备份 + diff 校验
回滚窗口内出现新提交无法回灌 低 停机期间禁止写入,无新数据产生

9. 我的判断(供你决策)

收益有限、风险显著。理由:

  1. GitLab 官方 chart 本身按多命名空间设计(PG / Redis / MinIO 独立),它们是同一套应用的不同组件,合并到 server 不会带来运维简化,反而让 server 这个"业务命名空间"混入数据库与对象存储。
  2. server 目前的定位是业务与入口(Traefik、LDAP 都在此),把 GitLab 的 PG/MinIO 塞进来会让后续的资源配额、NetworkPolicy、备份策略更难做。
  3. 真正需要"路由统一在同一命名空间"的诉求(IngressRoute 与后端同 ns 便于书写),GitLab 已经不走 Traefik(它用 Gateway API + Envoy Gateway),所以这个诉求对 GitLab 不成立。

因此建议二选一:

  • 方案 A(推荐):GitLab 保持现状不动,本次只把 gitlab-deploy-v2/ 里的文档与 values 注释补一句说明("GitLab 因数据卷与 chart 架构原因保留独立命名空间"),集群零变更。
  • 方案 B(按你原要求):执行上述 8 步完整迁移,需要你指定一个无 CI 任务的时间窗,我会先做全量备份再动手。

请告诉我选 A 还是 B。若选 B,我会在动手前把每一步的命令、预期输出、失败判据补全并逐条与你核对。


来源:/home/rain/Documents/k8s_ins/ns_migration/GitLab迁移到server-方案与风险.md | 最后更新:2026-09-18 00:34(由 build/sync.py 同步,请勿在站点侧修改)