업로드 개발 가이드라인

업로드는 많은 GitLab 기능의 필수 요소입니다. GitLab이 업로드를 어떻게 처리하는지 이해하려면, 이 페이지에서 파일을 리포지터리로 전송하는 주요 메커니즘에 대한 개요를 제공합니다.

GitLab 업로드는 기능별로 구성됩니다. 업로드를 포함하는 모든 기능은 동일한 구성 옵션을 제공하지만, 서로 독립적으로 구성할 수 있습니다. 예를 들어, Git LFS 업로드는 CI/CD 빌드 아티팩트 업로드와는 독립적으로 구성할 수 있지만, 두 가지 모두 동일한 설정 키 세트를 제공합니다. 이러한 설정은 업로드가 처리되는 방식을 조절하며, 성능과 확장성에 큰 영향을 미칠 수 있습니다.

이 페이지는 이러한 파일 처리에 중요한 업로드 설정을 요약하고, 그 다음 각 메커니즘을 더 자세히 설명합니다.

업로드 설정이 업로드 흐름에 미치는 영향

더 자세한 개별 업로드 전략을 살펴보기 전에, 이러한 전략에 어떤 업로드 설정이 매핑되는지에 대한 고수준 분석을 살펴봅시다.

업로드 설정 자체는 업로드 관리에 문서화되어 있습니다. 여기서는 이러한 설정이 GitLab 업로드 로직의 내부를 어떻게 조절하는지에 중점을 둡니다. 최상위 수준에서 우리는 업로드 된 파일에 대해 두 가지 대상을 구분합니다.

이 표에서 x.y.zgitlab.yml을 통해 취해진 경로를 지정합니다.

설정 동작
<feature>.object_store.enabled false 파일은 <feature>.storage_path에 로컬로 저장됨
<feature>.object_store.enabled true 파일은 <feature>.object_store.remote_directory에 원격으로 저장됨

객체 리포지터리를 사용할 때, 관리자는 해당 파일이 해당 버킷으로 이동하는 방법을 제어할 수 있습니다. 이 이동은 다음 중 하나의 방법으로 발생할 수 있습니다:

개별 Sidekiq 워커도 객체 리포지터리에 파일을 저장할 수 있지만, 이는 여기서 다루지 않습니다.

마지막으로, Workhorse는 대부분의 사용자 시작 업로드를 Rails 컨트롤러에서 느린 작업을 방지하기 위한 업로드 버퍼 메커니즘을 사용하여 보조합니다. 이 메커니즘은 Workhorse 보조 업로드에서 설명되어 있으며, 이는 우리가 이전에 논의한 것과는 상관없이 실행되는 것입니다.

이제 우리는 각 경우를 더 자세히 살펴봅니다.

로컬 리포지터리

로컬 리포지터리는 업로드가 할 수 있는 가장 간단한 경로입니다. 이것은 GitLab이 초기에 업로드를 처리하는 방식이었습니다. 레일 응용 프로그램 내에 storage_path에서 액세스 가능한 저장 볼륨(예: 디스크 또는 네트워크 연결 리포지터리)을 가정합니다. 이 파일 경로는 Rails 루트 디렉터리를 기준으로 하며, 다른 업로드 설정과 마찬가지로 기능별로 구성할 수 있습니다.

클라이언트가 파일 업로드를 보낼 때, Workhorse는 먼저 파일을 디스크에 버퍼링합니다. 이 메커니즘은 Workhorse 보조 업로드에서 더 자세히 설명되어 있습니다. 요청이 레일 응용 프로그램에 도달할 때 파일은 이미 로컬 리포지터리에 존재하기 때문에, 레일은 단순히 트랜잭션을 완료하기 위해 지정된 디렉터리로 이동해야 합니다.

로컬 리포지터리는 클라우드 네이티브 GitLab (CNG) 설치에는 사용할 수 없습니다. 따라서 GitLab SaaS에는 사용되지 않습니다.

객체 리포지터리

수평 확장 가능한 리포지터리를 제공하려면 다음과 같은 객체 리포지터리 공급 업체를 사용해야 합니다:

  • 아마존 AWS.
  • Google Cloud Storage (GCS).
  • Azure Cloud Storage.

객체 리포지터리를 사용하면 두 가지 주요 이점이 있습니다:

  • 더 많은 저장 용량을 추가하는 것이 쉽습니다: 클라우드 제공 업체가 자동으로 수행합니다.
  • GitLab 설치의 수평 스케일링을 활성화합니다: 여러 GitLab 응용 프로그램 서버가 동일한 데이터에 액세스할 수 있습니다. 해당 데이터가 객체 리포지터리에 저장되어 있을 때.

