GitLab이 관리하는 리포지터리 이동
Offering: GitLab Self-Managed
GitLab이 관리하는 모든 리포지터리를 다른 파일 시스템이나 다른 서버로 이동합니다. GitLab API를 사용하여 Git 리포지터리를 이동합니다: GitLab 리포지터리는 프로젝트, 그룹, 스니펫과 연결될 수 있습니다.
GitLab이 관리하는 모든 리포지터리를 다른 파일 시스템이나 다른 서버로 이동합니다.
GitLab 인스턴스에서 데이터 이동#
GitLab API를 사용하여 Git 리포지터리를 이동합니다:
- 서버 간.
- 다른 스토리지 간.
- 단일 노드 Gitaly에서 Gitaly 클러스터(Praefect)로.
GitLab 리포지터리는 프로젝트, 그룹, 스니펫과 연결될 수 있습니다. 이러한 각 유형은 리포지터리를 이동하기 위한 별도의 API가 있습니다. GitLab 인스턴스의 모든 리포지터리를 이동하려면 각 스토리지에 대해 각 유형의 리포지터리를 이동해야 합니다.
각 리포지터리는 이동하는 동안 읽기 전용으로 설정되며 이동이 완료될 때까지 쓸 수 없습니다.
리포지터리를 이동하려면:
- 모든 로컬 및 클러스터 스토리지가 GitLab 인스턴스에서 접근 가능한지 확인합니다. 이 예시에서는
<original_storage_name>과<cluster_storage_name>입니다. - 새 스토리지가 모든 새 프로젝트를 받도록 리포지터리 스토리지 가중치를 구성합니다. 이렇게 하면 마이그레이션이 진행되는 동안 기존 스토리지에 새 프로젝트가 생성되지 않습니다.
- 프로젝트, 스니펫, 그룹에 대한 리포지터리 이동을 예약합니다.
- Geo를 사용하는 경우 모든 리포지터리를 다시 동기화합니다.
- Sidekiq 파드에서 수평 파드 자동 스케일러를 사용하는 경우 마이그레이션 중에 스케일링을 방지하기 위해 Sidekiq 파드에 대한 HPA를 비활성화합니다.
프로젝트 이동#
모든 프로젝트 또는 개별 프로젝트를 이동할 수 있습니다.
API를 사용하여 모든 프로젝트를 이동하려면:
-
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" -
API를 사용하여 가장 최근 리포지터리 이동을 조회합니다. 응답은 다음 중 하나를 나타냅니다:
- 이동이 성공적으로 완료됨.
state필드가finished임. - 이동이 진행 중. 성공적으로 완료될 때까지 리포지터리 이동을 다시 조회합니다.
- 이동이 실패. 대부분의 실패는 일시적이며 이동을 다시 예약하면 해결됩니다.
- 이동이 성공적으로 완료됨.
-
이동이 완료된 후 API를 사용하여 프로젝트를 조회하고 모든 프로젝트가 이동했는지 확인합니다.
repository_storage필드가 이전 스토리지로 설정된 프로젝트는 반환되어서는 안 됩니다. 예:curl --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \ "https://gitlab.example.com/api/v4/projects?repository_storage=<original_storage_name>"또는 Rails 콘솔을 사용하여 모든 프로젝트가 이동했는지 확인합니다:
ProjectRepository.for_repository_storage('<original_storage_name>') -
필요에 따라 각 스토리지에 대해 반복합니다.
모든 프로젝트를 이동하지 않으려면 개별 프로젝트 이동 지침을 따릅니다.
스니펫 이동#
모든 스니펫 또는 개별 스니펫을 이동할 수 있습니다.
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/snippet_repository_storage_moves" -
가장 최근 리포지터리 이동을 조회합니다. 응답은 다음 중 하나를 나타냅니다:
- 이동이 성공적으로 완료됨.
state필드가finished임. - 이동이 진행 중. 성공적으로 완료될 때까지 리포지터리 이동을 다시 조회합니다.
- 이동이 실패. 대부분의 실패는 일시적이며 이동을 다시 예약하면 해결됩니다.
- 이동이 성공적으로 완료됨.
-
이동이 완료된 후 Rails 콘솔을 사용하여 모든 스니펫이 이동했는지 확인합니다:
SnippetRepository.for_repository_storage('<original_storage_name>')이 명령은 원래 스토리지의 스니펫을 반환해서는 안 됩니다.
-
필요에 따라 각 스토리지에 대해 반복합니다.
모든 스니펫을 이동하지 않으려면 개별 스니펫 지침을 따릅니다.
그룹 이동#
모든 그룹 또는 개별 그룹을 이동할 수 있습니다.
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/group_repository_storage_moves" -
가장 최근 리포지터리 이동을 조회합니다. 응답은 다음 중 하나를 나타냅니다:
- 이동이 성공적으로 완료됨.
state필드가finished임. - 이동이 진행 중. 성공적으로 완료될 때까지 리포지터리 이동을 다시 조회합니다.
- 이동이 실패. 대부분의 실패는 일시적이며 이동을 다시 예약하면 해결됩니다.
- 이동이 성공적으로 완료됨.
-
이동이 완료된 후 Rails 콘솔을 사용하여 모든 그룹이 이동했는지 확인합니다:
GroupWikiRepository.for_repository_storage('<original_storage_name>')이 명령은 원래 스토리지의 그룹을 반환해서는 안 됩니다.
-
필요에 따라 각 스토리지에 대해 반복합니다.
모든 그룹을 이동하지 않으려면 개별 그룹 지침을 따릅니다.
다른 GitLab 인스턴스로 마이그레이션#
새 GitLab 환경으로 마이그레이션하는 경우 API를 사용하여 데이터를 이동할 수 없습니다. 예:
- 단일 노드 GitLab에서 스케일 아웃 아키텍처로.
- 개인 데이터 센터의 GitLab 인스턴스에서 클라우드 공급자로.
이 경우 시나리오에 따라 /var/opt/gitlab/git-data/repositories에서 /mnt/gitlab/repositories로 모든 리포지터리를 복사하는 방법이 있습니다:
- 대상 디렉토리가 비어 있습니다.
- 대상 디렉토리에 오래된 리포지터리 사본이 있습니다.
- 수천 개의 리포지터리가 있을 때.
각 접근 방식은 대상 디렉토리 /mnt/gitlab/repositories의 데이터를 덮어쓸 수 있거나 덮어씁니다. 소스와 대상을 올바르게 지정해야 합니다.
백업 및 복원 사용 (권장)#
Gitaly 또는 Gitaly 클러스터(Praefect) 대상 모두에 대해 GitLab 백업 및 복원 기능을 사용해야 합니다. Git 리포지터리는 Gitaly에 의해 데이터베이스로 GitLab 서버에서 접근, 관리, 저장됩니다. rsync와 같은 도구를 사용하여 Gitaly 파일에 직접 접근하고 복사하면 데이터 손실이 발생할 수 있습니다. 다음을 수행할 수 있습니다:
- 여러 리포지터리를 동시에 처리하여 백업 성능을 향상시킵니다.
- 건너뛰기 기능을 사용하여 리포지터리만의 백업을 만듭니다.
Gitaly 클러스터(Praefect) 대상에는 백업 및 복원 방법을 사용해야 합니다.
tar 사용#
다음과 같은 경우 tar 파이프를 사용하여 리포지터리를 이동할 수 있습니다:
- Gitaly Cluster 대상이 아닌 Gitaly 대상을 지정합니다.
- 대상 디렉토리
/mnt/gitlab/repositories가 비어 있습니다.
이 방법은 오버헤드가 낮으며 tar은 보통 시스템에 사전 설치되어 있습니다. 그러나 중단된 tar 파이프를 재개할 수 없습니다. tar가 중단되면 대상 디렉토리를 비우고 모든 데이터를 다시 복사해야 합니다.
tar 프로세스의 진행 상황을 보려면 -xf를 -xvf로 바꿉니다.
sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
tar -C /mnt/gitlab/repositories -xf -'
다른 서버로 tar 파이프 사용#
Gitaly 대상의 경우 tar 파이프를 사용하여 데이터를 다른 서버로 복사할 수 있습니다. git 사용자가 git@<newserver>로 새 서버에 SSH 액세스 권한이 있으면 SSH를 통해 데이터를 파이프할 수 있습니다.
네트워크를 통과하기 전에 데이터를 압축하려면 (CPU 사용량이 증가함) ssh를 ssh -C로 바꿀 수 있습니다.
sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
ssh git@newserver tar -C /mnt/gitlab/repositories -xf -'
rsync 사용#
다음과 같은 경우 rsync를 사용하여 리포지터리를 이동할 수 있습니다:
- Gitaly Cluster 대상이 아닌 Gitaly 대상을 지정합니다.
- 대상 디렉토리에 이미 리포지터리의 부분적 또는 오래된 사본이 있어
tar로 모든 데이터를 다시 복사하는 것이 비효율적입니다.
rsync를 사용할 때 --delete 옵션을 사용해야 합니다. --delete 없이 rsync를 사용하면 데이터 손실과 리포지터리 손상이 발생할 수 있습니다. 자세한 내용은 이슈 270422를 참조하세요.
다음 명령에서 /.가 매우 중요하며, 그렇지 않으면 대상 디렉토리에 잘못된 디렉토리 구조가 생길 수 있습니다. 진행 상황을 보려면 -a를 -av로 바꿉니다.
sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
/mnt/gitlab/repositories'
다른 서버로 rsync 사용#
Gitaly 대상의 경우 소스 시스템의 git 사용자가 대상 서버에 SSH 액세스 권한이 있으면 rsync로 네트워크를 통해 리포지터리를 전송할 수 있습니다.
sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
git@newserver:/mnt/gitlab/repositories'
