Migrate a GitLab resource to a GitLabCore resource

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab Self-Managed
  • Status: Experiment

Use kubectl bridge migrate to move an instance from a GitLab resource (apps.gitlab.com/v1beta1) to a GitLabCore resource (apps.gitlab.com/v2alpha1) of the same name. After the migration, you manage the instance in Bridge.

The command deletes the GitLab resource, then creates the GitLabCore resource. The instance is down from the delete until the GitLabCore resource is available.

Bridge is an experiment in an early development phase. Migrate only an instance you can afford to lose.

Data the migration keeps

The migration keeps:

  • The Gitaly volumes, and with them the Git repositories.
  • The Secrets the GitLab chart generated, such as the Rails secrets and the root password.
  • The external PostgreSQL, Redis, and object storage, and the data in them.
  • The Gateways, EnvoyProxies, and LoadBalancer Services, so the instance keeps its IP addresses.
  • The cert-manager issuers, so certificates keep being issued and renewed.

The migration removes:

  • The bundled Prometheus and its metrics history. A GitLabCore resource always turns it off.
  • The other volume claims the GitLab resource owns, such as the Toolbox scratch volumes.
  • The app.kubernetes.io labels the Operator adds to every object of a GitLab resource. The labels your GitLab resource sets itself stay.

The command lists what it removes before it changes anything.

How the command drafts the GitLabCore resource

The command drafts a GitLabCore resource that renders the same chart values as the GitLab resource:

  • spec.version pins the chart version the GitLab resource runs, with the Static type. To follow GitLab releases after the migration, change the version type.
  • A setting moves into a structured field, such as spec.domain, only when the chart values stay the same. Every other setting stays in spec.chart.values.
  • Custom certificate authorities (global.certificates.customCAs) move into spec.certificates. A list the field cannot hold stays in spec.chart.values, and the command lists it under Trust:.
  • The Gateway API setup stays in the chart values. The command leaves spec.networking unset, because its modes would change the Gateway the instance runs on.
  • The Operator generates the shared Secrets through a GitLabSecrets resource instead of the shared secrets Job. It keeps every existing Secret, and adds only missing keys.
  • OpenBao and the AI gateway stay off, as they were under the GitLab resource.

The command prints every difference from the GitLab resource, grouped by topic, such as Monitoring:, Persistence:, Secrets:, or Labels:.

Prerequisites

  • An Operator with Bridge enabled (bridge.enabled set to true) that watches the namespace of the GitLab resource, and has finished rolling out. For more information, see Try Bridge in a development environment.
  • The v2alpha1 custom resource definitions in the cluster.
  • The kubectl bridge plugin, built from the same branch as the Operator image. The draft uses the chart defaults of the plugin version. If the versions of the plugin and the Operator cannot be compared, the command warns. If they can be compared and differ, the command stops.
  • A GitLab resource that runs GitLab chart 10.5.0 or later, is in the Running phase with the Available condition, and is not upgrading.
  • The GitLab resource does not use the bundled NGINX Ingress (nginx-ingress.enabled or nginx-ingress-geo.enabled), because a GitLabCore resource always turns it off.
  • The GitLab resource does not request cert-manager certificates for its Ingresses (global.ingress.configureCertmanager).
  • No GitLabCore resource of the same name exists in the namespace.
  • Your kubeconfig identity has the permissions the command needs.
  • If Argo CD, Flux, or Helm manages the GitLab resource, remove it from that tool first. Otherwise, the tool creates the GitLab resource again, and two Operator controllers compete for the instance.

Optional. Back up the instance before you migrate it.

Permissions the command needs

The command acts as your kubeconfig identity. In the namespace of the GitLab resource, it needs:

ResourcesVerbs
gitlabs.apps.gitlab.comget, patch, delete
gitlabcores.apps.gitlab.comget, create
ConfigMapsget, create
Pods and PersistentVolumeClaimslist
Services, and the Gateways, EnvoyProxies, and cert-manager Issuers of the instancelist, patch

To check the Operator, the command also lists Deployments in all namespaces. Without that permission, the command cannot check the Operator, and warns instead.

Review the draft

Run the command with --dry-run. The command checks the instance, prints the GitLabCore resource it drafts, and changes nothing:

shell
kubectl bridge migrate <gitlab_name> --namespace <namespace> --dry-run

The output lists:

  • The structured fields the draft moved settings into.
  • The differences from the GitLab resource.
  • The warnings you must accept, such as the volume claims the delete removes.
  • The blockers. The command does not migrate an instance while any blocker remains.

Resolve every blocker, and run the command again until the output lists none.

Migrate the instance

  1. Run the command without --dry-run:

    shell
    kubectl bridge migrate <gitlab_name> --namespace <namespace>
  2. Accept each warning, then confirm the delete of the GitLab resource.

The command then:

  1. Stores the GitLab resource, its UID, and the draft in the ConfigMap <gitlab_name>-v1beta1-migration.
  2. Adds the annotation apps.gitlab.com/migrate-to: GitLabCore to the GitLab resource, and waits until the resource reports the Migrating condition. From then on, the Operator stops applying the GitLab resource.
  3. Removes the owner reference to the GitLab resource from the objects the migration keeps.
  4. Deletes the GitLab resource, and waits until the resource and the pods of the instance are gone.
  5. Creates the GitLabCore resource, and waits until it is available.

To skip the prompts, for example in a script, add --yes. By default, the command waits up to 30 minutes for the GitLab resource to be deleted, and again for the GitLabCore resource to become available. To change that limit, use --timeout.

For all options, run kubectl bridge migrate --help.

After the migration, the ConfigMap stays in the namespace. You need it to hand the instance back.

Continue an interrupted migration

If the command stops, for example at a timeout, it undoes nothing. Run the same command again. The command continues from the ConfigMap, and asks for confirmation again while the GitLab resource still exists.

Cancel a migration before the delete

While the GitLab resource still exists, you can hand the instance back to it. Remove the annotation, and delete the ConfigMap:

shell
kubectl annotate gitlab <gitlab_name> --namespace <namespace> apps.gitlab.com/migrate-to-
kubectl delete configmap <gitlab_name>-v1beta1-migration --namespace <namespace>

The Operator removes the Migrating condition and manages the GitLab resource again.

Hand the instance back to the GitLab resource

The command does not hand a migrated instance back. The ConfigMap keeps the GitLab resource as it was before the migration, so you can restore it by hand.

Deleting the GitLabCore resource deletes every object it manages, except volume claims and Secrets. That includes the Gateways and LoadBalancer Services it took over, so the IP addresses of the instance change. The cert-manager issuers the migration kept stay.

To hand the instance back:

  1. Save the GitLab resource from the ConfigMap:

    shell
    kubectl get configmap <gitlab_name>-v1beta1-migration --namespace <namespace> \
      --output jsonpath='{.data.gitlab\.yaml}' > gitlab.yaml
  2. Delete the GitLabCore resource, and wait until it is gone:

    shell
    kubectl delete gitlabcore <gitlab_name> --namespace <namespace> --wait
  3. Create the GitLab resource again:

    shell
    kubectl apply --filename gitlab.yaml
  4. Delete the ConfigMap, so that a later migration starts from the new GitLab resource:

    shell
    kubectl delete configmap <gitlab_name>-v1beta1-migration --namespace <namespace>