GitLab이 관리하는 저장소 이동

Tier: Free, Premium, Ultimate Offering: Self-Managed

GitLab이 관리하는 모든 저장소를 다른 파일 시스템이나 다른 서버로 이동할 수 있습니다.

GitLab 인스턴스에서 데이터 이동

GitLab API는 Git 저장소를 이동하는 권장 방법입니다.

  • 서버 간.
  • 서로 다른 저장소 간.
  • 단일 노드 Gitaly에서 Gitaly 클러스터로.

자세한 정보는 다음을 참조하십시오:

저장소 이동

GitLab 저장소는 프로젝트, 그룹 및 스니펫과 연결될 수 있습니다. 각 유형에는 해당 저장소를 이동시키기 위한 별도의 API가 있습니다. GitLab 인스턴스의 모든 저장소를 이동하려면, 각 유형이 각 저장소에 대해 이동 예약을 해야 합니다.

경고: GitLab 버전 13.12에서 14.1까지 Gitaly 클러스터로 저장소를 이동하려면, gitaly_replicate_repository_direct_fetch 기능 플래그를 활성화해야 합니다.

경고: Gitaly 클러스터에 이미 저장된 프로젝트를 해당 클러스터로 다시 이동하려는 경우, /projects/:project_id/repository_storage_moves를 호출하여 저장소를 이동하려는 시도는 영구적으로 삭제될 수 있습니다. 자세한 내용은 이 문제를 참조하십시오. 이 문제는 GitLab 14.3.0에서 수정되었으며 후방 호환되었습니다: 14.2.4, 14.1.6, 14.0.11, 그리고 13.12.12.

각 저장소는 이동 기간 동안 읽기 전용으로 설정됩니다. 저장소는 이동이 완료될 때까지 쓰기가 불가능합니다.

저장소를 이동하려면:

  1. GitLab 인스턴스에서 모든 로컬 및 클러스터 스토리지에 액세스할 수 있는지 확인하십시오. 이 예에서는 <original_storage_name><cluster_storage_name>입니다.
  2. 저장소 스토리지 가중치 구성하여 새 저장소가 모든 새 프로젝트를 받도록 합니다. 이렇게 하면 마이그레이션이 진행되는 동안 기존 저장소에 새 프로젝트가 생성되는 것을 막을 수 있습니다.
  3. 저장소 이동 예약:
  4. Geo가 활성화된 경우, 모든 저장소 다시 동기화를 수행합니다.

모든 프로젝트 이동

API를 사용하여 모든 프로젝트를 이동하려면:

  1. API를 사용하여 저장소 이동을 예약합니다. 예를 들어:

    curl --request POST --header "Private-Token: <your_access_token>" \
         --header "Content-Type: application/json" \
         --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' \
         "https://gitlab.example.com/api/v4/project_repository_storage_moves"
    
  2. API를 사용하여 가장 최근의 저장소 이동을 조회합니다. 응답은 다음과 같이 나타낼 수 있습니다:
    • 이동이 성공적으로 완료되었습니다. state 필드는 finished입니다.
    • 이동이 진행 중입니다. 저장소 이동이 성공적으로 완료될 때까지 저장소 이동을 다시 조회합니다.
    • 이동에 실패했습니다. 대부분의 실패는 임시적이며 이동을 다시 예약함으로써 문제가 해결됩니다.
  3. 이동이 완료되면 API를 사용하여 프로젝트를 조회하여 모든 프로젝트가 이동되었는지 확인합니다. 예를 들어:

    curl --header "Private-Token: <your_access_token>" --header "Content-Type: application/json" \
    "https://gitlab.example.com/api/v4/projects?repository_storage=<original_storage_name>"
    

    또는 레일즈 콘솔를 사용하여 모든 프로젝트가 이동되었는지 확인합니다. 다음을 레일즈 콘솔에서 실행합니다:

    ProjectRepository.for_repository_storage('<original_storage_name>')
    
  4. 필요한 경우 각 저장소에 대해 반복합니다.

모든 스니펫 이동하기

