Data migration from GitLab 14.0.12 to 17.8.z
Versions 3.16 and 3.18 support GitLab versions that lag behind the official versions. Upgrading GitLab to the latest official version requires more than 10 upgrades to complete. After upgrading to 4.0, the product does not provide automatic upgrades to 17.8.z. This solution addresses how to migrate data from 14.0.12 to 17.8.z.
Considering the large version gap, we adopt a data migration approach for the upgrade.TOC
Terminology
Process Overview
Data Migration Path
According to the official upgrade path documentation, the data migration path is as follows:
- 14.0.12 -> 14.3.6
- 14.3.6 -> 14.9.5
- 14.9.5 -> 14.10.5
- 14.10.5 -> 15.0.5
- 15.0.5 -> 15.4.6
- 15.4.6 -> 15.11.13
- 15.11.13 -> 16.3.8
- 16.3.8 -> 16.7.9
- 16.7.9 -> 16.11.10
- 16.11.10 -> 17.3.6
- 17.3.6 → 17.5.5
- 17.5.5 → 17.8.1
Finally, back up the data from 17.8.1 and import it into the platform-deployed 17.8.z instance to complete the data migration.
Data Migration Process
Back up the platform-deployed GitLab and restore it to an all-in-one image deployed GitLab, then upgrade to 17.8.1 using the all-in-one image, and finally restore the data backup to the platform-deployed 17.8.z instance.
- Back up the
platform-deployedGitLab 14.0.12 instance. - Restore the backup to an
all-in-onedeployment of GitLab 14.0.12. - Perform a rolling upgrade of the
all-in-onedeployment to GitLab 17.8.1. - Back up the upgraded
all-in-oneGitLab 17.8.1 instance. - Restore the backup from the
all-in-one17.8.1 to aplatform-deployedGitLab 17.8.z instance.
For the latest GitLab instance and operator versions, please refer to the Release Note.
The migration process involves database and repository backup/restore operations:
- Larger databases increase migration time.
- A higher number of repositories or larger single repositories significantly extends the duration.
- Storage performance also impacts efficiency — using topolvm is recommended for better performance.
Test setup:
- One large repository (~600 MB), others are small initial repositories
- GitLab instance: 6,700 issues, 3,600 merge requests
Prerequisites
-
Install kubectl (>=1.30.0) and yq (>=4.45.0) on the execution host.
-
Configure environment variables:
-
Prepare the PVCs required for the upgrade. These must be created in the same namespace as the old GitLab instance:
TIPA simple way to estimate the required storage size for the original instance is to sum the PVC sizes used by the database and the Gitaly components.
-
backup-pvc: Used to store backup tarballs. The recommended capacity is twice the size of the original instance. -
upgrade-pvc: Used to store GitLab data during the rolling upgrade process. The recommended capacity is 1.2 times the size of the original instance.
-
Prepare the images needed for the upgrade. Download each version of the image from the attachments and push them to an image repository that the GitLab deployment cluster can pull from. Image download links:
-
Prepare the scripts needed for the upgrade.
Execute the following command to generate four scripts:
-
check_gitlab.sh: Check if the GitLab pod is ready. -
finalize_migrations.sql: Finalize the migrations. -
monitor_gitlab.sh: Monitor the GitLab pod to check if data migration is complete. -
rolling_upgrade.sh: Rolling upgrade the GitLab instances one by one.
Backup the platform-deployed GitLab 14.0.12
-
Enable the task-runner component on GitLab 14 to execute backup commands
-
Set GitLab 14 to read-only mode
-
Patch the backup PVC for the GitLab 14 task-runner. The PVC should be named
backup-pvc. -
Back up GitLab 14 data
Back up the rails-secret by executing the following command, which will save the rails-secret to a file named
gitlab14-rails-secret.yamlin the current directory. -
Remove the task-runner component after backup is complete.
Restore backup data to all-in-one deployment of 14.0.12
-
Use the
all-in-oneimage to deploy GitLab 14.0.12.First, set the
NODE_IPenvironment variable to access theall-in-oneGitLab instance through this IP and NodePort port.Create the
all-in-oneGitLab instance.Check if the
all-in-oneGitLab instance started successfully. -
Modify the rails secret content of the
all-in-oneGitLab. Replace thesecret_key_base,otp_key_base,db_key_base,openid_connect_signing_key,ci_jwt_signing_keyfields with the corresponding fields from the backed up GitLab 14 rails secret.Disable unnecessary components.
Restart the pod and wait for it to start up.
-
Restore the backup data.
TIPDuring the recovery process, database-related errors may occur, for example:
ERROR: role "xxx" does not existERROR: function xxx does not existERROR: permission denied to create extension "pg_stat_statements"ERROR: could not open extension control file
These errors can be ignored, details can be found at (https://gitlab.com/gitlab-org/gitlab/-/issues/266988).
Restart the pod and wait for it to start up, then execute
gitlab-rake gitlab:check SANITIZE=trueto check GitLab integrity.Log in to GitLab to check if the instance restoration was successful (root user password remains the same as the original instance), and execute the following command to get the access address of the
all-in-oneinstance.
Rolling upgrade all-in-one deployed gitlab to 17.8.1
Execute the rolling_upgrade.sh script, which will upgrade the all-in-one instance step by step to version 17.8.1 according to the upgrade path.
After the script execution is complete, enter the GitLab Web UI to check if the instance version is 17.8.1, and verify that the data is complete, including code repositories, users, issues, merge requests, etc.
Back up the data from 17.8.1 all-in-one instance
Stop the all-in-one instance service and back up the data. The backup files will be saved in the /var/opt/gitlab/backups/ directory.
Stop the all-in-one instance service.
Restore all-in-one backup data to platform-deployed 17.8.z
The namespace of the new gitlab instance must be the same as the namespace of the old gitlab instance.
-
Refer to the GitLab Deployment Guide to use the operator for deploying a new GitLab 17.8.z instance.
::: tip
- The newly deployed instance must be in the same namespace as the old instance
- The access method of the newly deployed instance must not conflict with the old instance, such as domain name, nodeport, etc. :::
After the new instance is deployed, set the environment variable for the new instance name:
-
Enable the toolbox component for the new GitLab instance.
Wait for the instance to complete redeployment.
-
Restore backup data to the GitLab 17.8.z deployed by the operator
TIPDuring the recovery process, database-related errors may occur, for example:
ERROR: role "xxx" does not existERROR: function xxx does not existERROR: must be owner of extension
These errors can be ignored, details can be found at (https://gitlab.com/gitlab-org/gitlab/-/issues/266988).
Close the external access of the new 17.8.z gitlab instance, and patch the toolbox component to mount the backup pvc.
Wait for the toolbox pod to be ready, and then restore the backup data to the new GitLab instance.
-
Replace the rails-secret for the new GitLab instance.
The operator will automatically redeploy the new GitLab instance. Wait for the instance to complete redeployment.
-
Verify that the data after the upgrade is normal.
- Enter the GitLab UI in administrator view and check whether the repositories and user data are normal.
- Select some repositories and verify whether the code, branches, and merge requests are functioning properly.
-
Clean up unused resources:
- Delete the old GitLab instance and the old operator if necessary.
- Delete the
all-in-oneGitLab instance if necessary.
FAQ
-
The migrated data does not include avatars and attachments, so the new GitLab instance cannot display this content. To resolve this issue, you can replace the upload PVC of GitLab 17.8.z with the PVC used by 14.0.12.
Set the environment variable for the uploads pvc name:
Patch the new GitLab instance to use the uploads PVC:
If your old GitLab instance uses HostPath storage, you must manually copy the data from the old instance's uploads directory to the
/srv/gitlab/public/uploadspath of the webservice component in the new instance.