• Русский
  • Миграция данных из GitLab 14.0.12 в 17.8.z

    Решаемая проблема

    Версии 3.16 и 3.18 поддерживают версии GitLab, которые отстают от официальных версий. Обновление GitLab до последней официальной версии требует более 10 обновлений подряд. После обновления до версии 4.0 продукт не предоставляет автоматического обновления до 17.8.z. В этом решении описывается, как выполнить миграцию данных с версии 14.0.12 на 17.8.z.

    Учитывая большой разрыв между версиями, для обновления используется подход миграции данных.

    Терминология

    ТерминОбъяснение
    all-in-one GitLabВсе компоненты GitLab упакованы и развернуты вместе в одном контейнере или Pod. Используется для быстрого обновления версий.
    platform-deployed GitLabGitLab развертывается и управляется платформой с помощью Operator, компоненты разделены.

    Обзор процесса

    Путь миграции данных

    Согласно официальной документации по пути обновления, путь миграции данных следующий:

    • 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

    В конце необходимо сделать резервную копию данных из версии 17.8.1 и импортировать её в экземпляр platform-deployed версии 17.8.z для завершения миграции данных.

    Процесс миграции данных

    Сделайте резервную копию platform-deployed GitLab и восстановите её в GitLab, развернутом с использованием образа all-in-one, затем обновите до 17.8.1 с помощью образа all-in-one, и наконец восстановите резервную копию данных в экземпляр platform-deployed версии 17.8.z.

    1. Сделайте резервную копию экземпляра platform-deployed GitLab 14.0.12.
    2. Восстановите резервную копию в развертывание all-in-one GitLab 14.0.12.
    3. Выполните поэтапное обновление развертывания all-in-one до GitLab 17.8.1.
    4. Сделайте резервную копию обновленного экземпляра all-in-one GitLab 17.8.1.
    5. Восстановите резервную копию из all-in-one 17.8.1 в экземпляр platform-deployed GitLab 17.8.z.
    TIP

    Для последних версий GitLab и оператора смотрите Release Note.

    Длительность миграции

    Процесс миграции включает операции резервного копирования и восстановления базы данных и репозиториев:

    • Чем больше база данных, тем дольше миграция.
    • Большое количество репозиториев или крупные отдельные репозитории значительно увеличивают время.
    • Производительность хранилища также влияет на эффективность — рекомендуется использовать topolvm для лучшей производительности.

    Тестовая конфигурация:

    • Один большой репозиторий (~600 МБ), остальные — небольшие начальные репозитории
    • Экземпляр GitLab: 6700 задач, 3600 merge requests
    Шаг миграцииКлючевой фактор1 000 репозиториев10 000 репозиториев
    Резервное копирование platform-deployed GitLab 14.0.12Размер и количество репозиториев10 мин30 мин
    Восстановление в all-in-one GitLab 14.0.12Размер и количество репозиториев20 мин1 час
    Поэтапное обновление до GitLab 17.8.1Размер базы данных1 ч 30 мин1 ч 40 мин
    Резервное копирование all-in-one GitLab 17.8.1Размер и количество репозиториев3 мин10 мин
    Восстановление в platform-deployed GitLabРазмер и количество репозиториев30 мин1 час

    Предварительные требования

    1. Установите kubectl (>=1.30.0) и yq (>=4.45.0) на хосте выполнения.

      kubectl version --client
      yq --version
      
      # Вывод:
      # Client Version: v1.30.0
      # Kustomize Version: v5.4.2
      # yq (https://github.com/mikefarah/yq/) version v4.45.4
    2. Настройте переменные окружения:

      # Замените на имя старого CR GitLab
      export GITLAB_NAME=<old gitlab name>
      export GITLAB_NAMESPACE=<gitlab deploy namespace>
    3. Подготовьте PVC, необходимые для обновления. Они должны быть созданы в том же namespace, что и старый экземпляр GitLab:

      TIP

      Простой способ оценить необходимый размер хранилища для исходного экземпляра — сложить размеры PVC, используемых базой данных и компонентами Gitaly.

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: backup-pvc
        namespace: ${GITLAB_NAMESPACE}
      spec:
        accessModes:
          - ReadWriteMany
        resources:
          requests:
            storage: 40Gi
        storageClassName: ceph
      ---
      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: upgrade-pvc
        namespace: ${GITLAB_NAMESPACE}
      spec:
        accessModes:
          - ReadWriteMany
        resources:
          requests:
            storage: 20Gi
        storageClassName: ceph
        volumeMode: Filesystem
      1. backup-pvc: Используется для хранения архивов резервных копий. Рекомендуемый объем — в два раза больше размера исходного экземпляра.
      2. Замените на имя storage class в вашем кластере.
      3. upgrade-pvc: Используется для хранения данных GitLab во время поэтапного обновления. Рекомендуется выделить объем, равный сумме общего размера исходного экземпляра и трёхкратного размера базы данных.
      4. Замените на имя storage class в вашем кластере.
    4. Подготовьте образы, необходимые для обновления. Скачайте каждый образ из приложений и загрузите их в репозиторий образов, к которому имеет доступ кластер с развертыванием GitLab. Ссылки для скачивания образов:

      Китайский регион
      Другие регионы
      # amd образы
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-14-0-12-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-14-3-6-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-14-9-5-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-14-10-5-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-15-0-5-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-15-4-6-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-15-11-13-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-16-3-8-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-16-7-9-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-16-11-10-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-17-3-6-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-17-5-5-amd.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-17-8-1-amd.tgz
      
      # arm образы
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-14-0-12-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-14-3-6-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-14-9-5-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-14-10-5-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-15-0-5-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-15-4-6-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-15-11-13-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-16-3-8-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-16-7-9-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-16-11-10-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-17-3-6-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-17-5-5-arm.tgz
      https://cloud.alauda.cn/attachments/knowledge/242090509/gitlab-ce-17-8-1-arm.tgz
    5. Подготовьте скрипты, необходимые для обновления.

      Выполните следующую команду для генерации четырёх скриптов:

    • check_gitlab.sh: Проверка готовности pod GitLab.
    • finalize_migrations.sql: Завершение миграций.
    • monitor_gitlab.sh: Мониторинг pod GitLab для проверки завершения миграции данных.
    • rolling_upgrade.sh: Поэтапное обновление экземпляров GitLab один за другим.
    Команда
    Сгенерированные скрипты
    cat << 'EOF' > check_gitlab.sh
    #!/bin/bash
    
    gitlab_pod=$1
    port=${2:-30855}
    
    log() {
        echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"
    }
    
    log "Starting monitoring script for GitLab pod: ${gitlab_pod} on port: ${port}"
    
    while true; do
      curl_result=$(kubectl -n $GITLAB_NAMESPACE exec ${gitlab_pod} -- curl -s localhost:${port} | grep "You are being")
      if [[ -z "${curl_result}" ]]; then
          log "HTTP not ready. Retrying in 10 seconds..."
          sleep 10
          continue
      fi
    
      log "GitLab is ready"
      break
    done
    EOF
    
    cat << 'EOF' > finalize_migrations.sql
    select concat(
      'gitlab-rake gitlab:background_migrations:finalize[',
      job_class_name, ',',
      table_name, ',',
      column_name, $$,'$$,
      REPLACE(cast(job_arguments as text), ',', $$\,$$),
      $$']$$
    )
    from batched_background_migrations WHERE status NOT IN(3, 6);
    EOF
    
    cat << 'EOF' > monitor_gitlab.sh
    #!/bin/bash
    
    gitlab_pod=$1
    port=${2:-30855}
    
    log() {
        echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"
    }
    
    log "Starting monitoring script for GitLab pod: ${gitlab_pod} on port: ${port}"
    
    while true; do
      curl_result=$(kubectl -n $GITLAB_NAMESPACE exec ${gitlab_pod} -- curl -s localhost:${port} | grep "You are being")
      if [[ -z "${curl_result}" ]]; then
          log "HTTP check not ready. Retrying in 10 seconds..."
          sleep 10
          continue
      fi
    
      migration_result=$(kubectl -n $GITLAB_NAMESPACE exec ${gitlab_pod} -- gitlab-psql -c "SELECT job_class_name, table_name,  column_name, job_arguments FROM batched_background_migrations WHERE status NOT IN(3, 6);" | grep "(0 rows)")
    
      if [[ -z "${migration_result}" ]]; then
          log "Database migration is running. Retrying in 10 seconds..."
          sleep 10
          continue
      fi
    
      log "GitLab is ready, all migrations are done"
      break
    done
    EOF
    
    cat << 'EOF' > rolling_upgrade.sh
    #!/bin/bash
    
    image=$(kubectl -n $GITLAB_NAMESPACE get deployment gitlab -o jsonpath='{.spec.template.spec.containers[?(@.name=="gitlab")].image} ')
    
    versions=(
      14.0.12-ce.0
      14.3.6-ce.0
      14.9.5-ce.0
      14.10.5-ce.0
      15.0.5-ce.0
      15.4.6-ce.0
      15.11.13-ce.0
      16.3.8-ce.0
      16.7.9-ce.0
      16.11.10-ce.0
      17.3.6-ce.0
      17.5.5-ce.0
      17.8.1-ce.0
    )
    
    STATE_FILE="upgrade_state.log"
    touch "$STATE_FILE"
    
    is_done() {
      grep -Fxq "$1" "$STATE_FILE"
    }
    
    mark_done() {
      echo "$1" >> "$STATE_FILE"
    }
    
    for version in "${versions[@]}"; do
      if is_done "$version"; then
        echo "Version ${version} already processed, skipping..."
        continue
      fi
    
      echo "Upgrading to ${version}..."
      new_image="${image%:*}:${version}"
      kubectl -n $GITLAB_NAMESPACE set image deployment/gitlab gitlab=$new_image
    
      echo "Waiting for the GitLab pod to start..."
      sleep 10
      kubectl -n $GITLAB_NAMESPACE wait deploy gitlab --for condition=available --timeout=3000s
      sleep 10
      kubectl -n $GITLAB_NAMESPACE wait pod -l deploy=gitlab --for=condition=Ready --timeout=3000s
    
      new_pod_name=$(kubectl -n $GITLAB_NAMESPACE get po -l deploy=gitlab --sort-by=.metadata.creationTimestamp  --field-selector=status.phase=Running -o jsonpath='{.items[-1].metadata.name}')
      echo "Waiting for GitLab to be ready..."
      bash check_gitlab.sh $new_pod_name
    
      echo "Waiting for migrations to finish..."
      kubectl -n $GITLAB_NAMESPACE cp finalize_migrations.sql $new_pod_name:/tmp/finalize_migrations.sql
      for i in {1..10}; do
        echo "Running migration tasks (attempt $i/10)..."
        if kubectl -n $GITLAB_NAMESPACE exec -ti $new_pod_name -- bash -c "gitlab-psql -t -A -f /tmp/finalize_migrations.sql > /tmp/run_migration_tasks.sh && xargs -d \"\n\" -P 3 -I {} bash -c \"{}\" < /tmp/run_migration_tasks.sh"; then
          echo "Migration tasks completed successfully"
          break
        fi
        sleep 30
      done
      bash monitor_gitlab.sh $new_pod_name
      echo "Upgraded to ${version} successfully"
      mark_done "$version"
    done
    
    echo "All upgrades completed successfully!"
    EOF

    Резервное копирование platform-deployed GitLab 14.0.12

    1. Включите компонент task-runner в GitLab 14 для выполнения команд резервного копирования

      Команды для Platform < 3.18.0
      Команды для Platform 3.18.0+
      Вывод
      # сформировать репозиторий образа и тег для task-runner на основе образа gitaly
      image=$(kubectl get pod ${GITLAB_NAME}-gitaly-0 -n $GITLAB_NAMESPACE -o jsonpath='{.spec.containers[0].image}')
      tag=${image##*:}
      registry=${image%%/*}
      
      echo "registry: ${registry}"
      echo "tag: ${tag}"
      
      kubectl patch gitlabofficials.operator.devops.alauda.io "${GITLAB_NAME}" \
        -n "$GITLAB_NAMESPACE" \
        --type=merge \
        -p "$(cat <<EOF
      {
        "spec": {
          "helmValues": {
            "gitlab": {
              "task-runner": {
                "enabled": "true",
                "image": {
                  "repository": "${registry}/devops/gitlab-org/build/cng/gitlab-task-runner-ce",
                  "tag": "${tag}"
                },
                "resources": {
                  "limits": {
                    "cpu": "2",
                    "memory": "4G"
                  }
                }
              }
            }
          }
        }
      }
      EOF
      )"
      
      # Ожидание доступности развертывания task-runner
      echo "Waiting for the task-runner deployment to be available..."
      sleep 60
      
      # Проверка существования развертывания ${GITLAB_NAME}-task-runner
      kubectl wait deploy ${GITLAB_NAME}-task-runner -n $GITLAB_NAMESPACE --for condition=available --timeout=3000s
      kubectl get deploy -n $GITLAB_NAMESPACE ${GITLAB_NAME}-task-runner
    2. Переведите GitLab 14 в режим только для чтения

      Команда
      Вывод
      kubectl patch deploy ${GITLAB_NAME}-webservice-default -n $GITLAB_NAMESPACE --type='merge' -p='{"metadata":{"annotations":{"skip-sync":"true"}}}'
      kubectl patch deploy ${GITLAB_NAME}-sidekiq-all-in-1-v1 -n $GITLAB_NAMESPACE --type='merge' -p='{"metadata":{"annotations":{"skip-sync":"true"}}}'
      kubectl scale deploy ${GITLAB_NAME}-webservice-default -n $GITLAB_NAMESPACE --replicas 0
      kubectl scale deploy ${GITLAB_NAME}-sidekiq-all-in-1-v1 -n $GITLAB_NAMESPACE --replicas 0
    3. Примените патч к backup PVC для task-runner GitLab 14. PVC должен называться backup-pvc.

      Команда
      Вывод
      kubectl patch deploy ${GITLAB_NAME}-task-runner -n $GITLAB_NAMESPACE --type='json' -p='
      [
        {
          "op": "add",
          "path": "/metadata/annotations/skip-sync",
          "value": "true"
        },
        {
          "op": "replace",
          "path": "/spec/template/spec/volumes/1",
          "value": {"name": "task-runner-tmp", "persistentVolumeClaim": {"claimName": "backup-pvc"}}
        }
      ]'
      
      echo "Waiting for the task-runner deployment to be available..."
      sleep 60
      
      # Проверка существования развертывания ${GITLAB_NAME}-task-runner
      kubectl wait deploy ${GITLAB_NAME}-task-runner -n $GITLAB_NAMESPACE --for condition=available --timeout=3000s
      kubectl get deploy -n $GITLAB_NAMESPACE ${GITLAB_NAME}-task-runner
    4. Сделайте резервную копию данных GitLab 14

      Команда
      Вывод
      pod_name=$(kubectl get po -n $GITLAB_NAMESPACE -l app=task-runner,release=${GITLAB_NAME} -o jsonpath='{.items[0].metadata.name}')
      kubectl exec -ti -n "$GITLAB_NAMESPACE" $pod_name -- gitlab-rake gitlab:backup:create SKIP=repositories
      
      # Добавьте права на файл резервной копии.
      kubectl exec -ti -n "$GITLAB_NAMESPACE" $pod_name -- bash -c '
      chmod 777 /srv/gitlab/tmp/backups/*_gitlab_backup.tar
      ls -lh /srv/gitlab/tmp/backups
      '

      Сделайте резервную копию rails-secret, выполнив следующую команду, которая сохранит rails-secret в файл gitlab14-rails-secret.yaml в текущем каталоге.

      kubectl get secrets -n ${GITLAB_NAMESPACE} ${GITLAB_NAME}-rails-secret -o jsonpath="{.data['secrets\.yml']}" | base64 --decode | yq -o yaml > gitlab14-rails-secret.yaml
    5. Удалите компонент task-runner после завершения резервного копирования.

      Команда
      Вывод
      kubectl patch gitlabofficials.operator.devops.alauda.io ${GITLAB_NAME} -n $GITLAB_NAMESPACE --type='merge' -p='
      {
        "spec": {
          "helmValues": {
            "gitlab": {
              "task-runner": null
            }
          }
        }
      }'
      
      echo "Waiting for the task-runner deployment to be removed..."
      sleep 30
      
      kubectl get po -n "$GITLAB_NAMESPACE" -l app=task-runner,release=${GITLAB_NAME}

    Восстановление резервной копии в развертывание all-in-one 14.0.12

    1. Используйте образ all-in-one для развертывания GitLab 14.0.12.

      Сначала установите переменную окружения NODE_IP для доступа к экземпляру all-in-one GitLab через этот IP и порт NodePort.

      export NODE_IP=<node_ip>
      export GITLAB_IMAGE=<registry-host>/gitlab/gitlab-ce:14.0.12-ce.0

      Создайте экземпляр all-in-one GitLab.

      Команда
      Вывод
      kubectl apply -f - <<EOF
      apiVersion: v1
      kind: Service
      metadata:
        name: gitlab-http-nodeport
        namespace: ${GITLAB_NAMESPACE}
      spec:
        ports:
          - appProtocol: tcp
            name: web
            port: 30855
            protocol: TCP
            targetPort: 30855
            nodePort: 30855
        selector:
          deploy: gitlab
        type: NodePort
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: gitlab
        namespace: ${GITLAB_NAMESPACE}
      spec:
        progressDeadlineSeconds: 600
        replicas: 1
        revisionHistoryLimit: 10
        selector:
          matchLabels:
            deploy: gitlab
        strategy:
          rollingUpdate:
            maxSurge: 1
            maxUnavailable: 1
          type: RollingUpdate
        template:
          metadata:
            labels:
              deploy: gitlab
          spec:
            affinity: {}
            containers:
              - env:
                  # Внешний адрес доступа к all-in-one gitlab, замените на IP и nodeport порта узла кластера
                  - name: GITLAB_OMNIBUS_CONFIG
                    value: external_url 'http://${NODE_IP}:30855'
                image: ${GITLAB_IMAGE} # Можно заменить на доступный образ
                imagePullPolicy: IfNotPresent
                name: gitlab
                ports:
                  - containerPort: 30855
                    name: http
                    protocol: TCP
                  - containerPort: 2424
                    name: ssh
                    protocol: TCP
                resources:
                  limits:
                    cpu: "8"
                    memory: 8Gi
                  requests:
                    cpu: 4
                    memory: "4Gi"
                securityContext:
                  privileged: true
                terminationMessagePath: /dev/termination-log
                terminationMessagePolicy: File
                volumeMounts:
                  - mountPath: /dev/shm
                    name: dshm
                  - mountPath: /var/opt/gitlab/backups
                    name: backup
                    subPath: backups
                  - mountPath: /etc/gitlab
                    name: gitlab-upgrade-data
                    subPath: config
                  - mountPath: /var/log/gitlab
                    name: gitlab-upgrade-data
                    subPath: logs
                  - mountPath: /var/opt/gitlab
                    name: gitlab-upgrade-data
                    subPath: data
            dnsPolicy: ClusterFirst
            restartPolicy: Always
            schedulerName: default-scheduler
            securityContext: {}
            terminationGracePeriodSeconds: 30
            volumes:
              - name: dshm
                emptyDir:
                  medium: Memory
                  sizeLimit: 512Mi
              - name: backup
                persistentVolumeClaim:
                  claimName: backup-pvc
              - name: gitlab-upgrade-data
                persistentVolumeClaim:
                  claimName: upgrade-pvc
      EOF

      Проверьте успешный запуск экземпляра all-in-one GitLab.

      Команда
      Вывод
      pod_name=$(kubectl get po -l deploy=gitlab -n $GITLAB_NAMESPACE -o jsonpath='{.items[0].metadata.name}')
      bash check_gitlab.sh $pod_name
    2. Измените содержимое rails secret в all-in-one GitLab. Замените поля secret_key_base, otp_key_base, db_key_base, openid_connect_signing_key, ci_jwt_signing_key соответствующими значениями из сохранённого rails secret GitLab 14.

      Команда
      Вывод
      # Скопировать gitlab-secrets.json локально
      pod_name=$(kubectl get po -l deploy=gitlab -n $GITLAB_NAMESPACE -o jsonpath='{.items[0].metadata.name}')
      kubectl -n $GITLAB_NAMESPACE cp $pod_name:/etc/gitlab/gitlab-secrets.json all-in-one-gitlab-secrets.json
      
      # Заменить данными из gitlab 14 rails-secret.
      KEYS=(secret_key_base otp_key_base db_key_base openid_connect_signing_key ci_jwt_signing_key)
      for key in "${KEYS[@]}"; do
        echo "Replace ${key} ..."
        export KEY_VALUE=$(yq eval -r --unwrapScalar=false ".production.${key}" gitlab14-rails-secret.yaml)
        yq eval ".gitlab_rails.${key} = env(KEY_VALUE)" all-in-one-gitlab-secrets.json -i
      done
      
      # Скопировать gitlab-secrets.json обратно в pod
      kubectl -n $GITLAB_NAMESPACE cp all-in-one-gitlab-secrets.json $pod_name:/etc/gitlab/gitlab-secrets.json

      Отключите ненужные компоненты.

      cat <<EOF >> gitlab.rb
      prometheus['enable'] = false
      gitlab_kas['enable'] = false
      redis_exporter['enable'] = false
      gitlab_exporter['enable'] = false
      postgres_exporter['enable'] = false
      sidekiq['enable'] = false
      EOF
      
      # Скопировать gitlab.rb в pod
      kubectl -n $GITLAB_NAMESPACE cp gitlab.rb $pod_name:/etc/gitlab/gitlab.rb
    3. Синхронизируйте данные Gitaly с all-in-one GitLab

      Tip

      Этот шаг необходимо выполнять на узле, где запущен pod all-in-one GitLab.

      Сначала определите пути монтирования на узле для PVC компонента Gitaly исходного GitLab (названного repo-data-${GITLAB_NAME}-gitaly-0) и PVC upgrade-pvc, используемого all-in-one GitLab.

      Используйте команду rsync для эффективного копирования данных Gitaly с исходного PVC в upgrade-pvc экземпляра all-in-one GitLab.

      Tip

      Используйте rsync вместо scp — это значительно быстрее и эффективнее для такого типа передачи данных.

      Получите тип хранилища исходного экземпляра

      persistence_type=$(kubectl get GitlabOfficial.operator.devops.alauda.io -n $GITLAB_NAMESPACE $GITLAB_NAME -o jsonpath='{.spec.persistence.type}')
      echo "gitlab persistence type: $persistence_type"
      Развернуто с LocalPath
      Развернуто с PVC или StorageClass
      origin_gitaly_local_mount_path=$(kubectl get GitlabOfficial.operator.devops.alauda.io -n $GITLAB_NAMESPACE $GITLAB_NAME -o jsonpath='{.spec.persistence.location.path}')/gitlab
      origin_gitaly_node_ip=<origin_gitaly_node_ip>
      all_in_one_upgrade_pvc_mount_path=<all_in_one_gitaly_mount_path>
      
      # Выполните эту команду на узле, где расположен pod all-in-one.
      rsync -avh --chown=998:998 ${origin_gitaly_node_ip}:${origin_gitaly_local_mount_path}/ ${all_in_one_upgrade_pvc_mount_path}/data/git-data/repositories/
      
      # Проверьте владельца данных репозитория.
      ls -alh ${all_in_one_upgrade_pvc_mount_path}/data/git-data/repositories

      Перезапустите pod и дождитесь его запуска.

      Команда
      Вывод
      # Перезапуск pod
      kubectl delete po -l deploy=gitlab -n $GITLAB_NAMESPACE
      
      echo "Waiting for the pod to start..."
      sleep 10
      
      pod_name=$(kubectl get po -l deploy=gitlab -n $GITLAB_NAMESPACE -o jsonpath='{.items[0].metadata.name}')
      bash check_gitlab.sh $pod_name
    4. Восстановите резервные данные.

      TIP

      В процессе восстановления могут возникать ошибки, связанные с базой данных, например:

      • ERROR: role "xxx" does not exist
      • ERROR: function xxx does not exist
      • ERROR: permission denied to create extension "pg_stat_statements"
      • ERROR: could not open extension control file

      Эти ошибки можно игнорировать, подробности доступны по ссылке (https://gitlab.com/gitlab-org/gitlab/-/issues/266988).

      Команда
      Вывод
      # Перевести gitlab в режим только для чтения
      pod_name=$(kubectl get po -l deploy=gitlab -n $GITLAB_NAMESPACE -o jsonpath='{.items[0].metadata.name}')
      kubectl -n $GITLAB_NAMESPACE exec -ti $pod_name -- gitlab-ctl stop puma
      kubectl -n $GITLAB_NAMESPACE exec -ti $pod_name -- gitlab-ctl stop sidekiq
      
      # Подтвердить остановку puma и sidekiq
      kubectl -n $GITLAB_NAMESPACE exec -ti $pod_name -- gitlab-ctl status
      
      # Выполнить восстановление
      backup_id=$(kubectl -n $GITLAB_NAMESPACE exec -ti $pod_name -- bash -c 'ls /var/opt/gitlab/backups/*14.0.12_gitlab_backup.tar | head -n1 | sed "s|.*/\([0-9_]*_14\.0\.12\)_gitlab_backup\.tar|\1|"')
      echo "Backup ID: ${backup_id}"
      
      echo "This step will prompt you multiple times to confirm whether to continue. \nPlease select \"yes\" each time to proceed."
      kubectl -n $GITLAB_NAMESPACE exec -ti $pod_name -- bash -c 'gitlab-backup restore BACKUP=${backup_id}'

      Перезапустите pod и дождитесь его запуска, затем выполните gitlab-rake gitlab:check SANITIZE=true для проверки целостности GitLab.

      Команда
      Вывод
      # Перезапуск pod
      kubectl delete po -l deploy=gitlab -n $GITLAB_NAMESPACE
      
      # Ожидание запуска pod
      sleep 10
      pod_name=$(kubectl get po -l deploy=gitlab -n $GITLAB_NAMESPACE -o jsonpath='{.items[0].metadata.name}')
      bash check_gitlab.sh $pod_name
      
      kubectl -n $GITLAB_NAMESPACE exec -ti $pod_name -- gitlab-rake gitlab:check SANITIZE=true

      Войдите в GitLab, чтобы проверить успешность восстановления экземпляра (пароль пользователя root остаётся прежним), и выполните следующую команду для получения адреса доступа к экземпляру all-in-one.

      Команда
      Вывод
      kubectl -n $GITLAB_NAMESPACE get pod -l deploy=gitlab -o yaml | grep external_url

    Поэтапное обновление all-in-one GitLab до 17.8.1

    Запустите скрипт rolling_upgrade.sh, который обновит экземпляр all-in-one поэтапно до версии 17.8.1 согласно пути обновления.

    bash -x rolling_upgrade.sh
    Tip

    Во время поэтапного обновления база данных может автоматически перезапускаться. В результате скрипт может показывать ошибки вида:

    connections on Unix domain socket "/var/opt/gitlab/postgresql/.s.PGSQL.5432"

    Это ожидаемое поведение — скрипт автоматически повторит попытку и продолжит работу.

    После завершения скрипта войдите в веб-интерфейс GitLab, чтобы проверить, что версия экземпляра — 17.8.1, и убедитесь, что данные целы, включая кодовые репозитории, пользователей, задачи, merge requests и т.д.

    Резервное копирование данных из экземпляра all-in-one 17.8.1

    Остановите сервис экземпляра all-in-one и сделайте резервную копию данных. Файлы резервных копий сохранятся в каталоге /var/opt/gitlab/backups/.

    Команда
    Вывод
    pod_name=$(kubectl get po -l deploy=gitlab -n $GITLAB_NAMESPACE -o jsonpath='{.items[0].metadata.name}')
    kubectl -n $GITLAB_NAMESPACE exec -ti $pod_name -- bash -c '
    gitlab-ctl stop puma
    gitlab-ctl stop sidekiq
    gitlab-ctl status
    gitlab-rake gitlab:backup:create
    '

    Остановите сервис экземпляра all-in-one.

    Команда
    Вывод
    kubectl scale deploy gitlab -n $GITLAB_NAMESPACE --replicas 0

    Восстановление резервной копии all-in-one в platform-deployed 17.8.z

    Namespace нового экземпляра gitlab

    Namespace нового экземпляра gitlab должен совпадать с namespace старого экземпляра.

    1. Следуйте Руководству по развертыванию GitLab, чтобы развернуть новый экземпляр GitLab 17.8.z с помощью оператора.

      Tip
      1. Новый экземпляр должен находиться в том же namespace, что и старый.
      2. Метод доступа к новому экземпляру не должен конфликтовать со старым, например, доменное имя, nodeport и т.д.

      После развертывания нового экземпляра установите переменную окружения с именем нового экземпляра:

      export NEW_GITLAB_NAME=<name of the new GitLab instance>
    2. Включите компонент toolbox для нового экземпляра GitLab.

      kubectl patch gitlabofficial.operator.alaudadevops.io ${NEW_GITLAB_NAME} -n $GITLAB_NAMESPACE --type='merge' -p='
      {
        "spec": {
          "helmValues": {
            "gitlab": {
              "toolbox": {
                "enabled": true,
                "resources": {
                  "limits": {
                    "cpu": 2,
                    "memory": "4G"
                  }
                }
              }
            }
          }
        }
      }'

      Дождитесь завершения повторного развертывания экземпляра.

      Команда
      Вывод
      kubectl get po -l app=toolbox,release=${NEW_GITLAB_NAME} -n $GITLAB_NAMESPACE
    3. Восстановите резервную копию в GitLab 17.8.z, развернутый оператором

      TIP

      В процессе восстановления могут возникать ошибки, связанные с базой данных, например:

      • ERROR: role "xxx" does not exist
      • ERROR: function xxx does not exist
      • ERROR: must be owner of extension

      Эти ошибки можно игнорировать, подробности доступны по ссылке (https://gitlab.com/gitlab-org/gitlab/-/issues/266988).

      Закройте внешний доступ к новому экземпляру gitlab 17.8.z и примените патч к компоненту toolbox для монтирования backup pvc.

      Команда
      Вывод
      kubectl patch deploy ${NEW_GITLAB_NAME}-webservice-default -n $GITLAB_NAMESPACE --type='merge' -p='{"metadata":{"annotations":{"skip-sync":"true"}}}'
      kubectl patch deploy ${NEW_GITLAB_NAME}-sidekiq-all-in-1-v2 -n $GITLAB_NAMESPACE --type='merge' -p='{"metadata":{"annotations":{"skip-sync":"true"}}}'
      kubectl scale deploy ${NEW_GITLAB_NAME}-webservice-default -n $GITLAB_NAMESPACE --replicas 0
      kubectl scale deploy ${NEW_GITLAB_NAME}-sidekiq-all-in-1-v2 -n $GITLAB_NAMESPACE --replicas 0
      
      # Изменить toolbox, примонтировать backup pvc к toolbox
      kubectl patch deploy ${NEW_GITLAB_NAME}-toolbox -n $GITLAB_NAMESPACE -p='{"metadata":{"annotations":{"skip-sync":"true"}}}'
      kubectl patch deploy ${NEW_GITLAB_NAME}-toolbox -n $GITLAB_NAMESPACE --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/volumes/1", "value": {"name": "toolbox-tmp", "persistentVolumeClaim": {"claimName": "backup-pvc"}}}]'

      Дождитесь готовности pod toolbox, затем восстановите резервную копию в новый экземпляр GitLab.

      Команда
      Вывод
      toolbox_pod_name=$(kubectl get po -n $GITLAB_NAMESPACE -l release=$NEW_GITLAB_NAME,app=toolbox -o jsonpath='{.items[0].metadata.name}')
      
      # Сделать резервную копию старого файла резервной копии
      kubectl -n $GITLAB_NAMESPACE exec -ti $toolbox_pod_name -- bash -c '
      mkdir -p /srv/gitlab/tmp/backup_tarballs
      mv /srv/gitlab/tmp/backups/*gitlab_backup.tar /srv/gitlab/tmp/backup_tarballs || true
      '
      
      backup_file=$(kubectl -n $GITLAB_NAMESPACE exec -ti $toolbox_pod_name -- bash -c "ls /srv/gitlab/tmp/backup_tarballs/*17.8.1_gitlab_backup.tar | head -n1 | tr -d '\r\n'")
      echo "Backup file of 17.8.1: ${backup_file}"
      
      kubectl -n $GITLAB_NAMESPACE exec -ti $toolbox_pod_name -- backup-utility --restore --skip-restore-prompt -f "file://${backup_file}"
    4. Замените rails-secret для нового экземпляра GitLab.

      Команда
      Вывод
      kubectl get secrets -n ${GITLAB_NAMESPACE} ${NEW_GITLAB_NAME}-rails-secret -o jsonpath="{.data['secrets\.yml']}" | base64 --decode | yq -o yaml > gitlab17-rails-secret.yaml
      yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' gitlab17-rails-secret.yaml gitlab14-rails-secret.yaml > final-rails-secret.yml
      kubectl create secret generic rails-secret -n ${GITLAB_NAMESPACE} --from-file=secrets.yml=final-rails-secret.yml
      
      kubectl patch gitlabofficials.operator.alaudadevops.io ${NEW_GITLAB_NAME} -n $GITLAB_NAMESPACE --type='merge' -p='
      {
        "spec": {
          "helmValues": {
            "global": {
              "railsSecrets": {
                "secret": "rails-secret"
              }
            }
          }
        }
      }'
      
      kubectl patch deploy ${NEW_GITLAB_NAME}-webservice-default -n $GITLAB_NAMESPACE --type='json' -p='[{"op":"remove","path":"/metadata/annotations/skip-sync"}]'
      kubectl patch deploy ${NEW_GITLAB_NAME}-sidekiq-all-in-1-v2 -n $GITLAB_NAMESPACE --type='json' -p='[{"op":"remove","path":"/metadata/annotations/skip-sync"}]'
      kubectl patch deploy ${NEW_GITLAB_NAME}-toolbox -n $GITLAB_NAMESPACE --type='json' -p='[{"op":"remove","path":"/metadata/annotations/skip-sync"}]'
      
      kubectl delete pod -lrelease=${NEW_GITLAB_NAME} -n $GITLAB_NAMESPACE
      kubectl scale deploy ${NEW_GITLAB_NAME}-webservice-default -n $GITLAB_NAMESPACE --replicas 1
      kubectl scale deploy ${NEW_GITLAB_NAME}-sidekiq-all-in-1-v2 -n $GITLAB_NAMESPACE --replicas 1

      Оператор автоматически повторно развернет новый экземпляр GitLab. Дождитесь завершения повторного развертывания.

    5. Проверьте корректность данных после обновления.

      • Войдите в UI GitLab в режиме администратора и проверьте корректность репозиториев и данных пользователей.
      • Выберите несколько репозиториев и проверьте работоспособность кода, веток и merge requests.
    6. Очистите неиспользуемые ресурсы:

      • При необходимости удалите старый экземпляр GitLab и старый оператор.
      • При необходимости удалите экземпляр all-in-one GitLab.

    FAQ

    Восстановление данных Uploads

    Мигрированные данные не включают аватары и вложения, поэтому новый экземпляр GitLab не может отображать этот контент. Для решения этой проблемы можно заменить PVC uploads GitLab 17.8.z на PVC, используемый в 14.0.12.

    Установите переменную окружения с именем PVC uploads:

    export UPLOADS_PVC_NAME=<name of the uploads pvc>

    Примените патч к новому экземпляру GitLab для использования PVC uploads:

    kubectl patch gitlabofficials.operator.devops.alauda.io ${NEW_GITLAB_NAME} -n $GITLAB_NAMESPACE --type='json' -p='
    {
      "spec": {
        "helmValues": {
          "global": {
            "uploads": {
              "persistence": {
                "enabled": true,
                "existingClaim": "${UPLOADS_PVC_NAME}"
              }
            }
          }
        }
      }
    }'

    Если ваш старый экземпляр GitLab использует хранилище HostPath, необходимо вручную скопировать данные из каталога uploads старого экземпляра в путь /srv/gitlab/public/uploads компонента webservice нового экземпляра.

    Как найти путь монтирования PVC на узле

    Выполните следующие шаги, чтобы определить путь монтирования PersistentVolumeClaim (PVC) на узле Kubernetes:

    1. Получите IP узла, на котором запущен pod

      kubectl -n $GITLAB_NAMESPACE get pod <pod-name> -o jsonpath='{.status.hostIP}'
      
      # Вывод:
      # 192.168.xxx.xxx
    2. Получите имя тома, связанного с PVC

      kubectl get pvc -n $GITLAB_NAMESPACE <pvc-name> -o jsonpath='{.spec.volumeName}'
      
      # Вывод:
      # pvc-359bb8d2-841e-406c-a5e7-e48bc701f610
    3. Найдите путь монтирования PVC на узле

      Войдите на узел (используя IP из шага 1), затем выполните:

      df -h | grep <pv-name>
      
      # Вывод:
      # 192.168.xx.xx:6789:/volumes/csi/csi-vol-4661bd66-a68f-42f6-b995-53bd5c3f79a8/ede3ffa1-0f77-4f44-b0e6-41ec7384484f   10G  216M  9.8G   3% /var/lib/kubelet/pods/7772096f-9b81-4698-8369-34689e36fc3a/   volumes/kubernetes.io~csi/pvc-359bb8d2-841e-406c-a5e7-e48bc701f610/mount

      Путь, указанный в последнем столбце, например:

      /var/lib/kubelet/pods/7772096f-9b81-4698-8369-34689e36fc3a/volumes/kubernetes.io~csi/pvc-359bb8d2-841e-406c-a5e7-e48bc701f610/mount

      — это директория монтирования вашего PVC на узле.