InfoGrab Docs

파일 내보내기 프로젝트 마이그레이션 트러블슈팅

요약

파일 내보내기를 사용하여 프로젝트를 마이그레이션하는 데 문제가 있다면 아래의 가능한 해결 방법을 참조하세요. Rails 콘솔을 사용하여 JID로 가져오기 상태 및 추가 로그에 대한 정보를 찾습니다: 인스턴스 러너 활성화가 내보낸 프로젝트와 프로젝트 가져오기 간에 일치하지 않으면 프로젝트 가져오기가 실패합니다.

파일 내보내기를 사용하여 프로젝트를 마이그레이션하는 데 문제가 있다면 아래의 가능한 해결 방법을 참조하세요.

트러블슈팅 명령#

Rails 콘솔을 사용하여 JID로 가져오기 상태 및 추가 로그에 대한 정보를 찾습니다:

Project.find_by_full_path('group/project').import_state.slice(:jid, :status, :last_error)
> {"jid"=>"414dec93f941a593ea1a6894", "status"=>"finished", "last_error"=>nil}
# 로그
grep JID /var/log/gitlab/sidekiq/current
grep "Import/Export error" /var/log/gitlab/sidekiq/current
grep "Import/Export backtrace" /var/log/gitlab/sidekiq/current
tail /var/log/gitlab/gitlab-rails/importer.log

불일치로 인한 프로젝트 가져오기 실패#

인스턴스 러너 활성화가 내보낸 프로젝트와 프로젝트 가져오기 간에 일치하지 않으면 프로젝트 가져오기가 실패합니다. 이슈 276930을 검토하고 다음 중 하나를 수행합니다:

  • 소스 및 대상 프로젝트 모두에서 인스턴스 러너가 활성화되어 있는지 확인합니다.
  • 프로젝트를 가져올 때 상위 그룹에서 인스턴스 러너를 비활성화합니다.

가져온 프로젝트에서 사용자 누락#

가져온 프로젝트에서 사용자가 가져오지 않는 경우 사용자 기여도 보존 요구사항을 참조하세요.

사용자 누락의 일반적인 이유는 사용자에 대해 공개 이메일 설정이 구성되지 않은 것입니다. 이 문제를 해결하려면 사용자에게 GitLab UI를 사용하여 이 설정을 구성하도록 요청합니다.

수동 구성이 불가능할 만큼 사용자가 너무 많은 경우, Rails 콘솔을 사용하여 모든 사용자 프로필에 공개 이메일 주소를 설정할 수 있습니다:

User.where("public_email IS NULL OR public_email = '' ").find_each do |u|
  next if u.bot?

  puts "Setting #{u.username}'s currently empty public email to #{u.email}…"
  u.public_email = u.email
  u.save!
end

대용량 저장소에 대한 가져오기 우회 방법#

최대 가져오기 크기 제한으로 인해 가져오기가 성공하지 못할 수 있습니다. 가져오기 제한을 변경할 수 없는 경우 여기에 나열된 우회 방법 중 하나를 시도할 수 있습니다.

우회 방법 옵션 1#

