前言:在企业运维中,GitLab 版本升级与服务器迁移是高频且关键的操作。本文基于真实生产场景,完整记录了从 CentOS7 上的 GitLab通过 5 步合规升级(含额外安全过渡节点),再将全量数据迁移至 Rocky9.5 新服务器的全流程。
本次操作严格遵循 GitLab 官方升级规范,重点补充了「后台迁移检查」「维护模式双应急退出方案」「UI 界面进度核验」等生产环境极易踩坑的隐形细节,并针对跨操作系统(CentOS7 → Rocky9.5)带来的潜在风险(如 PostgreSQL 索引损坏)进行了重点排错。所有步骤通用化,无任何业务敏感信息,可直接用于企业生产环境落地。
一、环境与版本路径说明
1.1 环境定义
- 旧环境:CentOS 7,GitLab
版本号秘密,数据存储于系统盘/var/opt/gitlab - 新环境:Rocky Linux 9.5,目标版本
秘密,规划独立存储以提升性能与可扩展性
1.2 官方升级路径查询(必做前置)
在开始任何升级前,必须通过 GitLab 官方工具查询唯一合规的升级路径,避免因版本跳跃导致数据损坏。
官方查询链接
GitLab Upgrade Path Tool
查询步骤
- 打开上述链接。
- 在表单中填写:
Current version:秘密Target version:秘密Linux distribution:根据你的系统选择(如 AlmaLinux 或 CentOS/Rocky)GitLab edition:CE(社区版)或EE(企业版)
- 点击查询,获取官方推荐路径。
升级路径可视化(Mermaid 流程图)
官方推荐升级路径(秘密 → 秘密)
具体版本路径省略实际执行升级路径(含额外安全过渡)
具体路径版本省略,只讲通用方法为何额外增加版本号秘密节点?
官方路径是推荐的稳定中继,但在生产实践中,从秘密.x直接跨到秘密.x存在一定风险:
- 兼容性风险:.x 系列引入了大量架构变更,直接跳至 .x 可能导致配置不兼容。
- 数据库风险:跨大版本升级可能触发 PostgreSQL 索引损坏,尤其在后续还要跨 OS 迁移的场景下,风险被放大。
- 保守实践:我们选择
秘密作为额外过渡节点,它是 .x 系列的首个稳定分支,能有效平滑过渡,降低升级风险,是更稳妥的生产级选择。
二、旧环境(CentOS7)5步完整升级
2.1 升级前置准备(解决CentOS7 GPG签名过期问题)
CentOS 7 系统中 GitLab 官方仓库的 GPG 签名密钥在 2024 年完成更新,未更新密钥会导致yum install时报签名验证失败,需提前执行以下命令:
# 导入GitLab最新GPG签名密钥,预防安装失败rpm--importhttps://packages.gitlab.com/gitlab/gitlab-ce/gpgkeyrpm--importhttps://packages.gitlab.com/gitlab/gitlab-ce/gpgkey/gitlab-gitlab-ce-3D645A26AB9FBD22.pub.gpg2.2 升级通用前置操作(每步升级前必执行)
# 1. 停止核心业务服务,避免写入冲突gitlab-ctl stop sidekiq puma geo-logcursor mailroom# 2. 开启维护模式(只读),禁止业务写入(替代原只读命令,更通用)gitlab-ctl deploy-page up# 3. 检查数据库迁移状态(必须全部显示 up)gitlab-rake db:migrate:status# 4. 清理系统缓存gitlab-rake cache:clear# 5. 全量备份(每跨一个版本必做,升级生命线)gitlab-backup createSTRATEGY=copycp-r/etc/gitlab /etc/gitlab_backup_$(date+%Y%m%d_%H%M)🔥 核心补充:维护模式挂载失败的双应急方案
若执行gitlab-ctl deploy-page up后提示「挂载失败/服务无响应」,需根据场景选择以下方案:
方案1:强制退出维护模式(快速恢复业务)
适用于无需等待后台迁移,优先恢复业务访问的场景:
# 应急退出维护模式(强制清理挂载锁)gitlab-ctl deploy-page down# 若仍无效,直接删除维护模式配置文件rm-rf/var/opt/gitlab/nginx/www/deploy.html gitlab-ctl restart nginx方案2:启动sidekiq完成后台迁移(保障数据一致性)
适用于维护模式挂不上,但必须完成后台迁移再升级的场景(匹配生产实战操作):
# 步骤1:启动sidekiq服务,继续后台迁移gitlab-ctl start sidekiq gitlab-ctl status sidekiq# 确认显示 run 状态# 步骤2:等待后台迁移全部完成(生产环境实际查询命令)gitlab-psql-c"SELECT id, job_class_name, status FROM batched_background_migrations WHERE status < 3;"# 要求:输出为空(即无未完成/运行中的迁移任务)# 补充UI核验:后台 → 管理中心 → 监控 → 后台迁移 → 「队列中=0,失败=0」# 步骤3:后台迁移完成后,停止sidekiq(恢复只读状态)gitlab-ctl stop sidekiq gitlab-ctl status sidekiq# 确认显示 down 状态2.3 第1步:版本号秘密 → (.x 最终稳定版)
yuminstall-ygitlab-ce-具体版本号-ce.0.el7.x86_64 gitlab-ctl reconfigure gitlab-ctl restart# ========== 关键检查:后台迁移进度(必须完成才能继续) ==========# 生产环境实际查询命令(优先使用)gitlab-psql-c"SELECT id, job_class_name, status FROM batched_background_migrations WHERE status < 3;"# 补充CLI命令(备用)gitlab-rake gitlab:background_migrations:status# UI 核验:管理中心 → 监控 → 后台迁移 → 无未完成任务# 基础状态校验gitlab-rake db:migrate:status gitlab-rake gitlab:checkSANITIZE=true2.4 第2步:版本号秘密 → (额外安全过渡,核心)
yuminstall-ygitlab-ce-具体版本号-ce.0.el7.x86_64 gitlab-ctl reconfigure gitlab-ctl restart# ========== 后台迁移进度检查(必做) ==========gitlab-psql-c"SELECT id, job_class_name, status FROM batched_background_migrations WHERE status < 3;"# 要求:输出为空(无未完成迁移)# UI 核验:管理中心 → 监控 → 后台迁移 → 所有任务「Completed」gitlab-rake db:migrate:status gitlab-rake gitlab:checkSANITIZE=true2.5 第3步:版本号秘密 → (官方推荐中继)
yuminstall-ygitlab-ce-具体版本号-ce.0.el7.x86_64 gitlab-ctl reconfigure gitlab-ctl restart# ========== 后台迁移进度检查(必做) ==========gitlab-psql-c"SELECT id, job_class_name, status FROM batched_background_migrations WHERE status < 3;"# 要求:输出为空(无未完成迁移)# UI 核验:管理中心 → 监控 → 后台迁移 → 无未完成任务gitlab-rake db:migrate:status gitlab-rake gitlab:checkSANITIZE=true2.6 第4步:版本号秘密 → (最终目标版本)
yuminstall-ygitlab-ce-具体版本号-ce.0.el7.x86_64 gitlab-ctl reconfigure gitlab-ctl restart# ========== 后台迁移最终检查(必做) ==========gitlab-psql-c"SELECT id, job_class_name, status FROM batched_background_migrations WHERE status < 3;"# 要求:输出为空(所有迁移完成)# UI 核验:管理中心 → 监控 → 后台迁移 → 所有任务完成# 关闭维护模式,恢复业务写入gitlab-ctl deploy-page down# 最终全量验证gitlab-rake gitlab:env:info gitlab-rake gitlab:checkSANITIZE=true2.7 旧环境最终备份(用于新环境迁移)
⚠️ 核心警告:务必确保
/etc/gitlab/gitlab-secrets.json文件被正确迁移。如果该文件丢失或与数据库内的加密数据不匹配,会导致所有加密数据(如 CI 变量、Runner Token、双重认证密钥)无法解密,且该类数据几乎无法挽回!
# 生成最终版本全量数据备份gitlab-backup create# 备份文件示例:1707485440_2026_02_09_gitlab_backup.tar# 核心说明:备份文件名格式为「时间戳_日期_版本号_gitlab_backup.tar」# 备份全部配置文件(重点包含gitlab-secrets.json)cp-r/etc/gitlab /tmp/gitlab_etc_bak# 建议单独备份gitlab-secrets.json,双重保障cp/etc/gitlab/gitlab-secrets.json /tmp/gitlab-secrets.json.bak将以下文件传输至新服务器/tmp目录:
- 数据备份包:如
1707485440_2026_02_09_gitlab_backup.tar - 配置备份目录:
gitlab_etc_bak - 单独的secrets备份:
gitlab-secrets.json.bak
三、新环境(Rocky9.5)初始化与安装
3.1 新环境安装同版本 GitLab
# 安装基础依赖dnfinstall-ycurlpolicycoreutils openssh-server postfix systemctlenable--nowpostfix# 配置 GitLab 官方源curl-sShttps://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh|bash# 安装与旧环境一致的最终版本dnfinstall-ygitlab-ce-具体版本号-ce.0.el9.x86_64# 初始化(自动创建 git 用户、目录结构)gitlab-ctl reconfigure# 初始化后立即停止所有服务gitlab-ctl stop四、新环境备份恢复与数据迁移
4.1 备份与配置文件权限处理
⚠️ 核心提醒:恢复配置时优先覆盖
gitlab-secrets.json,确保与旧环境完全一致!
# 1. 移动数据备份包至指定目录mv/tmp/1707485440_2026_02_09_gitlab_backup.tar /var/opt/gitlab/backups/# 2. 修正备份文件权限(必须为 git:git)chowngit:git /var/opt/gitlab/backups/*.tarchmod600/var/opt/gitlab/backups/*.tar# 3. 恢复配置文件(优先恢复secrets文件)cp/tmp/gitlab-secrets.json.bak /etc/gitlab/gitlab-secrets.jsoncp-r/tmp/gitlab_etc_bak_/* /etc/gitlab/chown-Rroot:root /etc/gitlab4.2 执行备份恢复
📌 关键说明:
BACKUP=后仅需填写备份文件名的「时间戳部分」,而非完整文件名!
示例:备份文件为1707485440_2026_02_09_gitlab_backup.tar→BACKUP=1707485440_2026_02_09
# 1. 启动PostgreSQL(恢复操作依赖数据库服务)gitlab-ctl start postgresql# 2. 停止其他依赖服务gitlab-ctl stop puma sidekiq geo-logcursor# 3. 执行恢复(输入 yes 确认)gitlab-backup restoreBACKUP=1707485440_2026_02_09# 4. 恢复完成后重载配置+启动所有服务gitlab-ctl reconfigure gitlab-ctl start📢 补充提醒:外部存储数据同步
若你的 GitLab 开启了外部存储(LFS、CI 制品、Artifacts 存储在 S3/MinIO/对象存储),需注意:
gitlab-backup create不会备份外部存储数据;- 需手动同步外部存储的文件至新环境,或在新环境配置相同的外部存储访问权限。
五、跨OS迁移后的高频排错(重点)
问题1:PostgreSQL 索引损坏(官方警告场景)
现象:数据库查询缓慢、报错,对应官方警告 “Potential PostgreSQL index corruption when upgrading OS”。
原因:从 CentOS7(glibc 2.17)迁移到 Rocky9.5(glibc 2.34),locale 数据变化导致索引损坏。
修复:
# 1. 停止 PostgreSQLgitlab-ctl stop postgresql# 2. 重新索引(针对所有受影响的表,核心操作)gitlab-ctl reindex--all# 3. 启动服务并验证gitlab-ctl start postgresql gitlab-rake db:migrate:status问题2:PostgreSQL/Redis 权限问题
现象:服务启动失败,报错Permission denied。
原因:跨 OS 迁移后,目录属主与权限丢失。
修复:
# 修复 PostgreSQL 权限gitlab-ctl stop postgresqlchown-Rgitlab-psql:gitlab-psql /var/opt/gitlab/postgresql/datachmod-R700/var/opt/gitlab/postgresql/data gitlab-ctl start postgresql# 修复 Redis 权限gitlab-ctl stop redischown-Rgit:git /var/opt/gitlab/redischmod-R700/var/opt/gitlab/redischmod600/var/opt/gitlab/redis/redis.conf gitlab-ctl start redis问题3:服务启动异常
现象:部分服务(如 Alertmanager,Prometheus,Puma, Sidekiq)启动失败。
修复:
# 重新配置并重启所有服务gitlab-ctl reconfigure gitlab-ctl restart# 检查服务状态gitlab-ctl status六、生产级数据一致性验证
6.1 服务状态验证
gitlab-ctl status# 所有服务均为 run 状态gitlab-rake gitlab:checkSANITIZE=true# 无红色报错,所有项为 yes6.2 核心业务数据计数验证(新老环境必须完全一致)
# 用户总数gitlab-rails runner"puts '用户总数:' + User.count.to_s"# 活跃用户数gitlab-rails runner"puts '活跃用户数:' + User.active.count.to_s"# 项目总数gitlab-rails runner"puts '项目总数:' + Project.count.to_s"# 分组总数gitlab-rails runner"puts '分组总数:' + Group.count.to_s"# MR 总数gitlab-rails runner"puts 'MR 总数:' + MergeRequest.count.to_s"# Issues 总数gitlab-rails runner"puts 'Issues 总数:' + Issue.count.to_s"6.3 仓库可用性验证
# 统计仓库文件总数find/var/opt/gitlab/git-data/repositories/-typed-name"*.git"|wc-l# 验证首个项目仓库是否存在(输出 true 即为正常)gitlab-rails runner"puts Project.first.repository.exists?"七、附录:GitLab 迁移速查 Cheat Sheet (CentOS7 → Rocky9)
### 1. 旧环境升级循环 (每一步) # 停止服务 → 开启维护模式 → 备份 → 安装 → 刷新 → 检查后台迁移 → 基础校验 gitlab-ctl stop sidekiq puma geo-logcursor gitlab-ctl deploy-page up gitlab-backup create yum install -y gitlab-ce-<VERSION>-ce.0.el7.x86_64 gitlab-ctl reconfigure gitlab-ctl restart gitlab-psql -c "SELECT id, job_class_name, status FROM batched_background_migrations WHERE status < 3;" # 必须无输出 gitlab-rake db:migrate:status gitlab-rake gitlab:check SANITIZE=true ### 2. 维护模式挂载失败的双应急方案 # 方案1:强制退出维护模式 gitlab-ctl deploy-page down rm -rf /var/opt/gitlab/nginx/www/deploy.html gitlab-ctl restart nginx # 方案2:启动sidekiq完成后台迁移 gitlab-ctl start sidekiq gitlab-psql -c "SELECT id, job_class_name, status FROM batched_background_migrations WHERE status < 3;" gitlab-ctl stop sidekiq ### 3. 最终打包 (旧环境) gitlab-backup create tar -czvf /tmp/gitlab_config_backup.tar.gz /etc/gitlab # 将上面两个文件 scp 到新服务器 ### 4. 新环境恢复 (Rocky9) # 必须先安装同版本 GitLab dnf install -y gitlab-ce-具体版本号-ce.0.el9.x86_64 gitlab-ctl reconfigure gitlab-ctl stop # 放置文件 cp <backup_file> /var/opt/gitlab/backups/ chown git:git /var/opt/gitlab/backups/* tar -xzvf gitlab_config_backup.tar.gz -C / chown -R root:root /etc/gitlab # 执行恢复(BACKUP=时间戳部分) gitlab-ctl start postgresql gitlab-backup restore BACKUP=<TIMESTAMP> ### 5. 关键修复 (新环境) # 修复 PostgreSQL 索引 (glibc 变更必做) gitlab-ctl reindex --all # 修复权限 chown -R gitlab-psql:gitlab-psql /var/opt/gitlab/postgresql chown -R git:git /var/opt/gitlab/redis ### 6. 重启与验证 gitlab-ctl reconfigure gitlab-ctl restart gitlab-rake gitlab:check SANITIZE=true八、总结与经验
- 官方工具优先:升级前务必使用 GitLab Upgrade Path Tool 查询合规路径,这是避免灾难的第一步。
- 后台迁移是隐形杀手具体版本.x→.x 升级中,未完成的后台迁移会直接导致数据库损坏,生产环境优先用
gitlab-psql命令核验,确保无未完成任务。 - 维护模式有双兜底方案:挂载失败时,可选择「强制退出恢复业务」或「启动sidekiq完成迁移」,适配不同生产场景。
- 密钥绝不丢失:
gitlab-secrets.json是 GitLab 加密数据的核心,迁移时必须单独备份、优先恢复,丢失会导致加密数据永久失效。 - CentOS7 特殊处理:提前更新 GPG 密钥,避免安装时签名验证失败。
- 跨OS迁移核心坑:glibc 版本差异会导致 PostgreSQL 索引损坏,必须执行
reindex --all修复。 - 备份参数别填错:
gitlab-backup restore的BACKUP=仅需填写时间戳部分,而非完整文件名。 - 版本升级保守化:额外增加 版本号1 过渡节点,能大幅降低跨大版本升级的兼容性风险,生产环境优先选择“慢但稳”的路径。