• Русский
  • Миграция данных из 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. Восстановите резервную копию в развертывание GitLab 14.0.12 с помощью all-in-one.
    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: 6,700 задач, 3,600 merge request
    Шаг миграцииКлючевой фактор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 "Запуск скрипта мониторинга для pod GitLab: ${gitlab_pod} на порту: ${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 не готов. Повтор через 10 секунд..."
          sleep 10
          continue
      fi
    
      log "GitLab готов"
      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 "Запуск скрипта мониторинга для pod GitLab: ${gitlab_pod} на порту: ${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 проверка не готова. Повтор через 10 секунд..."
          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 "Миграция базы данных выполняется. Повтор через 10 секунд..."
          sleep 10
          continue
      fi
    
      log "GitLab готов, все миграции завершены"
      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} уже обработана, пропускаем..."
        continue
      fi
    
      echo "Обновление до ${version}..."
      new_image="${image%:*}:${version}"
      kubectl -n $GITLAB_NAMESPACE set image deployment/gitlab gitlab=$new_image
    
      echo "Ожидание запуска pod GitLab..."
      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 "Ожидание готовности GitLab..."
      bash check_gitlab.sh $new_pod_name
    
      echo "Ожидание завершения миграций..."
      kubectl -n $GITLAB_NAMESPACE cp finalize_migrations.sql $new_pod_name:/tmp/finalize_migrations.sql
      for i in {1..10}; do
        echo "Выполнение миграционных задач (попытка $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 "Миграционные задачи успешно выполнены"
          break
        fi
        sleep 30
      done
      bash monitor_gitlab.sh $new_pod_name
      echo "Обновление до ${version} успешно завершено"
      mark_done "$version"
    done
    
    echo "Все обновления успешно завершены!"
    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 "Ожидание доступности развертывания task-runner..."
      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 "Ожидание доступности развертывания task-runner..."
      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 "Ожидание удаления развертывания task-runner..."
      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 "Заменяем ${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 "Тип persistence gitlab: $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 "Ожидание запуска 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
    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 "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 request и т.д.

    Резервное копирование данных из экземпляра 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 в 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 "Файл резервной копии 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 request работают корректно.
    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.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 на узле.