
搞GitLab EE版本升级最怕的不是升级本身而是升级到一半发现数据库迁移卡死、页面502、Runner全部失联。我这次把一台跑了很久的13.12.5社区版一路撸到17.0中间经历了三次大版本跨越踩了license失效、unicorn换puma、PostgreSQL自动迁移这三个典型的坑。整个过程整理出来希望能帮准备升级gitlab-ee的朋友少走弯路。这篇文章适合谁看如果你的GitLab实例已经跑了大半年以上、版本明显落后、或者你正打算从旧版EE跨多个大版本升级这篇文章可以直接当操作手册用。我会把升级路径规划、备份验证、逐级升级动作、故障排查、回滚预案全部讲透。1. 为什么GitLab EE升级不能想升就升1.1 GitLab升级路径是硬约束不是建议很多人以为升级就像装个新版软件包那么简单直接yum update就完事。GitLab官方最强调的一件事就是升级路径必须按顺序走不允许跨大版本跳级。原因在于数据库迁移和底层结构变更不同大版本之间的schema可能完全不兼容。比如你在13.x想一步装到15.x就算安装成功了reconfigure阶段极可能跑出一堆数据库迁移报错数据都救不回来。GitLab官方Upgrade Path工具可以输入起点和终点版本号自动规划路线。按我的经验跨大版本最稳妥的原则是先升级到当前大版本最新的patch版本再跨到下一个大版本的最新patch版本一级一级走。这是我这次升级的路线规划示例当前版本目标版本中间必须经过13.12.514.x先升到13.12.5最新patch再升14.10.514.10.515.x升到15.11.1315.11.1316.x升到16.x最新patch版本16.x17.x用官方Upgrade Path确认最后一步1.2 升级前先体检系统、版本和许可证状态拿到升级任务后第一步不是下载安装包而是先确认当前实例的状态。先看当前版本sudo cat /opt/gitlab/embedded/service/gitlab-rails/VERSION再看系统发行版是否在官方支持矩阵里。这里有个很多人忽略的坑GitLab 16和17已经不再支持CentOS 7如果你还在CentOS 7上跑直接装新版本会发现源里根本没有匹配的包。这时候你得先做系统迁移而不是升级GitLab。RHEL 8/9、Ubuntu 20.04/22.04这些才是新版本的目标系统。接着检查License状态。如果你是EE版本打开管理员后台的License页面确认当前许可证的有效期和订阅类型。GitLab 16之后许可证机制有调整我这次从13跨到16之后后台就提示旧的许可证格式需要重新上传新版License文件提前准备好正版许可文件能避免升级后功能被锁。磁盘空间和内存也要算清楚。GitLab官方建议升级时至少预留备份文件大小 安装包大小2到3倍的空闲空间。比如备份有20GB安装包3GB那/var/opt/gitlab所在分区至少要留60GB以上不然升级到一半磁盘写满直接卡死。2. 备份做得有多重升级就有多稳2.1 数据库与代码库的备份实操GitLab备份工具会把Git仓库、数据库、上传文件打包成一个tar文件。新版用gitlab-backup老版本用gitlab-rake gitlab:backup:create命令如下# GitLab 12.2之后推荐用这个 sudo gitlab-backup create # 老版本用这个 sudo gitlab-rake gitlab:backup:create备份文件默认生成在/var/opt/gitlab/backups目录文件名是时间戳加_gitlab_backup.tar的形式。生产环境建议加STRATEGYcopy参数避免文件系统的流式复制导致某些仓库快照不一致sudo gitlab-backup create STRATEGYcopy备份时间长短取决于仓库数量和大小我的实例跑一次要15到20分钟。备份期间服务可以继续运行但如果你追求极致的数据一致性尤其是升级前这个时间点建议先停掉Puma和Sidekiq再备份确保没有正在写入的事务sudo gitlab-ctl stop puma sudo gitlab-ctl stop sidekiq sudo gitlab-backup create sudo gitlab-ctl start puma sudo gitlab-ctl start sidekiq2.2 gitlab.rb和secrets.json比数据库备份还命根子数据库能备份但很多人忽略了/etc/gitlab/gitlab.rb和/etc/gitlab/gitlab-secrets.json这两个配置文件。gitlab.rb里面记录着你所有的自定义配置secrets.json里面则是各种加密密钥包括2FA、Runner注册令牌、CI/CD变量加密密钥、数据库加密密钥等。如果secrets.json丢失或和恢复的数据不匹配最典型的症状是Runner重新注册后怎么都不通、项目访问令牌全部失效、2FA用户无法登录。恢复备份时旧数据配新secrets效果等于让一把新钥匙开旧锁。升级前一定要把这两个文件单独复制出来sudo cp /etc/gitlab/gitlab.rb /etc/gitlab/gitlab.rb.bak.$(date %Y%m%d) sudo cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.bak.$(date %Y%m%d)如果配了对象存储备份加密比如backup_encryption开启了AES256那把加密密钥也要一并保存否则备份文件拿到手也无法解密恢复。2.3 备份有效性验证升级前最容易被跳过的环节备份没验证就等于没备份。我见过太多同事升级失败想恢复结果发现备份文件是坏的直接炸裂。验证分两步走。第一步检查备份文件完整性sudo ls -lht /var/opt/gitlab/backups # 确认最新的tar包时间戳是刚才生成的文件大小不是0第二步是在一台闲置的同版本机器上做恢复测试。这个动作最科学但很多人没条件。退一步的做法至少检查tar包内目录结构是否完整tar tf /var/opt/gitlab/backups/1712345678_2024_04_05_13.12.5_gitlab_backup.tar | head -n 50正常备份包会有db、repositories、builds、artifacts等目录。如果能看到这些目录结构说明备份基本没坏。3. 按图索骥逐级升级实操过程3.1 规划升级路线图这一节我用我这次13.12.5跨到17.0的真实路线举例。假设当前版本是13.12.5目标是最新的17.0.x那路线就是13.12.5 → 14.10.5 → 15.11.13 → 16.x最新patch → 17.0.x。中间需要经过四个大版本至少要执行四次安装操作每次装完都要确认服务正常后才进行下一次。查可用版本的方式# RHEL/CentOS yum list gitlab-ee --showduplicates | sort -r # Debian/Ubuntu apt-cache policy gitlab-ee建议下载目标版本到本地而不是直接yum install最新版。这样能精准控制升级步骤避免一步跨太多。3.2 软件源配置与版本锁定GitLab EE的官方源在国内访问速度不理想我这边用的是清华的GitLab镜像源配置方式# RHEL/CentOS cat /etc/yum.repos.d/gitlab_gitlab-ee.repo EOF [gitlab_gitlab-ee] namegitlab_gitlab-ee baseurlhttps://mirrors.tuna.tsinghua.edu.cn/gitlab-ee/yum/el8 gpgcheck0 enabled1 EOF # 更新缓存 yum clean all yum makecacheUbuntu的源配置类似把baseurl换成对应系统的apt路径即可。如果公司有内网镜像直接走内网最快。配置好源之后不要直接yum update gitlab-ee。因为生产环境必须精确锁定版本使用# RHEL/CentOS安装特定版本 sudo yum install gitlab-ee-14.10.5-ee.0.el8.x86_64 # Debian/Ubuntu sudo apt install gitlab-ee14.10.5-ee.0一次只装一个目标版本禁止跳版本。3.3 逐级升级后的检查点每跑完一次安装必须依次做以下几项检查全绿才允许进入下一级。第一步看reconfigure是否成功完成。安装过程中会自动跑gitlab-ctl reconfigure如果结尾出现Upgrade complete才能放心。安装完成后再次手动执行reconfigure确认无误sudo gitlab-ctl reconfigure第二步查看服务状态确保核心服务全部runningsudo gitlab-ctl status重点看nginx、puma或unicorn、sidekiq、postgresql的状态任何一个down都不能往下走。第三步跑健康检查sudo gitlab-rake gitlab:check看到All checks should pass基本就稳了。如果有红色警告比如Redis连接异常、数据库pending migrations先解决再继续。第四步浏览器直接访问实例首页确认能正常打开登录界面。这一步能快速发现nginx转发、Puma启动等方面的问题。3.4 跨大版本时容易忽略的行为变化跨大版本升级不只是换版本号行为变化也要提前了解。从13升14这个过程unicorn会切换成Puma。如果你之前在nginx里配置了指向unicorn socket的反代reconfigure后会自动调整但如果你有自定义的unicorn配置升级后可能失效导致502。升级后一定要测一遍页面能不能打开。另一个坑是内置Grafana的移除。老版本Omnibus自带Grafana服务升级到较新版本后Grafana不再随包安装之前用的监控看板会消失。如果你们团队依赖这个提前把监控指标接到外部Prometheus上再动手。还有GitLab 16开始的许可证格式变更老式license文件可能无法直接激活。升级后第一时间进管理员后台确认License状态。4. 升级过程中最常卡壳的三个场景4.1 reconfigure失败先看日志再动手reconfigure失败的时候屏幕上的红色报错往往不完整真正的原因几乎都在/var/log/gitlab/reconfigure里。错误文本比较长我通常用tail直接看最后的几十行sudo tail -n 80 /var/log/gitlab/reconfigure | grep -A 20 ERROR常见原因是文件权限问题。之前手动改过/var/opt/gitlab下的目录属主reconfigure时某一步写不进去就会失败。遇到这种先确认报错涉及的目录属主是不是git用户再用chown修正。还有一种情况是PostgreSQL自动升级卡住。reconfigure检测到数据库大版本需要变更时会自动做PG的迁移这段时间CPU和磁盘IO会很高屏幕上可能长时间停在某一处。别急着CtrlC先看数据库日志sudo gitlab-ctl tail postgresql | tail -n 50如果日志显示在正常刷Write Ahead Log或者reindex就耐心等着。手动中断reconfigure导致状态不完整后面再跑往往更麻烦。4.2 数据库迁移报错怎么读跨大版本升级时最容易报错的就是数据库迁移环节。出现这类报错先判断是SQL执行问题还是依赖缺失。如果报错里有PG::DuplicateColumn这类说明迁移脚本执行到一半中断过。这通常是因为之前某次reconfigure失败后你手动重跑未完成的迁移被重复执行。解决方案是进入Rails console手动补齐迁移状态sudo gitlab-rails runner ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths).get_all_versions当确认哪些迁移没跑完可以手动执行缺失的迁移sudo gitlab-rails db:migrate跑完再看迁移状态全部到位后再reconfigure。4.3 升级后502与维护页面卡住升级完成之后访问首页出现502是GitLab升级最常见的场景。502的直接原因通常是Puma和Sidekiq没起来但为什么没起来才是关键。按顺序排查# 看服务状态 sudo gitlab-ctl status # 看Puma日志 sudo gitlab-ctl tail puma | tail -n 50 # 看Sidekiq日志 sudo gitlab-ctl tail sidekiq | tail -n 50 # 看Nginx日志 sudo gitlab-ctl tail nginx | tail -n 50我遇到过一次Puma起不来的情况日志里显示内存不足被OOM Killer杀掉。那个实例总共只有4GB内存跨大版本之后Puma多开了一个worker内存直接爆了。解决方式是调整Puma配置减少worker数量或者在升级窗口内临时加内存# /etc/gitlab/gitlab.rb puma[worker_processes] 2还有一种情况是旧的unicorn socket残留导致Nginx转发到错误地址。升级后如果一直502可以把/var/opt/gitlab/gitlab-rails/sockets目录下的老socket清掉重启Puma和Nginxsudo rm -f /var/opt/gitlab/gitlab-rails/sockets/*.socket sudo gitlab-ctl restart puma sudo gitlab-ctl restart nginx升级完有条件的话直接重启一次整机让内核和所有系统服务都进入干净状态。我实测下来重启一次之后很多莫名其妙的小问题自动消失。5. 升级完成后的验证清单与回滚预案5.1 功能层验证清单升级完成不代表万事大吉功能验证是必做项。我每次升级完会按这个清单走一遍验证项操作方式预期结果页面和登录浏览器访问首页登录管理员账号正常打开、可登录Git操作创建一个测试项目clone并pushSSH和HTTP都能正常操作CI/CD触发一条流水线Runner正常拉取任务并执行成功后台健康/admin 页面访问各种组件绿灯License/admin/license 页面查看许可证有效日期正确Runner运行gitlab-runner list确认注册状态Runner显示active标签正确同时要注意如果启用了外部Elasticsearch做高级搜索跨大版本后ES索引可能出现不兼容问题搜索结果异常或索引无法更新。这时候需要按新版本的ES兼容矩阵升级ES集群、重新创建索引。5.2 Runner和集成服务兼容性GitLab Runner的兼容性也是高频翻车点。GitLab升级后Runner不一定必须同步升级但版本相差太远会导致注册令牌和API调用不兼容。我在升级后遇到过Runner显示在线但无法pick job的情况原因就是Runner版本太老接口路径已废弃。最佳实践是先升级GitLab实例然后立刻看Runner的兼容矩阵把Runner升到对应版本gitlab-runner --version sudo gitlab-runner verify如果register用的token在升级后失效需要重新注册Runnersudo gitlab-runner register --url https://your.gitlab.com --token xxxWebhook、第三方集成也类似。检查一下你配置的Webhook最近是否有推送失败的记录有就重新保存一次Webhook配置让签名密钥重新同步。5.3 回滚到上一个版本的正确姿势升级失败要回滚前提是你按前面说的做了备份。回滚流程要记住不只是恢复数据库连软件包版本也要一起降回去。# 停止相关服务 sudo gitlab-ctl stop puma sudo gitlab-ctl stop sidekiq # 恢复备份 sudo gitlab-backup restore BACKUP1712345678_2024_04_05_13.12.5 # 降级软件包版本 sudo yum downgrade gitlab-ee-13.12.5-ee.0.el8.x86_64 # 重新配置并启动 sudo gitlab-ctl reconfigure sudo gitlab-ctl restart这里有个关键细节备份文件名里的时间戳要写全不要带_gitlab_backup.tar后缀。降级包版本时要注意yum downgrade不一定能找到旧版本因为旧版本可能已经被你安装后清理了如果降级不成功静态从官网下载对应rpm包手动安装sudo yum install -y ./gitlab-ee-13.12.5-ee.0.el8.x86_64.rpm --oldpackage恢复完成后gitlab.rb和secrets.json必须是回滚前备份的那一份这一点千万别搞混。否则secrets不匹配runner和2FA全部乱掉。6. 三条用代价换来的经验第一升级窗口要留足。跨多个大版本的升级不是半小时能搞定的。数据库迁移、PG版本升级、多轮reconfigure每轮都有不确定性。我在这次升级中预留了4个小时实际用了将近3个小时还包括一次问题排查。建议至少留4小时以上的窗口期并且安排在业务低峰期升级前还要把维护通知发给团队。第二遇到问题不要慌先看日志。GitLab的日志体系很完整/var/log/gitlab/目录下每个服务都有自己的日志文件。很多报错看日志就能定位但新手容易在Google里瞎搜浪费时间还搜不到正确答案。动手之前先执行sudo gitlab-ctl tail相关的服务日志里写得很明白。第三升级不是一锤子买卖要养成定期升级的习惯。很多团队是把GitLab装好就不管了堆到落后两三个大版本才升级这时候升级风险极高。这里说的定期是指至少每个季度或半年看一次当前版本是否还在官方安全支持周期内及时升到当前大版本的最新patch版本。小版本升级成本低、风险小比一次性跨多个大版本省心太多。我自己的习惯是每次升级完把本次升级的版本路径、遇到的问题、处理方式都记进团队运维文档。下一次升级直接翻文档很多坑就不用再踩一遍了。