직접 전송을 통한 그룹 마이그레이션
GitLab v19.1직접 전송을 사용하려면 GitLab 설치가 GitLab IP 주소에서 접근 가능하고 공개 DNS 항목이 있어야 합니다. 직접 전송을 통한 그룹 마이그레이션은 파일 내보내기를 사용한 그룹 및 프로젝트 마이그레이션의 발전된 형태입니다.
직접 전송을 사용하려면 GitLab 설치가 GitLab IP 주소에서 접근 가능하고 공개 DNS 항목이 있어야 합니다.
직접 전송을 통한 그룹 마이그레이션은 파일 내보내기를 사용한 그룹 및 프로젝트 마이그레이션의 발전된 형태입니다. 목표는 사용자가 프로젝트를 포함한 전체 그룹을 하나의 GitLab 인스턴스에서 다른 인스턴스로 더 쉽게 마이그레이션할 수 있도록 하는 것입니다.
설계 결정#
다음 아키텍처 다이어그램은 현재 GitLab API를 활용하는 일련의 ETL 파이프라인을 통해 그룹 마이그레이션이 어떻게 작동하는지 보여줍니다.
[
](/19.1/development/img/bulk_imports_overview_v13_7.png)
ETL#
ETL은 추출(Extract), 변환(Transform), 적재(Load)의 약자로, 여러 데이터 소스의 데이터를 결합하여 데이터 웨어하우스 또는 다른 타깃 시스템에 적재되는 단일하고 일관된 데이터 저장소로 만드는 데이터 통합 프로세스입니다.
ETL 아키텍처를 사용하면 코드가 더 명확해지고 추적, 테스트, 확장이 쉬워집니다. 아이디어는 임포트할 각 관계에 대해 하나의 ETL 파이프라인을 갖는 것입니다.
API#
현재 프로젝트 및 그룹 임포트는 파일 기반이므로, 임포트할 파일을 생성하기 위한 내보내기 단계가 필요합니다.
직접 전송을 통한 그룹 마이그레이션은 GitLab API를 활용하여 마이그레이션 속도를 높입니다.
또한, GraphQL로 나아가는 과정에서 직접 전송을 통한 그룹 마이그레이션은 GraphQL API 적용 범위 확대에 기여할 수 있으며, 이는 GitLab과 사용자 모두에게 이익이 됩니다.
네임스페이스#
마이그레이션 프로세스는 마이그레이션을 추적하기 위한 BulkImport 레코드 생성으로 시작됩니다. 이후 GitLab 그룹 마이그레이션과 관련된 모든 코드는 모든 애플리케이션 레이어에서 새로운 BulkImports 네임스페이스 아래에서 찾을 수 있습니다.
멱등성#
동일한 Sidekiq job을 재실행할 때 중복 항목이 생기지 않도록, 각 항목이 처리될 때 캐시에 저장하고 캐시에 이미 있는 항목은 건너뜁니다.
두 가지 전략이 있습니다:
-
BulkImports::Pipeline::HexdigestCacheStrategy: 데이터의 hexdigest 표현을 캐시합니다. -
BulkImports::Pipeline::IndexCacheStrategy: 파이프라인에서 항목의 마지막으로 처리된 인덱스를 캐시합니다.
Sidekiq job 실행 계층 구조#
대상 인스턴스에서:
flowchart TD subgraph s1["Main"] BulkImportWorker -- Enqueue itself --> BulkImportWorker BulkImportWorker --> BulkImports::ExportRequestWorker BulkImports::ExportRequestWorker --> BulkImports::EntityWorker BulkImports::EntityWorker -- Enqueue itself --> BulkImports::EntityWorker BulkImports::EntityWorker --> BulkImports::PipelineWorker BulkImports::PipelineWorker -- Enqueue itself --> BulkImports::PipelineWorker BulkImports::EntityWorker --> BulkImports::PipelineWorkerA["BulkImports::PipelineWorker"] BulkImports::EntityWorker --> BulkImports::PipelineWorkerA1["..."]
BulkImportWorker --> BulkImports::ExportRequestWorkerB["BulkImports::ExportRequestWorker"]
BulkImports::ExportRequestWorkerB --> BulkImports::PipelineBatchWorkerBB["..."]
end
subgraph s2["Batched pipelines"]
BulkImports::PipelineWorker --> BulkImports::PipelineBatchWorker
BulkImports::PipelineWorker --> BulkImports::PipelineBatchWorkerA["..."]
BulkImports::PipelineBatchWorker --> BulkImports::FinishBatchedPipelineWorker
end
flowchart TD subgraph s1["Cron"] BulkImports::StaleImportWorker end
소스 인스턴스에서:
flowchart TD subgraph s1["Main"] BulkImports::RelationExportWorker end
subgraph s2["Batched relations"]
BulkImports::RelationExportWorker --> BulkImports::RelationBatchExportWorker
BulkImports::RelationExportWorker --> BulkImports::RelationBatchExportWorkerA["..."]
BulkImports::RelationBatchExportWorker --> BulkImports::FinishBatchedRelationExportWorker
end
사용자 기여 매핑#
직접 전송은 사용자 기여 매핑을 지원합니다. 이를 통해 임포트된 레코드를 플레이스홀더 사용자에게 귀속시켰다가 임포트 완료 후 실제 사용자를 할당할 수 있습니다.
핵심 컴포넌트#
-
BulkImports::Common::Pipelines::MembersPipeline은 대부분의 소스 사용자 및 플레이스홀더 레코드를 생성하는 파이프라인입니다. 사용자 기여는 일반적으로 그룹 및 프로젝트 멤버에서 발생하기 때문입니다. 이 파이프라인의 트랜스포머인BulkImports::Common::Transformers::SourceUserMemberAttributesTransformer는Import::SourceUserMapper를 호출하여 소스 멤버 속성을 대상의 사용자에게 매핑합니다. 그러나 사용자가 기여를 하기 위해 반드시 멤버일 필요는 없으며, 임포트된 관계 데이터에 이름이나 사용자명 같은 식별 데이터가 포함되지 않을 수 있으므로, 소스 사용자는 다른 관계 파이프라인에 의해 멤버 없이 생성될 수도 있습니다. -
BulkImports::SourceUsersAttributesWorker는 멤버가 아닌 기여자의 소스 사용자 정보를 백필(backfill)합니다. 이 워커는 마이그레이션 시작 시BulkImports::CreateService의BulkImportWorker바로 전에 처음 호출됩니다.BulkImports::SourceUsersAttributesWorker는 각 엔티티의 최상위 네임스페이스에 대해BulkImports::UpdateSourceUsersService를 호출하고, 대량 임포트가 완료될 때까지 5분마다 자신을 다시 큐에 추가합니다. -
BulkImports::UpdateSourceUsersService는 현재 마이그레이션과 연결된source_name또는source_username이 없는Import::SourceUser레코드를 쿼리한 다음, 소스 인스턴스에 GraphQL 요청을 보내 누락된 이름과 사용자명을 가져오고, 마지막으로 정보가 누락된 소스 사용자를 업데이트합니다.
핵심 클래스#
| 클래스 | 목적 |
|---|---|
| BulkImports::Pipeline::Context | 파이프라인에 source_user_mapper와 source_ghost_user_id를 제공합니다. |
| BulkImports::CreateService | 사용자 매핑을 활성화하는 진입점입니다. |
| BulkImports::NdjsonPipeline | ImportExport::Base::RelationFactory를 사용하여 관계를 영속화하기 전에 Import::SourceUser 레코드를 생성하고, 이를 필요로 하는 관계에 대한 관계 임포트 중 플레이스홀더 참조를 캐시합니다. |
| BulkImports::Common::Pipelines::MembersPipeline | 사용자 기여는 일반적으로 그룹 및 프로젝트 멤버에서 발생하므로 대부분의 소스 사용자 및 플레이스홀더 레코드를 생성합니다. |
| BulkImports::Common::Transformers::SourceUserMemberAttributesTransformer | Import::SourceUserMapper를 호출하여 소스 멤버 속성을 대상의 사용자에게 매핑합니다. 그러나 사용자가 기여를 하기 위해 반드시 멤버일 필요는 없으며, 임포트된 관계 데이터에 이름이나 사용자명 같은 식별 데이터가 포함되지 않을 수 있으므로, 소스 사용자는 다른 관계 파이프라인에 의해 멤버 없이 생성될 수 있습니다. |
| Import::BulkImports::SourceUsersMapper | ImportExport::Base::RelationFactory가 소스 사용자 ID를 대상 사용자 ID에 매핑할 수 있도록 해시와 유사한 인터페이스를 제공합니다. 이를 통해 파일 기반 임포트가 플레이스홀더 사용자 매핑을 지원하지 않더라도 직접 전송과 파일 기반 임포트 모두 ImportExport::Base::RelationFactory를 사용할 수 있습니다. |
| BulkImports::SourceUsersAttributesWorker | 멤버가 아닌 기여자의 소스 사용자 정보를 백필합니다. 마이그레이션 시작 시 BulkImports::CreateService의 BulkImportWorker 바로 전에 처음 호출됩니다. 각 엔티티의 최상위 네임스페이스에 대해 BulkImports::UpdateSourceUsersService를 호출하고, 대량 임포트가 완료될 때까지 5분마다 자신을 다시 큐에 추가합니다. |
| BulkImports::UpdateSourceUsersService | 현재 마이그레이션과 연결된 source_name 또는 source_username이 없는 Import::SourceUser 레코드를 쿼리한 다음, 소스 인스턴스에 GraphQL 요청을 보내 누락된 이름과 사용자명을 가져오고, 마지막으로 정보가 누락된 소스 사용자를 업데이트합니다. |
고스트 사용자 처리#
직접 전송은 소스 인스턴스의 고스트 사용자에 대한 특별한 처리 방식을 가지고 있습니다. BulkImports::SourceInternalUserFinder는 소스 인스턴스에 GraphQL 요청을 보내 GitLab 고스트 사용자명을 가진 비인간 사용자를 쿼리하고(구현 당시에는 고스트 사용자에 대한 명시적인 API 요청이 없었음) 소스 고스트 사용자 ID를 캐시합니다.
소스 고스트 사용자를 만났을 때:
-
기여는 대상 인스턴스의 고스트 사용자에게 직접 귀속됩니다.
-
플레이스홀더 사용자는 생성되지 않습니다.
플레이스홀더 사용자 생성 건너뛰기#
특정 관계(예: approvals, builds, ci_pipelines, events)는 플레이스홀더 사용자 생성을 건너뜁니다. 이는 소스 인스턴스에 더 이상 존재하지 않는 사용자를 참조할 수 있기 때문입니다(외래 키 제약 조건 없음). BulkImports::NdjsonPipeline::IGNORE_PLACEHOLDER_USER_CREATION을 참조하세요.