다음 로컬 워크플로를 사용하여 다른 가져오기 시도를 위해 저장소 크기를 일시적으로 줄일 수 있습니다:

  1. 내보내기에서 임시 작업 디렉토리를 만듭니다:

    EXPORT=<filename-without-extension>
    
    mkdir "$EXPORT"
    tar -xf "$EXPORT".tar.gz --directory="$EXPORT"/
    cd "$EXPORT"/
    git clone project.bundle
    
    # 나중에 가져올 수 있는 파일을 다시 만드는 데 방해가 되지 않도록
    mv project.bundle ../"$EXPORT"-original.bundle
    mv ../"$EXPORT".tar.gz ../"$EXPORT"-original.tar.gz
    
    git switch --create smaller-tmp-main
    
  2. 저장소 크기를 줄이려면 이 smaller-tmp-main 브랜치에서 작업합니다: 대용량 파일을 식별하고 제거하거나 대화형 리베이스 및 픽스업으로 커밋 수를 줄입니다.

    # .git/objects/pack/ 파일 크기 줄이기
    cd project
    git reflog expire --expire=now --all
    git gc --prune=now --aggressive
    
    # 가져올 수 있는 파일 다시 만들기 준비
    git bundle create ../project.bundle <default-branch-name>
    cd ..
    mv project/ ../"$EXPORT"-project
    cd ..
    
    # 가져올 수 있는 파일 다시 만들기
    tar -czf "$EXPORT"-smaller.tar.gz --directory="$EXPORT"/ .
    
  3. 이 새로운 소용량 파일을 GitLab으로 가져옵니다.

  4. 원본 저장소의 전체 클론에서 git remote set-url origin <new-url> && git push --force --all을 사용하여 가져오기를 완료합니다.

  5. 가져온 저장소의 브랜치 보호 규칙기본 브랜치를 업데이트하고, 임시 smaller-tmp-main 브랜치와 로컬 임시 데이터를 삭제합니다.

우회 방법 옵션 2#

Note

이 우회 방법은 LFS 개체를 고려하지 않습니다.

모든 변경사항을 한 번에 푸시하는 대신 이 우회 방법은:

  • 프로젝트 가져오기를 Git 저장소 가져오기와 분리합니다
  • 저장소를 GitLab에 점진적으로 푸시합니다
  1. 마이그레이션할 저장소의 로컬 클론을 만듭니다. 이후 단계에서 이 클론을 프로젝트 내보내기 외부에서 푸시합니다.

  2. 내보내기를 다운로드하고 project.bundle(Git 저장소 포함)을 제거합니다:

    tar -czvf new_export.tar.gz --exclude='project.bundle' @old_export.tar.gz
    
  3. Git 저장소 없이 내보내기를 가져옵니다. 저장소 없이 가져오기를 확인하라는 메시지가 표시됩니다.

  4. 이 bash 스크립트를 파일로 저장하고 적절한 origin을 추가한 후 실행합니다.

    #!/bin/sh
    
    # 가정:
    # - GitLab 위치가 "origin"
    # - 기본 브랜치가 "main"
    # - 총 크기를 500MB로 나누어 500MB 단위로 청크 푸시를 시도합니다.
    #   타임아웃이 계속 발생하면 이 크기를 줄여 더 작은 청크로 푸시합니다.
    
    git gc
    SIZE=$(git count-objects -v 2> /dev/null | grep size-pack | awk '{print $2}')
    
    # 보수적으로 한 번에 2GB를 푸시하려고 합니다
    # (각 커밋의 크기가 동일하다고 가정하므로 잘못된 가정입니다)
    BATCHES=$(($SIZE / 500000))
    TOTAL_COMMITS=$(git rev-list --count HEAD)
    if (( BATCHES > TOTAL_COMMITS )); then
        BATCHES=$TOTAL_COMMITS
    fi
    
    INCREMENTS=$(( ($TOTAL_COMMITS / $BATCHES) - 1 ))
    
    for (( BATCH=BATCHES; BATCH>=1; BATCH-- ))
    do
      COMMIT_NUM=$(( $BATCH - $INCREMENTS ))
      COMMIT_SHA=$(git log -n $COMMIT_NUM --format=format:%H | tail -1)
      git push -u origin ${COMMIT_SHA}:refs/heads/main
    done
    git push -u origin main
    git push -u origin --all
    git push -u origin --tags
    

Sidekiq 프로세스가 프로젝트를 내보내지 못하는 경우#

경우에 따라 Sidekiq 프로세스가 실행 중에 종료되는 등의 이유로 프로젝트 내보내기에 실패할 수 있습니다.

GitLab.com 사용자는 이 문제를 해결하기 위해 지원팀에 문의해야 합니다.