API를 사용하여 모든 스니펫을 이동하려면 다음을 수행합니다:

  1. 스토리지 샤드의 모든 스니펫에 대한 저장소 이동 일정을 만듭니다. 예:

    curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
         --header "Content-Type: application/json" \
         --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' \
         "https://gitlab.example.com/api/v4/snippet_repository_storage_moves"
    
  2. 가장 최근의 저장소 이동 조회를 수행합니다. 응답은 다음 중 하나를 나타냅니다:
    • 이동이 성공적으로 완료됨. state 필드는 finished입니다.
    • 이동이 진행 중. 이동이 성공적으로 완료될 때까지 저장소 이동을 다시 조회합니다.
    • 이동에 실패했습니다. 대부분의 실패는 일시적이며 이동을 다시 예약하여 해결됩니다.
  3. 이동이 완료되면 레일즈 콘솔을 사용하여 모든 스니펫이 이동되었는지 확인합니다. 원본 저장소에는 스니펫이 반환되지 않아야 합니다. 다음을 레일즈 콘솔에서 실행합니다:

    SnippetRepository.for_repository_storage('<original_storage_name>')
    
  4. 필요에 따라 각 저장소에 대해 반복합니다.

모든 그룹 이동하기

상세정보: Tier: 프리미엄, 얼티밋 Offering: Self-managed

API를 이용하여 모든 그룹을 이동하려면 다음을 수행합니다:

  1. 스토리지 샤드의 모든 그룹에 대한 저장소 이동 일정을 만듭니다. 예:

    curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
         --header "Content-Type: application/json" \
         --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' \
         "https://gitlab.example.com/api/v4/group_repository_storage_moves"
    
  2. 가장 최근의 저장소 이동 조회를 수행합니다. 응답은 다음 중 하나를 나타냅니다:
    • 이동이 성공적으로 완료됨. state 필드는 finished입니다.
    • 이동이 진행 중. 이동이 성공적으로 완료될 때까지 저장소 이동을 다시 조회합니다.
    • 이동에 실패했습니다. 대부분의 실패는 일시적이며 이동을 다시 예약하여 해결됩니다.
  3. 이동이 완료되면 레일즈 콘솔을 사용하여 모든 그룹이 이동되었는지 확인합니다. 원본 저장소에는 그룹이 반환되지 않아야 합니다. 다음을 레일즈 콘솔에서 실행합니다:

    GroupWikiRepository.for_repository_storage('<original_storage_name>')
    
  4. 필요에 따라 각 저장소에 대해 반복합니다.

다른 GitLab 인스턴스로의 이전

GitLab 환경을 새로운 인스턴스로 이전하는 경우 API를 사용할 수 없습니다. 예를 들어:

  • 단일 노드 GitLab에서 확장된 아키텍처로 이전하는 경우.
  • 개인 데이터 센터의 GitLab 인스턴스에서 클라우드 공급업체로 이동하는 경우.

문서의 나머지 부분에서는 /var/opt/gitlab/git-data/repositories에서 모든 리포지토리를 복사하는 여러 가지 방법을 살펴봅니다.

세 가지 시나리오를 살펴봅니다:

  • 대상 디렉터리가 비어 있는 경우.
  • 대상 디렉터리에 오래된 리포지토리 사본이 있는 경우.
  • 수천 개의 리포지토리를 처리하는 방법

경고: 나열한 각 방법은 대상 디렉터리 /mnt/gitlab/repositories의 데이터를 덮어씁니다. 소스와 대상을 혼동하지 마세요.

모든 경우에 권장되는 접근 방식

Gitaly 또는 Gitaly 클러스터 대상의 경우 GitLab의 백업 및 복원 기능 을 사용해야 합니다. Gitaly는 데이터베이스로서 Git 리포지토리를 GitLab 서버에서 액세스, 관리 및 저장합니다. rsync와 같은 도구를 사용하여 직접 Gitaly 파일에 액세스하는 것은 데이터 손실을 가져올 수 있습니다.

Gitaly 클러스터 대상에 대해서는 다른 방법이 작동하지 않습니다.

대상 디렉터리가 비어 있는 경우: tar 파이프 사용

Gitaly 대상의 경우 (Gitaly 클러스터 대상의 경우 권장된 접근 방식을 사용하세요), 대상 디렉터리 /mnt/gitlab/repositories가 비어 있는 경우 가장 간단한 방법은 tar 파이프를 사용하는 것입니다. 이 방법은 오버헤드가 적으며 대부분의 시스템에 이미 tar가 설치되어 있습니다.

