• Русский
  • Миграция данных из 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. Замените на имя класса хранилища в вашем кластере.
      3. upgrade-pvc: Используется для хранения данных GitLab во время поэтапного обновления. Рекомендуется выделять объем, равный сумме общего объема исходного экземпляра и трёхкратного размера базы данных.
      4. Замените на имя класса хранилища в вашем кластере.
    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 "Этот шаг потребует несколько раз подтвердить продолжение. \nПожалуйста, выбирайте \"yes\" для продолжения."
      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 Deployment Guide для развертывания нового экземпляра 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
      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.

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

    export UPLOADS_PVC_NAME=<name of the uploads pvc>

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

    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 на узле.