GitLab Self-Managed 관리자는 Rails 콘솔을 사용하여 Sidekiq 프로세스를 우회하고 수동으로 프로젝트 내보내기를 트리거할 수 있습니다:

project = Project.find(1)
current_user = User.find_by(username: 'my-user-name')
RequestStore.begin!
ActiveRecord::Base.logger = Logger.new(STDOUT)
params = {}

::Projects::ImportExport::ExportService.new(project, current_user, params).execute(nil)

이렇게 하면 UI를 통해 내보내기를 사용할 수 있지만 사용자에게 이메일을 트리거하지 않습니다. 프로젝트 내보내기를 수동으로 트리거하고 이메일을 보내려면:

project = Project.find(1)
current_user = User.find_by(username: 'my-user-name')
RequestStore.begin!
ActiveRecord::Base.logger = Logger.new(STDOUT)
params = {}

ProjectExportWorker.new.perform(current_user.id, project.id)

내보내기 단계 수동 실행#

일반적으로 웹 인터페이스프로젝트 가져오기 및 내보내기 API를 통해 프로젝트를 내보냅니다. 이러한 방법을 사용한 내보내기는 때때로 충분한 정보 없이 실패할 수 있습니다. 이런 경우 Rails 콘솔 세션을 열고 정의된 모든 내보내기 도구를 반복합니다. 각 명령이 반환하는 오류를 볼 수 있도록 전체 블록을 한 번에 붙여넣지 말고 각 줄을 개별적으로 실행합니다.

# 사용자는 내보내기 권한이 있어야 함
u = User.find_by_username('someuser')
p = Project.find_by_full_path('some/project')
e = Projects::ImportExport::ExportService.new(p,u)

e.send(:version_saver).send(:save)
e.send(:repo_saver).send(:save)
e.send(:avatar_saver).send(:save)
e.send(:project_tree_saver).send(:save)
e.send(:uploads_saver).send(:save)
e.send(:wiki_repo_saver).send(:save)
e.send(:lfs_saver).send(:save)
e.send(:snippets_repo_saver).send(:save)
e.send(:design_repo_saver).send(:save)
## 내보내기 도구 목록을 계속 `e.send(:exporter_name).send(:save)`로 진행

# 다음 줄은 /var/opt/gitlab/gitlab-rails/shared/tmp/gitlab_exports/@hashed/49/94/4994....와 유사한 export_path를 표시해야 합니다
s = Gitlab::ImportExport::Saver.new(exportable: p, shared: p.import_export_shared, user: u)

# GitLab 17.0 이전에는 `user` 매개변수가 지원되지 않았습니다. 위 내용에서 오류가 발생하거나
# `user` 인수를 제공해야 하는지 확실하지 않은 경우 다음 확인을 사용합니다:
Gitlab::ImportExport::Saver.instance_method(:initialize).parameters.include?([:keyreq, :user])
# 앞의 확인이 false를 반환하면 user 인수를 생략합니다:
s = Gitlab::ImportExport::Saver.new(exportable: p, shared: p.import_export_shared)

# 업로드를 시도하려면:
s.send(:compress_and_save)
s.send(:save_upload)

프로젝트가 성공적으로 업로드된 후 내보낸 프로젝트는 /var/opt/gitlab/gitlab-rails/uploads/-/system/import_export_upload/export_file/.tar.gz 파일에 있습니다.

오류: PG::QueryCanceled: ERROR: canceling statement due to statement timeout#

일부 마이그레이션은 PG::QueryCanceled: ERROR: canceling statement due to statement timeout 오류로 시간 초과될 수 있습니다. 이 문제를 피하는 한 가지 방법은 마이그레이션 배치 크기를 줄이는 것입니다. 이렇게 하면 마이그레이션이 시간 초과될 가능성이 줄어들지만 마이그레이션이 느려집니다.

배치 크기를 줄이려면 기능 플래그를 활성화해야 합니다. 자세한 내용은 이슈 456948을 참조하세요.

