GitLab CE 18.6.1 升级到 18.11.13 的过程记录
记录时间:2026-10-22
环境:生产 K8s 集群(信创 ARM64),devops 命名空间,GitLab CE omnibus 单容器 Deployment,数据在 NFS PVC
一、背景
升级的原因是 GitLab 发布了 18.11.13 关键安全版本(critical security release),修复了多个高危漏洞,生产环境在用的 18.6.1 在受影响范围内,所以决定升级。漏洞细节以官方发布说明为准,这里不展开 CVE 清单。
生产环境的 GitLab 是 K8s 单容器部署,原镜像是内部仓库的 18.6.1-ce.0-linuxarm64,PostgreSQL、Redis 都跑在容器内部,数据整体落在 NFS PVC(gitlab-pvc,storageClass 由 NFS 提供)上。目标是升到 18.11.13-ce.0(ARM64)。
我一开始的想法是直接把镜像 tag 改掉。查了 GitLab 的升级路径文档之后否掉了:18.x 的强制停靠点是 18.2、18.5、18.8、18.11,从 18.6.1 到 18.11.13 必须先到 18.8 的最新补丁,等后台迁移完成,再上 18.11.13。
| 环境信息 | 值 |
|---|---|
| 命名空间 | devops |
| 部署形态 | Deployment gitlab-ce,单副本,单容器 omnibus |
| 镜像仓库 | 内部 Harbor(library/gitlab/gitlab-ce) |
| 存储 | NFS PVC gitlab-pvc,/etc/gitlab、/var/log/gitlab、/var/opt/gitlab 三个 subPath |
| 节点 | arm64(nodeSelector 固定),第一跳调度到 arm64 节点 |
二、操作过程
2.1 先改造 Deployment YAML
直接改 tag 会遇到两个问题。第一是升级路径(上面说的 18.8 停靠点);第二是 Deployment 没有 strategy,默认 RollingUpdate,单副本加 RWX PVC 会先起新 Pod,新旧两个 GitLab 同时挂同一份 /var/opt/gitlab(PostgreSQL、Redis 都在里面),有损坏数据的风险。所以动手前我先把 YAML 改了一轮:
| 参数 | 值 | 说明 |
|---|---|---|
| strategy.type | Recreate | 先停旧 Pod 再起新 Pod,避免双实例共用 PVC |
| progressDeadlineSeconds | 3600 | 给跨版本数据库迁移留时间(原来 600 太短) |
| revisionHistoryLimit | 5 | 两跳升级,多留几个版本方便回滚 |
| terminationGracePeriodSeconds | 300 | 给 GitLab 足够的优雅退出时间 |
| nodeSelector | kubernetes.io/arch: arm64 | 防止调度到 x86 节点起不来 |
| resources | requests 2C/4Gi,limits 3C/6Gi | 迁移期间内存容易吃紧,稍微放宽 |
readiness/liveness probe 这次没有加。代价是 rollout status 完成不代表 GitLab 真正可用,后面全靠手工确认。
2.2 备份 18.6.1
升级前先在旧版本上做完整备份:
kubectl -n devops exec deploy/gitlab-ce -- gitlab-backup create STRATEGY=copy
kubectl -n devops exec deploy/gitlab-ce -- tar czf /var/opt/gitlab/backups/etc-gitlab-18.6.1-$(date +%F-%H%M).tar.gz -C /etc gitlab
注意:gitlab-backup 的备份不包含 gitlab.rb 和 gitlab-secrets.json,这两样必须单独打包。备份默认落在 /var/opt/gitlab/backups,和数据在同一个 NFS 上,只留同盘不算独立备份,还要复制一份到主机本地盘。
产物:1792655913_2026_10_22_18.6.1_gitlab_backup.tar(4.5MB)、etc-gitlab-18.6.1-*.tar.gz。
2.3 第一跳 18.6.1 → 18.8.11
确认镜像仓库里的 18.8.11-ce.0 是 ARM64 后,把镜像改成 18.8.11 再 apply:
kubectl apply -f gitlab.yaml
kubectl -n devops rollout status deploy/gitlab-ce --timeout=60m
起来后查 gitlab-rake gitlab:background_migrations:status,里面有 7 条 active(BackfillProjectNamespaceDetails、BackfillPartitionedUploads、BackfillNamespaceState 等)。我决定停在这里等,不继续切版本。过了一段时间再查,变成 no active。
2.4 第二跳 18.8.11 → 18.11.13
18.6.1 的备份只能恢复到 18.6.1,这一跳的回滚依据是 18.8.11 的备份,所以先把 18.8.11 也备份一遍:
kubectl -n devops exec deploy/gitlab-ce -- gitlab-backup create STRATEGY=copy
kubectl -n devops exec deploy/gitlab-ce -- tar czf /var/opt/gitlab/backups/etc-gitlab-18.8.11-$(date +%F-%H%M).tar.gz -C /etc gitlab
再用 docker manifest inspect 确认 18.11.13-ce.0 有 arm64,然后改镜像 tag、apply。
2.5 18.11.13 触发 PostgreSQL 自动升级
切过去之后,gitlab-ctl status 突然一大片 down:postgresql、gitaly、sidekiq、sshd 都是 down,只有 puma、nginx、redis 等少数几个还在。我第一反应是升级出问题了,翻启动日志看到:
Upgrading PostgreSQL to 17.10
Toggling deploy page
Toggling services
Running stop on postgresql
Initializing the new database: OK
这才明白是 omnibus 在自动升 PostgreSQL 到 17.10,服务 down 是被主动停掉的,puma/nginx 还挂着是给 deploy page 用的。我决定不动 Pod,等它跑完,也不手工重启,避免打断 pg_upgrade。数据 5GB 左右,等了几分钟,服务陆续全部起来。
三、验证
kubectl -n devops exec deploy/gitlab-ce -- cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
# 18.11.13
kubectl -n devops exec deploy/gitlab-ce -- gitlab-ctl status
# 15 个服务全部 run
kubectl -n devops exec deploy/gitlab-ce -- curl -s -o /dev/null -w '%{http_code}\n' http://localhost/-/readiness
# 200
kubectl -n devops exec deploy/gitlab-ce -- gitlab-rake gitlab:background_migrations:status
# 全部 finalized / finished,没有 active
kubectl -n devops exec deploy/gitlab-ce -- gitlab-rake gitlab:check SANITIZE=true
# 全部 OK,All migrations up: yes
Sidekiq 日志里反复出现的 Cannot obtain an exclusive lease 是 DEBUG 级别,来自并发限流 worker(ci/unlock_pipelines_in_queue_worker),表示已有实例在执行,不是故障。
四、注意事项
- 恢复必须同版本:18.6.1 的备份只能恢复到 18.6.1,18.8.11 的备份只能恢复到 18.8.11。
- 回滚不是换镜像:数据目录已经被 PostgreSQL 17.10 升级过,直接把镜像换回 18.8.11 起不来,回滚路径是 18.8.11 镜像加 18.8.11 备份恢复。
- 强制停靠点要提前查:18.x 是 18.2、18.5、18.8、18.11,不能跨过。
- 备份文件留在 NFS 同盘不算独立备份,要复制到集群外。
- Recreate 会有停机窗口,选维护时间做。
- 没有 readiness probe,rollout status 完成不代表能登录,要等 readiness 200 和 gitlab:check 通过。
- 18.8.11 的镜像和备份先保留,观察几天再清理。