GitLab의 파일 저장소

파일 업로드, 저장 및 검색을 처리하기 위해 CarrierWave gem을 사용합니다.

파일 업로드는 workhorse에 의해 가속화되어야 하며 자세한 내용은 업로드 개발 문서를 참조하십시오.

다음과 같은 맥락에 따라 파일 업로드가 사용되는 많은 곳이 있습니다:

  • 시스템
    • 인스턴스 로고 (로그인/가입 페이지에 표시되는 로고)
    • 헤더 로고 (내비게이션 바에 표시되는 로고)
  • 그룹
    • 그룹 아바타
  • 사용자
    • 사용자 아바타
    • 사용자 스니펫 첨부 파일
  • 프로젝트
    • 프로젝트 아바타
    • 이슈/MR/노트의 마크다운 첨부 파일
    • 이슈/MR/노트의 레거시 마크다운 첨부 파일
    • CI 아티팩트 (아카이브, 메타데이터, 트레이스)
    • LFS 오브젝트
    • 머지 리퀘스트 차이
    • 디자인 관리 디자인 섬네일
  • 토픽
    • 토픽 아바타

디스크 저장

GitLab은 모든 것을 로컬 디스크에 저장하기 시작했습니다. 이전 버전에서 디렉토리 위치가 변경되었지만, 아직 100% 표준화되지는 않았습니다. 아래에서 확인할 수 있습니다:

설명 DB에 있음? 상대 경로 (CarrierWave.root에서) 업로더 클래스 모델 유형
인스턴스 로고 uploads/-/system/appearance/logo/:id/:filename AttachmentUploader Appearance
헤더 로고 uploads/-/system/appearance/header_logo/:id/:filename AttachmentUploader Appearance
그룹 아바타 uploads/-/system/group/avatar/:id/:filename AvatarUploader Group
사용자 아바타 uploads/-/system/user/avatar/:id/:filename AvatarUploader User
사용자 스니펫 첨부 파일 uploads/-/system/personal_snippet/:id/:random_hex/:filename PersonalFileUploader Snippet
프로젝트 아바타 uploads/-/system/project/avatar/:id/:filename AvatarUploader Project
토픽 아바타 uploads/-/system/projects/topic/avatar/:id/:filename AvatarUploader Topic
이슈/MR/노트 마크다운 첨부 파일 uploads/:project_path_with_namespace/:random_hex/:filename FileUploader Project
이슈/MR/노트 레거시 마크다운 첨부 파일 아니오 uploads/-/system/note/attachment/:id/:filename AttachmentUploader Note
디자인 관리 디자인 썸네일 uploads/-/system/design_management/action/image_v432x230/:id/:filename DesignManagement::DesignV432x230Uploader DesignManagement::Action
CI 아티팩트 (CE) shared/artifacts/:disk_hash[0..1]/:disk_hash[2..3]/:disk_hash/:year_:month_:date/:job_id/:job_artifact_id (:disk_hashproject_id의 SHA256 다이제스트) JobArtifactUploader Ci::JobArtifact
LFS 오브젝트 (CE) shared/lfs-objects/:hex/:hex/:object_hash LfsObjectUploader LfsObject
외부 머지 리퀘스트 차이 shared/external-diffs/merge_request_diffs/mr-:parent_id/diff-:id ExternalDiffUploader MergeRequestDiff
이슈어블 메트릭 이미지 uploads/-/system/issuable_metric_image/file/:id/:filename IssuableMetricImageUploader IssuableMetricImage

CI 아티팩트 및 LFS 오브젝트는 CE 및 EE에서 다르게 작동합니다. CE에서는 GitlabUploader를 상속받지만, EE에서는 ObjectStorage를 상속받아 S3 API 호환 오브젝트 스토어에 파일을 저장합니다.

이슈/MR/노트 마크다운 첨부 파일의 경우, 해시된 저장소 레이아웃을 사용하여 다른 접근 방식이 있으며, 가변 변수 :project_path_with_namespace을 기반으로 하는 대신 프로젝트 ID의 해시를 사용할 수 있습니다. 이 접근 방식은 새로운 접근 방식으로 마이그레이션할 경우(10.2에서 도입됨) 가능합니다.