오류: command exited with error code 15 and Unable to save [FILTERED] into [FILTERED]#

파일 내보내기를 사용하여 프로젝트를 마이그레이션할 때 로그에서 다음 오류가 발생할 수 있습니다:

command exited with error code 15 and Unable to save [FILTERED] into [FILTERED]

이 오류는 Sidekiq이 SIGTERM을 받을 때 내보내기 또는 가져오기 중에 발생하며, 종종 tar 명령을 실행하는 동안 발생합니다.

GitLab.com 및 GitLab Dedicated와 같은 Kubernetes 환경에서는 메모리나 디스크 부족, 코드 배포 또는 인스턴스 업그레이드로 인해 운영 체제가 SIGTERM 신호를 트리거합니다. 근본 원인을 파악하려면 관리자가 Kubernetes가 인스턴스를 종료한 이유를 조사해야 합니다.

비Kubernetes 환경에서는 tar 명령을 실행하는 동안 인스턴스가 종료된 경우 이 오류가 발생할 수 있습니다. 그러나 이 오류는 디스크 부족으로 인해 발생하지 않으므로 메모리 부족이 가장 가능한 원인입니다.

이 오류가 발생하면:

  • 파일을 내보낼 때 GitLab은 최대 재시도 횟수에 도달할 때까지 내보내기를 재시도한 후 내보내기를 실패로 표시합니다. GitLab.com의 경우 인스턴스 부하가 적은 주말에 내보내기를 시도합니다.
  • 파일을 가져올 때 직접 가져오기를 재시도해야 합니다. GitLab은 가져오기를 자동으로 재시도하지 않습니다.

성능 문제 트러블슈팅#

아래의 Import/Export를 사용하는 현재 성능 문제를 읽어봅니다.

OOM 오류#

메모리 부족(OOM) 오류는 일반적으로 Sidekiq 메모리 킬러로 인해 발생합니다:

SIDEKIQ_MEMORY_KILLER_MAX_RSS = 2000000
SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS = 3000000
SIDEKIQ_MEMORY_KILLER_GRACE_TIME = 900

가져오기 상태 started와 다음 Sidekiq 로그는 메모리 문제를 나타냅니다:

WARN: Work still in progress <struct with JID>

시간 초과#

시간 초과 오류는 Gitlab::Import::StuckProjectImportJobsWorker가 프로세스를 실패로 표시하면서 발생합니다:

module Gitlab
  module Import
    class StuckProjectImportJobsWorker
      include Gitlab::Import::StuckImportJob
      # ...
    end
  end
end

module Gitlab
  module Import
    module StuckImportJob
      # ...
      IMPORT_JOBS_EXPIRATION = 15.hours.to_i
      # ...
      def perform
        stuck_imports_without_jid_count = mark_imports_without_jid_as_failed!
        stuck_imports_with_jid_count = mark_imports_with_jid_as_failed!

        track_metrics(stuck_imports_with_jid_count, stuck_imports_without_jid_count)
      end
      # ...
    end
  end
end
Marked stuck import jobs as failed. JIDs: xyz
  +-----------+    +-----------------------------------+
  |Export Job |--->| Calls ActiveRecord `as_json` and  |
  +-----------+    | `to_json` on all project models   |
                   +-----------------------------------+

  +-----------+    +-----------------------------------+
  |Import Job |--->| Loads all JSON in memory, then    |
  +-----------+    | inserts into the DB in batches    |
                   +-----------------------------------+

문제 및 해결 방법#

데이터베이스에서 느린 JSON 로딩/덤핑 모델:

  • 워커 분할
  • 배치 내보내기
  • SQL 최적화
  • ActiveRecord 콜백에서 벗어나기 (어려움)

높은 메모리 사용량 (분석 참조):

  • 메모리를 덜 사용하는 DB 커밋 최적 지점
  • Netflix Fast JSON API가 도움이 될 수 있음
  • 디스크 및 모든 SQL에 대한 배치 읽기/쓰기

