Skip to content

Version Management & Upgrades

The operator uses a GitlabVersionMap CRD to map GitLab application versions to the corresponding Helm chart versions. Understanding version resolution and the required upgrade stop sequence is essential before performing upgrades.

How version resolution works

When the operator reconciles a GitlabInstance, it resolves spec.version through this priority chain:

  1. spec.helm.version (escape hatch) — if set, this exact chart version is used directly, bypassing the version map entirely.
  2. GitlabVersionMap/default — the operator always looks up the cluster-scoped GitlabVersionMap named default.
  3. Alias resolution"latest" and "stable" resolve to the version string they point at in spec.aliases.
  4. Prefix resolution"18" or "18.5" resolve to the highest matching entry (e.g. "18.5.7").
  5. Exact match"18.5.7" matches the entry directly.

If the version map is not present, the error is transient (the operator requeues with back-off). If the version string is not found in the map, it is a permanent user error and the instance enters phase: Failed.

The default GitlabVersionMap

The examples/versionmap-default.yaml ships the full upgrade ladder from GitLab 17.3 through 19.x:

apiVersion: k8s.bnerd.com/v1alpha1
kind: GitlabVersionMap
metadata:
  name: default
spec:
  versions:
    "17.3.0":
      chartVersion: "8.3.0"
    "17.5.5":
      chartVersion: "8.5.5"
    "17.8.7":
      chartVersion: "8.8.7"
    "17.11.7":
      chartVersion: "8.11.8"
    "18.2.8":
      chartVersion: "9.2.8"
    "18.5.7":
      chartVersion: "9.5.7"
    "18.8.10":
      chartVersion: "9.8.11"
    "18.11.6":
      chartVersion: "9.11.7"
    "19.1.1":
      chartVersion: "10.1.1"
  aliases:
    latest: "19.1.1"
    stable: "18.11.6"
    "17": "17.11.7"
    "18": "18.11.6"
    "19": "19.1.1"

Each version key in spec.versions corresponds to a required upgrade stop — a GitLab version through which every upgrade path must pass.

Required upgrade stops

Never skip upgrade stops

GitLab enforces required upgrade stops. Skipping a stop (e.g. going from 17.3 → 17.11 directly) will cause GitLab to refuse to start due to pending irreversible database migrations. Always follow the stop sequence exactly.

Since GitLab 17.5, required upgrade stops occur at x.2 / x.5 / x.8 / x.11 of each major version. The full path is:

17.3.0 → 17.5.5 → 17.8.7 → 17.11.7 → 18.2.8 → 18.5.7 → 18.8.10 → 18.11.6 → 19.1.1

Each arrow represents one spec.version bump and one helm upgrade emitted by the operator.

Performing an upgrade

Upgrades are declarative: update spec.version on the GitlabInstance to the next required stop. The operator resolves the chart version, emits an updated HelmRelease, and Flux runs helm upgrade.

Example: 17.3 → 17.5

  1. Confirm the current running version:

    kubectl get gli my-gitlab -n my-gitlab
    # NAME       PHASE   HOST                      VERSION   AGE
    # my-gitlab  Ready   https://git.example.com   17.3.0    30d
    
  2. Update spec.version to the next stop:

    kubectl patch gli my-gitlab -n my-gitlab \
      --type merge \
      -p '{"spec":{"version":"17.5.5"}}'
    
  3. Watch the upgrade progress:

    kubectl get gli my-gitlab -n my-gitlab -w
    # NAME       PHASE      HOST                      VERSION   AGE
    # my-gitlab  Deploying  https://git.example.com   17.5.5    30d
    # my-gitlab  Ready      https://git.example.com   17.5.5    30d
    
  4. Verify the HelmRelease completed:

    kubectl get helmrelease my-gitlab -n my-gitlab
    kubectl describe helmrelease my-gitlab -n my-gitlab
    
  5. Repeat for the next stop (17.8.7, then 17.11.7, etc.).

Checking observedVersion

The status.observedVersion reflects the value of spec.version that was last reconciled. After an upgrade it should match spec.version:

kubectl get gli my-gitlab -n my-gitlab \
  -o jsonpath='{.status.observedVersion}{"\n"}'

Major version considerations

GitLab 17 → 18

The chart major version jumps from 8.x to 9.x. The Helm values schema is compatible; no manual values migration is required for standard configurations. If you use spec.helm.values to pass custom chart values, review the GitLab chart changelog for breaking changes.

GitLab 18 to 19 (chart 9 to 10)

External object storage is mandatory on GitLab 19 / chart 10

GitLab 19 (chart 10) removed bundled MinIO and the bundled PostgreSQL and Redis sub-charts. You must have spec.objectStorage.credentialsSecret configured with a valid external S3 Secret before upgrading to 19.x. Upgrading without it will cause the chart install to fail.

Ensure your spec.objectStorage.credentialsSecret is wired and validated (all bucket-class keys present) before applying spec.version: "19.1.1".

Customising the version map

To add a new GitLab version that is not yet in the default map:

kubectl edit gitlabversionmap default

Add the new entry under spec.versions:

spec:
  versions:
    "18.11.7":          # new patch release
      chartVersion: "9.11.8"

And update the relevant alias if appropriate:

spec:
  aliases:
    stable: "18.11.7"

Editing the GitlabVersionMap does not automatically trigger a reconcile on running instances. Version resolution only re-runs when the GitlabInstance spec changes. To trigger an upgrade after updating the map, update spec.version on the instance.

No downgrades

GitLab does not support database schema downgrades. The operator does not prevent you from setting a lower spec.version, but the chart upgrade will fail (or GitLab will refuse to start) because the database schema is ahead of the requested version. If you need to roll back, restore a database backup.