그러나 중단된 tar 파이프를 다시 시작할 수 없습니다. 이 경우 모든 데이터를 다시 복사해야 합니다.

sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
  tar -C /mnt/gitlab/repositories -xf -'

진행 상황을 보려면 -xf 대신 -xvf로 대체하세요.

tar 파이프를 사용하여 다른 서버로 전송

Gitaly 대상의 경우 (Gitaly Cluster 대상의 경우 권장된 방법을 사용하십시오), tar 파이프를 사용하여 데이터를 다른 서버로 복사할 수도 있습니다. git 사용자가 git@newserver로 새 서버에 SSH 액세스 권한이 있는 경우 데이터를 SSH를 통해 파이프로 전송할 수 있습니다.

sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
  ssh git@newserver tar -C /mnt/gitlab/repositories -xf -'

네트워크를 통해 데이터를 보내기 전에 데이터를 압축하려면 (CPU 사이클을 사용하여 비용이 발생함) sshssh -C로 바꿀 수 있습니다.

대상 디렉터리에는 저장소의 오래된 사본이 포함되어 있음: rsync 사용

경고: Git 데이터를 마이그레이션하기 위해 rsync를 사용하면 데이터 손실 및 저장소 훼손이 발생할 수 있습니다. [이 지침이 검토 중입니다.]((https://gitlab.com/gitlab-org/gitlab/-/issues/270422)

대상 디렉터리에 이미 부분적이거나 오래된 저장소 사본이 포함되어 있으면 tar로 모든 데이터를 다시 복사하는 것이 낭비일 수 있습니다. 이러한 시나리오에서는 Gitaly 대상의 경우 rsync를 사용하는 것이 더 좋습니다 (Gitaly Cluster 대상의 경우 권장된 방법을 사용하십시오).

이 유틸리티는 시스템에 이미 설치되어 있거나 apt 또는 yum을 사용하여 설치할 수 있습니다.

sudo -u git  sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
  /mnt/gitlab/repositories'

위의 명령어에서 /. 은 매우 중요합니다. 이것이 없으면 대상 디렉터리의 잘못된 디렉터리 구조를 얻을 수 있습니다. 진행 상황을 보고 싶다면 -a-av로 바꿀 수 있습니다.

다른 서버로 단일 rsync

경고: Git 데이터를 마이그레이션하기 위해 rsync를 사용하면 데이터 손실 및 저장소 훼손이 발생할 수 있습니다. [이 지침이 검토 중입니다.]((https://gitlab.com/gitlab-org/gitlab/-/issues/270422)

Gitaly 대상의 경우 (Gitaly Cluster 대상의 경우 권장된 방법을 사용하십시오), 소스 시스템의 git 사용자가 대상 서버에 SSH 액세스 권한이 있는 경우 rsync를 사용하여 저장소를 네트워크를 통해 보낼 수 있습니다.

sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
  git@newserver:/mnt/gitlab/repositories'

최근 활동이 있는 저장소에 대해서만 병렬 rsync 수행

경고: GitLab 16.4에서 더 이상 사용되지 않는 Rake 작업 gitlab:list_repos가 있으며, 17.0에서 제거될 예정입니다. 모든 경우에 백업 및 복원을 사용하십시오.

경고: Git 데이터를 마이그레이션하는 데 rsync를 사용하면 데이터 손실과 저장소 손상이 발생할 수 있습니다. 이 지침은 검토 중입니다.

이미 2015-10-1 12:00 UTC 이후에 시작된 동기화를 수행했다고 가정해 봅시다. 그럼 그 이후에 GitLab을 사용하여 변경된 저장소만 동기화하고 싶을 수 있습니다. SINCE 변수를 사용하여 rake gitlab:list_repos에 최근 활동이 있는 저장소만 출력하도록 할 수 있습니다.

# Omnibus
sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
  sudo -u git \
  /usr/bin/env JOBS=10 \
  /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
    success-$(date +%s).log \
    /var/opt/gitlab/git-data/repositories \
    /mnt/gitlab/repositories

# 소스
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
  sudo -u git -H \
  /usr/bin/env JOBS=10 \
  bin/parallel-rsync-repos \
    success-$(date +%s).log \
    /home/git/repositories \
    /mnt/gitlab/repositories