파일 내보내기 프로젝트 마이그레이션 트러블슈팅

Tier: Free, Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기
요약

파일 내보내기를 사용하여 프로젝트를 마이그레이션하는 데 문제가 있다면 아래의 가능한 해결 방법을 참조하세요. Rails 콘솔을 사용하여 JID로 가져오기 상태 및 추가 로그에 대한 정보를 찾습니다: 인스턴스 러너 활성화가 내보낸 프로젝트와 프로젝트 가져오기 간에 일치하지 않으면 프로젝트 가져오기가 실패합니다.

파일 내보내기를 사용하여 프로젝트를 마이그레이션하는 데 문제가 있다면 아래의 가능한 해결 방법을 참조하세요.

트러블슈팅 명령#

Rails 콘솔을 사용하여 JID로 가져오기 상태 및 추가 로그에 대한 정보를 찾습니다:

Project.find_by_full_path('group/project').import_state.slice(:jid, :status, :last_error)
> {"jid"=>"414dec93f941a593ea1a6894", "status"=>"finished", "last_error"=>nil}
# 로그
grep JID /var/log/gitlab/sidekiq/current
grep "Import/Export error" /var/log/gitlab/sidekiq/current
grep "Import/Export backtrace" /var/log/gitlab/sidekiq/current
tail /var/log/gitlab/gitlab-rails/importer.log

불일치로 인한 프로젝트 가져오기 실패#

인스턴스 러너 활성화가 내보낸 프로젝트와 프로젝트 가져오기 간에 일치하지 않으면 프로젝트 가져오기가 실패합니다. 이슈 276930을 검토하고 다음 중 하나를 수행합니다:

  • 소스 및 대상 프로젝트 모두에서 인스턴스 러너가 활성화되어 있는지 확인합니다.
  • 프로젝트를 가져올 때 상위 그룹에서 인스턴스 러너를 비활성화합니다.

가져온 프로젝트에서 사용자 누락#

가져온 프로젝트에서 사용자가 가져오지 않는 경우 사용자 기여도 보존 요구사항을 참조하세요.

사용자 누락의 일반적인 이유는 사용자에 대해 공개 이메일 설정이 구성되지 않은 것입니다. 이 문제를 해결하려면 사용자에게 GitLab UI를 사용하여 이 설정을 구성하도록 요청합니다.

수동 구성이 불가능할 만큼 사용자가 너무 많은 경우, Rails 콘솔을 사용하여 모든 사용자 프로필에 공개 이메일 주소를 설정할 수 있습니다:

User.where("public_email IS NULL OR public_email = '' ").find_each do |u|
  next if u.bot?

  puts "Setting #{u.username}'s currently empty public email to #{u.email}…"
  u.public_email = u.email
  u.save!
end

대용량 저장소에 대한 가져오기 우회 방법#

최대 가져오기 크기 제한으로 인해 가져오기가 성공하지 못할 수 있습니다. 가져오기 제한을 변경할 수 없는 경우 여기에 나열된 우회 방법 중 하나를 시도할 수 있습니다.

우회 방법 옵션 1#