일괄 Rake 작업을 제공하여 한 번에 모든 업로드를 객체 스토리지로 마이그레이션할 수 있습니다. 새로운 업로더 클래스나 모델 유형이 도입되면, 해당하는 Rake 작업 호출을 카테고리 목록에 추가해야 합니다.

경로 세그먼트

파일은 여러 위치에 저장되며 다른 경로 체계를 사용합니다. 모든 GitlabUploader 파생 클래스는 이 경로 세그먼트 스키마를 준수해아 합니다.

|   GitlabUploader
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `<gitlab_root>/public/` | `uploads/-/system/`       | `user/avatar/:id/`                | `:filename`                      |
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `CarrierWave.root`      | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment`  | `CarrierWave::Uploader#filename` |
|                         | `CarrierWave::Uploader#store_dir`                             |                                  |

|   FileUploader
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `<gitlab_root>/shared/` | `artifacts/`              | `:year_:month/:id`                | `:filename`                      |
| `<gitlab_root>/shared/` | `snippets/`               | `:secret/`                        | `:filename`                      |
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `CarrierWave.root`      | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment`  | `CarrierWave::Uploader#filename` |
|                         | `CarrierWave::Uploader#store_dir`                             |                                  |
|                         |                           | `FileUploader#upload_path                                            |

|   ObjectStore::Concern (store = remote)
| ----------------------- + ------------------------- + ----------------------------------- + -------------------------------- |
| `<bucket_name>`         | <ignored>                 | `user/avatar/:id/`                  | `:filename`                      |
| ----------------------- + ------------------------- + ----------------------------------- + -------------------------------- |
| `#fog_dir`              | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment`    | `CarrierWave::Uploader#filename` |
|                         |                           | `ObjectStorage::Concern#store_dir`  |                                  |
|                         |                           | `ObjectStorage::Concern#upload_path                                    |

RecordsUploads::Concern concern은 GitlabUploader에 의해 저장된 파일마다 GitlabUploader#dynamic_path를 사용하여 경로의 동적 부분을 지속합니다. 그런 다음 Upload#build_uploader 메서드를 사용하여 파일을 조작할 수 있습니다.

객체 스토리지

GitlabUploader 파생 클래스에 ObjectStorage::Concern을 포함하면이 업로더를위한 객체 스토리지를 활성화 할 수 있습니다. 업로더에 객체 스토리지를 활성화하려면 1) RecordsUpload::Concern를 포함하고 ObjectStorage::Extension::RecordsUploads를 먼저 삽입하거나 2) 업로더를 마운트하고 새로운 필드를 <mount>_store라는 이름으로 만들어야 합니다.

CarrierWave::Uploader#store_dir는 다음과 같이 재정의됩니다.

  • 저장소가 LOCAL 인 경우 GitlabUploader.base_dir + GitlabUploader.dynamic_segment
  • 저장소가 REMOTE인 경우 GitlabUploader.dynamic_segment (버킷 이름은 이름 공간으로 사용됨)

ObjectStorage::Extension::RecordsUploads 사용

이 concern은 이미 포함되지 않은 경우 RecordsUploads::Concern을 포함합니다.

ObjectStorage::Concern 업로더는 일치하는 Upload을 찾아 올바른 객체 저장소를 선택합니다. Upload는 각 저장소 (LOCAL/REMOTE)마다 #store_dirs + identifier를 사용하여 매핑됩니다.

class SongUploader < GitlabUploader
  include RecordsUploads::Concern
  include ObjectStorage::Concern
  prepend ObjectStorage::Extension::RecordsUploads

  ...
end

class Thing < ActiveRecord::Base
  mount :theme, SongUploader # 멋진 테마 송을 갖고 있습니다!

  ...
end

마운트된 업로더 사용

ObjectStorage::Concernmodel.<mount>_store 속성을 쿼리하여 올바른 객체 저장소를 선택합니다. 이 열은 모델 스키마에 있어야합니다.

class SongUploader < GitlabUploader
  include ObjectStorage::Concern

  ...
end

class Thing < ActiveRecord::Base
  attr_reader :theme_store # 이것은 ActiveRecord 속성입니다.
  mount :theme, SongUploader # 멋진 테마 송을 갖고 있습니다!

  def theme_store
    super || ObjectStorage::Store::LOCAL
  end

  ...
end