GitLab SaaS를 포함한 CNG 설치는 항상 객체 리포지터리를 사용합니다 (GitLab SaaS의 경우 GCS 사용.)

원격 객체 리포지터리로 업로드하는 것의 어려움은 GitLab에서 객체 리포지터리 제공 업체로의 아웃바운드 HTTP 요청을 포함한다는 것입니다. 앞서 언급한 것처럼, 이 HTTP 요청이 전송되는 방법에는 세 가지 다른 전략이 있습니다.

Rails 컨트롤러 업로드

직접 업로드를 사용할 수 없을 때, Rails는 컨트롤러 create 액션의 일부로 파일을 객체 리포지터리로 업로드합니다. 업로드된 파일의 종류에 따라 책임을지는 주요 컨트롤러가 달라집니다.

Rails 컨트롤러 업로드는 로컬 리포지터리에 업로드하는 것과 매우 유사합니다. 주요 차이점: Rails은 객체 리포지터리로 HTTP 요청을 보내야 합니다. 이는 CarrierWave Fog 업로더를 통해 발생합니다.

로컬 리포지터리와 마찬가지로, 이 전략은 Workhorse 보조를 받아 비용이 많이 드는 I/O 작업을 Ruby와 Rails에서 빼냅니다. 직접 업로드가 Puma의 60초 요청 제한에 영향을 덜 받기 때문에 직접 업로드가 더 잘 작동합니다.

이 전략은 파일 업로드가 작을 때에만 적합합니다. Puma의 요청 제한 시간인 60초에 영향을 받기 때문입니다.

직접 업로드

직접 업로드는 GitLab SaaS와 같은 CNG 설치에 대한 객체 리포지터리로 대용량 파일을 이동하는 권장 방법입니다.

직접 업로드를 사용하면, Workhorse는 다음 작업을 수행합니다:

  1. 요청을 레일 응용 프로그램으로 승인합니다.
  2. 객체 리포지터리 자체와 연결을 설정하여 파일을 임시 위치로 전송합니다.
  3. 전송이 완료되면, Workhorse는 레일 응용 프로그램으로 요청을 완료합니다. 레일은 객체 리포지터리 복사 작업을 실행하여 파일을 최종 위치에 넣습니다.
  4. 객체 리포지터리의 임시 파일을 삭제하여 업로드를 완료합니다.

이 전략은 Workhorse 보조 업로드의 다른 형태입니다. Workhorse와 Puma 모두에서 액세스 할 수있는 공유 리포지터리에 의존하지 않습니다.

모든 기존 업로드 전략 중에서, 직접 업로드는 대용량 (기가바이트) 업로드를 가장 잘 처리할 수 있습니다. 그러나 여전히 Puma가 업로드 크기에 비례하여 시간이 걸리는 객체 리포지터리 복사 작업을 수행하기 때문에 Puma 제한 시간을 초과할 수 있는 가능성이 있습니다.

Workhorse 보조 업로드

대부분의 업로드는 어떤 방식으로든 Workhorse의 도움을 받습니다.

  • 대부분의 경우, Workhorse는 업로드를 임시 파일로 버퍼링합니다. Workhorse는 Puma에게 임시 파일의 이름과 위치를 알려주기위해 요청에 메타데이터를 추가합니다. 이는 Workhorse와 Puma 사이에 공유되는 임시 리포지터리가 필요합니다. 모든 GitLab 설치 (CNG 포함)에는이 공유 임시 리포지터리가 있습니다.
  • 때로는 Workhorse가 파일을 사전 처리합니다. 예를 들어, CI 아티팩트 업로드의 경우, Workhorse는 ZIP 파일의 내용에 대한 별도의 색인을 만듭니다. 이 작업을 Workhorse에서 수행함으로써 Puma 요청 제한 시간을 우회합니다. Sidekiq 백그라운드 처리와 비교하면 유저가 파일 업로드를 수락하지만 아직 처리하지 않은 중간 상태를 보지 않는 장점이 있습니다.
  • 직접 업로드에서 Workhorse는 파일의 사전 처리 및 객체 리포지터리로 업로드합니다. 대용량 파일을 객체 리포지터리로 업로드하는데 시간이 걸리는 작업은 Workhorse에서 처리하여 Puma 요청 제한 시간을 피합니다.