다음 로컬 워크플로를 사용하여 다른 가져오기 시도를 위해 저장소 크기를 일시적으로 줄일 수 있습니다:

  1. 내보내기에서 임시 작업 디렉토리를 만듭니다:

    EXPORT=<filename-without-extension>
    
    mkdir "$EXPORT"
    tar -xf "$EXPORT".tar.gz --directory="$EXPORT"/
    cd "$EXPORT"/
    git clone project.bundle
    
    # 나중에 가져올 수 있는 파일을 다시 만드는 데 방해가 되지 않도록
    mv project.bundle ../"$EXPORT"-original.bundle
    mv ../"$EXPORT".tar.gz ../"$EXPORT"-original.tar.gz
    
    git switch --create smaller-tmp-main
    
  2. 저장소 크기를 줄이려면 이 smaller-tmp-main 브랜치에서 작업합니다: 대용량 파일을 식별하고 제거하거나 대화형 리베이스 및 픽스업으로 커밋 수를 줄입니다.

    # .git/objects/pack/ 파일 크기 줄이기
    cd project
    git reflog expire --expire=now --all
    git gc --prune=now --aggressive
    
    # 가져올 수 있는 파일 다시 만들기 준비
    git bundle create ../project.bundle <default-branch-name>
    cd ..
    mv project/ ../"$EXPORT"-project
    cd ..
    
    # 가져올 수 있는 파일 다시 만들기
    tar -czf "$EXPORT"-smaller.tar.gz --directory="$EXPORT"/ .
    
  3. 이 새로운 소용량 파일을 GitLab으로 가져옵니다.

  4. 원본 저장소의 전체 클론에서 git remote set-url origin <new-url> && git push --force --all을 사용하여 가져오기를 완료합니다.

  5. 가져온 저장소의 브랜치 보호 규칙기본 브랜치를 업데이트하고, 임시 smaller-tmp-main 브랜치와 로컬 임시 데이터를 삭제합니다.

우회 방법 옵션 2#

Note

이 우회 방법은 LFS 개체를 고려하지 않습니다.

모든 변경사항을 한 번에 푸시하는 대신 이 우회 방법은:

  • 프로젝트 가져오기를 Git 저장소 가져오기와 분리합니다
  • 저장소를 GitLab에 점진적으로 푸시합니다
  1. 마이그레이션할 저장소의 로컬 클론을 만듭니다. 이후 단계에서 이 클론을 프로젝트 내보내기 외부에서 푸시합니다.

  2. 내보내기를 다운로드하고 project.bundle(Git 저장소 포함)을 제거합니다:

    tar -czvf new_export.tar.gz --exclude='project.bundle' @old_export.tar.gz
    
  3. Git 저장소 없이 내보내기를 가져옵니다. 저장소 없이 가져오기를 확인하라는 메시지가 표시됩니다.

  4. 이 bash 스크립트를 파일로 저장하고 적절한 origin을 추가한 후 실행합니다.

    #!/bin/sh
    
    # 가정:
    # - GitLab 위치가 "origin"
    # - 기본 브랜치가 "main"
    # - 총 크기를 500MB로 나누어 500MB 단위로 청크 푸시를 시도합니다.
    #   타임아웃이 계속 발생하면 이 크기를 줄여 더 작은 청크로 푸시합니다.
    
    git gc
    SIZE=$(git count-objects -v 2> /dev/null | grep size-pack | awk '{print $2}')
    
    # 보수적으로 한 번에 2GB를 푸시하려고 합니다
    # (각 커밋의 크기가 동일하다고 가정하므로 잘못된 가정입니다)
    BATCHES=$(($SIZE / 500000))
    TOTAL_COMMITS=$(git rev-list --count HEAD)
    if (( BATCHES > TOTAL_COMMITS )); then
        BATCHES=$TOTAL_COMMITS
    fi
    
    INCREMENTS=$(( ($TOTAL_COMMITS / $BATCHES) - 1 ))
    
    for (( BATCH=BATCHES; BATCH>=1; BATCH-- ))
    do
      COMMIT_NUM=$(( $BATCH - $INCREMENTS ))
      COMMIT_SHA=$(git log -n $COMMIT_NUM --format=format:%H | tail -1)
      git push -u origin ${COMMIT_SHA}:refs/heads/main
    done
    git push -u origin main
    git push -u origin --all
    git push -u origin --tags
    

Sidekiq 프로세스가 프로젝트를 내보내지 못하는 경우#

경우에 따라 Sidekiq 프로세스가 실행 중에 종료되는 등의 이유로 프로젝트 내보내기에 실패할 수 있습니다.

GitLab.com 사용자는 이 문제를 해결하기 위해 지원팀에 문의해야 합니다.

GitLab Self-Managed 관리자는 Rails 콘솔을 사용하여 Sidekiq 프로세스를 우회하고 수동으로 프로젝트 내보내기를 트리거할 수 있습니다:

project = Project.find(1)
current_user = User.find_by(username: 'my-user-name')
RequestStore.begin!
ActiveRecord::Base.logger = Logger.new(STDOUT)
params = {}

::Projects::ImportExport::ExportService.new(project, current_user, params).execute(nil)

이렇게 하면 UI를 통해 내보내기를 사용할 수 있지만 사용자에게 이메일을 트리거하지 않습니다. 프로젝트 내보내기를 수동으로 트리거하고 이메일을 보내려면:

project = Project.find(1)
current_user = User.find_by(username: 'my-user-name')
RequestStore.begin!
ActiveRecord::Base.logger = Logger.new(STDOUT)
params = {}

ProjectExportWorker.new.perform(current_user.id, project.id)

내보내기 단계 수동 실행#

일반적으로 웹 인터페이스프로젝트 가져오기 및 내보내기 API를 통해 프로젝트를 내보냅니다. 이러한 방법을 사용한 내보내기는 때때로 충분한 정보 없이 실패할 수 있습니다. 이런 경우 Rails 콘솔 세션을 열고 정의된 모든 내보내기 도구를 반복합니다. 각 명령이 반환하는 오류를 볼 수 있도록 전체 블록을 한 번에 붙여넣지 말고 각 줄을 개별적으로 실행합니다.

# 사용자는 내보내기 권한이 있어야 함
u = User.find_by_username('someuser')
p = Project.find_by_full_path('some/project')
e = Projects::ImportExport::ExportService.new(p,u)

e.send(:version_saver).send(:save)
e.send(:repo_saver).send(:save)
e.send(:avatar_saver).send(:save)
e.send(:project_tree_saver).send(:save)
e.send(:uploads_saver).send(:save)
e.send(:wiki_repo_saver).send(:save)
e.send(:lfs_saver).send(:save)
e.send(:snippets_repo_saver).send(:save)
e.send(:design_repo_saver).send(:save)
## 내보내기 도구 목록을 계속 `e.send(:exporter_name).send(:save)`로 진행

# 다음 줄은 /var/opt/gitlab/gitlab-rails/shared/tmp/gitlab_exports/@hashed/49/94/4994....와 유사한 export_path를 표시해야 합니다
s = Gitlab::ImportExport::Saver.new(exportable: p, shared: p.import_export_shared, user: u)

# GitLab 17.0 이전에는 `user` 매개변수가 지원되지 않았습니다. 위 내용에서 오류가 발생하거나
# `user` 인수를 제공해야 하는지 확실하지 않은 경우 다음 확인을 사용합니다:
Gitlab::ImportExport::Saver.instance_method(:initialize).parameters.include?([:keyreq, :user])
# 앞의 확인이 false를 반환하면 user 인수를 생략합니다:
s = Gitlab::ImportExport::Saver.new(exportable: p, shared: p.import_export_shared)

# 업로드를 시도하려면:
s.send(:compress_and_save)
s.send(:save_upload)

프로젝트가 성공적으로 업로드된 후 내보낸 프로젝트는 /var/opt/gitlab/gitlab-rails/uploads/-/system/import_export_upload/export_file/.tar.gz 파일에 있습니다.

오류: PG::QueryCanceled: ERROR: canceling statement due to statement timeout#

일부 마이그레이션은 PG::QueryCanceled: ERROR: canceling statement due to statement timeout 오류로 시간 초과될 수 있습니다. 이 문제를 피하는 한 가지 방법은 마이그레이션 배치 크기를 줄이는 것입니다. 이렇게 하면 마이그레이션이 시간 초과될 가능성이 줄어들지만 마이그레이션이 느려집니다.

배치 크기를 줄이려면 기능 플래그를 활성화해야 합니다. 자세한 내용은 이슈 456948을 참조하세요.

오류: command exited with error code 15 and Unable to save [FILTERED] into [FILTERED]#

파일 내보내기를 사용하여 프로젝트를 마이그레이션할 때 로그에서 다음 오류가 발생할 수 있습니다:

command exited with error code 15 and Unable to save [FILTERED] into [FILTERED]

이 오류는 Sidekiq이 SIGTERM을 받을 때 내보내기 또는 가져오기 중에 발생하며, 종종 tar 명령을 실행하는 동안 발생합니다.

GitLab.com 및 GitLab Dedicated와 같은 Kubernetes 환경에서는 메모리나 디스크 부족, 코드 배포 또는 인스턴스 업그레이드로 인해 운영 체제가 SIGTERM 신호를 트리거합니다. 근본 원인을 파악하려면 관리자가 Kubernetes가 인스턴스를 종료한 이유를 조사해야 합니다.

비Kubernetes 환경에서는 tar 명령을 실행하는 동안 인스턴스가 종료된 경우 이 오류가 발생할 수 있습니다. 그러나 이 오류는 디스크 부족으로 인해 발생하지 않으므로 메모리 부족이 가장 가능한 원인입니다.

이 오류가 발생하면:

  • 파일을 내보낼 때 GitLab은 최대 재시도 횟수에 도달할 때까지 내보내기를 재시도한 후 내보내기를 실패로 표시합니다. GitLab.com의 경우 인스턴스 부하가 적은 주말에 내보내기를 시도합니다.
  • 파일을 가져올 때 직접 가져오기를 재시도해야 합니다. GitLab은 가져오기를 자동으로 재시도하지 않습니다.

성능 문제 트러블슈팅#

아래의 Import/Export를 사용하는 현재 성능 문제를 읽어봅니다.

OOM 오류#

메모리 부족(OOM) 오류는 일반적으로 Sidekiq 메모리 킬러로 인해 발생합니다:

SIDEKIQ_MEMORY_KILLER_MAX_RSS = 2000000
SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS = 3000000
SIDEKIQ_MEMORY_KILLER_GRACE_TIME = 900

가져오기 상태 started와 다음 Sidekiq 로그는 메모리 문제를 나타냅니다:

WARN: Work still in progress <struct with JID>

시간 초과#

시간 초과 오류는 Gitlab::Import::StuckProjectImportJobsWorker가 프로세스를 실패로 표시하면서 발생합니다:

module Gitlab
  module Import
    class StuckProjectImportJobsWorker
      include Gitlab::Import::StuckImportJob
      # ...
    end
  end
end

module Gitlab
  module Import
    module StuckImportJob
      # ...
      IMPORT_JOBS_EXPIRATION = 15.hours.to_i
      # ...
      def perform
        stuck_imports_without_jid_count = mark_imports_without_jid_as_failed!
        stuck_imports_with_jid_count = mark_imports_with_jid_as_failed!

        track_metrics(stuck_imports_with_jid_count, stuck_imports_without_jid_count)
      end
      # ...
    end
  end
end
Marked stuck import jobs as failed. JIDs: xyz
  +-----------+    +-----------------------------------+
  |Export Job |--->| Calls ActiveRecord `as_json` and  |
  +-----------+    | `to_json` on all project models   |
                   +-----------------------------------+

  +-----------+    +-----------------------------------+
  |Import Job |--->| Loads all JSON in memory, then    |
  +-----------+    | inserts into the DB in batches    |
                   +-----------------------------------+

문제 및 해결 방법#

데이터베이스에서 느린 JSON 로딩/덤핑 모델:

  • 워커 분할
  • 배치 내보내기
  • SQL 최적화
  • ActiveRecord 콜백에서 벗어나기 (어려움)

높은 메모리 사용량 (분석 참조):

  • 메모리를 덜 사용하는 DB 커밋 최적 지점
  • Netflix Fast JSON API가 도움이 될 수 있음
  • 디스크 및 모든 SQL에 대한 배치 읽기/쓰기