This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned on this page are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
implemented @jdrpereira @glopezfernandez @trizzi @hswimelar devops package 2020-09-29

컨테이너 레지스트리 메타데이터 데이터베이스

GitLab 컨테이너 레지스트리 사용

GitLab에 통합된 컨테이너 레지스트리를 사용하면 모든 GitLab 프로젝트는 자체 도커 이미지를 저장할 공간을 갖게 됩니다. 레지스트리를 사용하여 도커 클라이언트, CI/CD 또는 GitLab API를 사용하여 이미지를 빌드, 푸시 및 공유할 수 있습니다.

매일 GitLab.com에서 150k to 200k 이미지가 레지스트리에 푸시되며, 약 700k API 이벤트가 생성됩니다. 또한, 다른 레지스트리 공급 업체를 사용하는 고객도 있지만, 96% 이상의 사례가 GitLab 컨테이너 레지스트리를 사용하고 있다는 사실 역시 주목할 가치가 있습니다.

GitLab.com 및 GitLab 고객을 위해 컨테이너 레지스트리는 소프트웨어를 빌드하고 배포하는 데 중요한 구성 요소입니다.

현재 아키텍처

컨테이너 레지스트리는 단일 Go 어플리케이션입니다. 유일한 종속성은 이미지와 메타데이터가 저장되는 저장소 백엔드입니다.

graph LR C((클라이언트)) -- HTTP 요청 --> R(컨테이너 레지스트리) -- 블롭 업로드/다운로드 --> B(저장소 백엔드) R -- 메타데이터 쓰기/읽기 --> B

클라이언트 응용프로그램(예: GitLab Rails 및 Docker CLI)은 컨테이너 레지스트리와 HTTP API를 통해 상호 작용합니다. 가장 일반적인 작업은 레지스트리에 이미지를 푸시하거나 풀링하는 것으로, 이를 위해서는 특정한 순서로 일련의 HTTP 요청이 필요합니다. 이러한 작업의 요청 흐름은 요청 흐름에서 자세히 설명되어 있습니다.

이 레지스트리는 Google Cloud Storage (GCS)를 비롯한 여러 저장소 백엔드를 지원하며, GitLab.com 레지스트리에는 GCS가 사용됩니다. 저장소 백엔드에서 이미지는 블롭으로 저장되고 중복이 제거되며, 저장소 간에 공유됩니다. 그런 다음 필요한 저장소에 대해 (심볼릭 링크와 같이) 각 저장소에 연결되어 중앙 저장 위치에 액세스할 수 있습니다.

저장소의 이름, 계층 구조, 이미지 매니페스트 및 태그도 저장소 백엔드에 저장되며, 중첩된 폴더 및 파일 구조로 표시됩니다. 이 비디오에서 레지스트리 저장소 구조에 대해 실제로 살펴볼 수 있습니다.

클라이언트

컨테이너 레지스트리에는 두 가지 주요 클라이언트가 있습니다: GitLab Rails 어플리케이션 및 Docker 클라이언트/CLI.

Docker

Docker 클라이언트(docker CLI)는 GitLab 컨테이너 레지스트리와 주로 로그인, 푸시 명령을 사용하여 상호 작용합니다.

로그인 및 인증

GitLab Rails는 GitLab 컨테이너 레지스트리의 기본 토큰 기반 인증 공급자입니다.

레지스트리가 인증되지 않은 Docker 클라이언트로부터의 요청을 받으면 401 Unauthorized로 응답하고, 클라이언트에게 GitLab Rails API에서 토큰을 얻을 수 있는 위치(예: https://gitlab.example.com/jwt/auth)를 알려줍니다. 그런 다음 Docker 클라이언트는 Bearer 토큰을 요청하고 모든 요청의 Authorization 헤더에 내장합니다. 레지스트리는 제공된 토큰을 기반으로 사용자가 해당 요청을 수행할 수 있는지를 결정하는 책임이 있습니다.

sequenceDiagram participant C as Docker 클라이언트 participant R as GitLab 컨테이너 레지스트리 participant G as GitLab Rails C->>R: docker login gitlab.example.com R->>C: 401 Unauthorized Note left of R: 응답에는 토큰을 얻을 수 있는 경위(예: https://gitlab.example.com/jwt/auth)가 포함됩니다 C->>G: Bearer 토큰 획득 G->>C: 200 OK C-->>R: 푸시/풀 요청 Note right of C: 'Authorization' 헤더에 Bearer 토큰이 포함됨

자세한 내용은 Docker 문서를 참조하십시오.

푸시 및 풀

푸시 및 풀 명령은 이미지(매니페스트 및 블롭)를 업로드하고 다운로드하는 데 사용됩니다. 푸시/풀 흐름은 문서에 설명되어 있습니다.

GitLab Rails

GitLab Rails은 레지스트리와 HTTP API를 통해 상호 작용하고 웹훅 알림을 구독합니다.

GitLab Rails에서 레지스트리로

레지스트리의 단일 엔트리포인트는 HTTP API입니다. GitLab Rails은 이 API를 호출하여 다음 작업을 수행합니다.

작업 UI 백그라운드 관찰사항
API 버전 확인 Yes Yes 레지스트리가 Docker Distribution V2 API를 지원하는지 확인하고 GitLab Rails가 GitLab 컨테이너 레지스트리 또는 제3자 레지스트리에 연결되어 있는지 확인하는 데 전역적으로 사용됩니다(전자에서만 사용 가능한 기능을 전환하는 데 사용됨).
저장소 태그 목록 Yes Yes UI에서 태그를 나열하고 표시하는 데 사용됩니다. 정리 정책Geo 복제를 위해 백그라운드에서 태그를 나열하는 데 사용됩니다.
매니페스트 존재 여부 확인 Yes No 태그별로 매니페스트의 다이제스트를 가져오는 데 사용됩니다. 그런 다음 이를 사용하여 UI에서 매니페스트를 끌어오고 태그 세부 정보를 표시합니다.
매니페스트 끌어오기 Yes No UI에서 이미지 크기와 매니페스트 다이제스트를 표시하는 데 사용됩니다.
블롭 끌어오기 Yes No UI에서 구성 다이제스트와 작성 날짜를 표시하는 데 사용됩니다.
태그 삭제 Yes Yes UI 및 백그라운드(정리 정책)에서 태그를 삭제하는 데 사용됩니다.

유효한 인증 토큰은 GitLab Rails에서 생성되고 이러한 요청에 삽입되어 레지스트리로 전송됩니다.

레지스트리에서 GitLab Rails로

레지스트리는 웹훅 알림을 지원하여 이미지 푸시와 같은 이벤트가 발생할 때 외부 애플리케이션에 알립니다.

GitLab의 경우, 레지스트리는 현재 이미지 푸시 이벤트에 대한 알림을 GitLab Rails API로 전달하도록 구성되어 있습니다. 이러한 알림은 현재 Snowplow 지표 및 Geo 복제에 사용됩니다.

도전 과제

가비지 컬렉션

컨테이너 레지스트리는 오프라인 마크스윕 가비지 컬렉션 (GC) 알고리즘에 의존합니다. 실행하려면 레지스트리를 종료하거나 읽기 전용으로 설정한 상태를 유지해야 합니다.

마크 단계에서 레지스트리는 모든 저장소를 분석하고 각 저장소에 참조/링크된 구성, 레이어 및 매니페스트 목록을 작성합니다. 그런 다음 레지스트리는 모든 기존 구성, 레이어 및 매니페스트를 나열하고 이들 중 어느 것도 저장소에서 참조되거나 연결되지 않은 목록을 가져옵니다. 이는 삭제할 수 있는 블롭의 목록입니다.

마크 단계의 출력을 사용하여 레지스트리는 스윕 단계를 시작하며 이 단계에서는 삭제할 수 있는 블롭을 하나씩 저장소 백엔드에서 루핑하며 제거합니다.

대규모 레지스트리의 경우 이 작업을 완료하는 데 여러 시간/일이 소요될 수 있으며 이 기간 동안 레지스트리는 읽기 전용으로 유지해야 합니다. 이는 GitLab.com과 같은 시간 대의 사용 가능성 요구 사항이 엄격한 플랫폼에서 실행하기 어려운 작업입니다.

이 제한 사항은 상류 Docker Distribution 문서에서도 설명되어 있습니다.

성능

현재 아키텍처 및 저장소 백엔드를 통한 저장소 및 이미지 메타데이터 저장에 의존하기 때문에 저장소가 커짐에 따라 기본 작업, 예를 들어 저장소 또는 태그를 나열하는 것조차 매우 느려질 수 있습니다.

예를 들어, 어떤 저장소가 존재하는지 알아내려면 레지스트리는 저장소 백엔드의 모든 폴더를 훑어야 하고 이들에서 저장소를 식별해야 합니다. 존재하는 모든 폴더를 방문한 후에 레지스트리는 목록을 클라이언트에게 응답할 수 있습니다. 원격 저장소 백엔드(예: GCS 또는 S3와 같은)를 사용할 경우 여러 HTTP 요청을 사용하여 각 방문한 폴더를 나열하고 검사해야 하므로 성능이 더욱 나빠집니다.

일관성

일부 저장 백엔드(예: S3)는 최종 일관성만 제공할 수 있습니다. 예를 들어, 블롭을 삭제한 후에도 잠시 동안 블롭을 읽는 것이 성공할 수 있습니다. 온라인 가비지 수집과 함께 최종 일관성은 삭제된 블롭에 대한 API 수준의 읽기 요청이 계속해서 성공할 수 있기 때문에 문제가 될 수 있습니다.

통찰

위에서 강조한 이유와 유사하게 현재는 레지스트리에서 리포지토리가 사용하는 공간의 양, 어떤 리포지토리가 가장 많은 공간을 사용하고, 어떤 것이 더 활발하며 각 이미지 또는 태그에 대한 자세한 푸시/풀 메트릭과 같은 가치 있는 정보를 추출하는 것이 현실적이지 않습니다. 이러한 통찰과 메트릭에 접근할 수 없는 것은 제품 전략에 대한 판단을 내릴 수 있는 능력을 크게 약화시킵니다.

추가 기능

현재 메타데이터의 제한으로 HTTP API의 페이징, 필터링 및 정렬과 Docker 및 Helm 차트 이미지를 구분할 수 있는 더 고급 기능과 같은 가치 있는 기능을 구현하는 것이 현실적이지 않습니다. 이러한 제약 때문에 우리는 이러한 기초적인 제한을 극복할 수 있는 해결책이 나올 때까지 새로운 기능의 개발을 중단하기로 결정했습니다.

새 아키텍처

위에서 설명한 모든 도전을 극복하기 위해 레지스트리 메타데이터(블롭 목록, 리포지토리, 각각의 매니페스트/레이어가 어느 것에 참조되거나 연결되었는지)를 저장 백엔드에서 PostgreSQL 데이터베이스로 이전하는 노력을 시작했습니다.

새 아키텍처의 궁극적인 목표는 온라인 가비지 수집을 가능케 하는 것입니다(&2313). 그러나 데이터베이스가 준비되면 메타데이터 제한으로 막힌 모든 기능을 구현할 수 있게 될 것입니다. 기존 API의 성능도 급격히 향상될 것입니다.

데이터베이스의 도입으로 레지스트리 아키텍처가 변화하며 아래와 같은 하나의 구성 요소가 더 추가될 것입니다:

graph LR C((클라이언트)) -- HTTP 요청 --> R(컨테이너 레지스트리) -- 블롭 업로드/다운로드 --> B(저장 백엔드) R -- 메타데이터 쓰기/읽기 --> D[(데이터베이스)]

데이터베이스가 준비되면 레지스트리는 메타데이터를 쓰거나 읽기 위해 저장 백엔드를 사용하지 않을 것입니다. 대신 메타데이터는 PostgreSQL 데이터베이스에 저장되고 조작될 것입니다. 저장 백엔드는 블롭을 업로드하고 다운로드하는 데에만 사용될 것입니다.

GitLab Rails 및 Docker 클라이언트를 포함한 레지스트리와 그 클라이언트 간의 상호 작용은 현재 아키텍처에서 문서화된 것과 동일할 것입니다. 아키텍처 변경 및 데이터베이스는 내부적인 것입니다. 레지스트리 HTTP API와 웹훅 알림도 변경되지 않을 것입니다.

데이터베이스

GitLab Go 표준 및 스타일 가이드를 준수하여 데이터베이스를 관리하기 위해 ORM을 사용하지 않고 Go 표준 라이브러리의 database/sql 패키지, PostgreSQL 드라이버인 lib/pq, 그리고 원시 SQL 쿼리만을 사용합니다. 또한 데이터베이스 관리에 필요한 도구류를 개발해야 할 것입니다.

온라인포스트 배포 마이그레이션은 이미 레지스트리 CLI에서 지원되고 있으며, 이에 대한 설명은 문서에 나와 있습니다.

파티셔닝

레지스트리 데이터베이스는 성능을 향상시키기 위해 처음부터 파티셔닝될 것입니다(데이터 양을 제한하고 병렬 실행을 가능케하여 유지보수를 용이하게 하고 파티션 독립성으로 고가용성을 실현합니다). 데이터베이스를 처음부터 파티셔닝함으로써 필요할 경우 이후에 샤딩을 용이하게 할 수도 있습니다.

블롭은 리포지토리 간에 공유되지만, 매니페스트와 태그의 메타데이터는 리포지토리별로 범위가 지정됩니다. API 수준에서도 리포지토리 목록 만(제외)이 아닌 모든 쓰기와 읽기 요청이 리포지토리별로 범위가 지정됩니다. 이에 따라 액세스 패턴을 식별한 후, 매니페스트와 태그를 리포지토리별로, 블롭을 다이제스트별로 파티셔닝하기로 결정하여 조회가 항상 최적의 성능으로 이루어지도록 했습니다. 최초 버전의 파티셔닝된 스키마에 대한 설명은 병합 요청에서 문서화되었습니다.

GitLab.com

GitLab.com의 규모, 성능 및 격리 문제로 인해 레지스트리 데이터베이스는 별도의 전용 PostgreSQL 클러스터에 있게 될 것입니다. 추가 정보는 #93GitLab-com/gl-infra/reliability#10109를 참조하십시오.

다음 다이어그램은 데이터베이스 클러스터의 아키텍처를 보여줍니다:

GitLab.com 데이터베이스 아키텍처

예상 요구르 및 크기

GitLab.com 데이터베이스의 요구 사항은 dev.gitlab.org 레지스트리를 기반으로 추정되었으며 링크된 이슈에서 확인할 수 있습니다.

Self-managed 인스턴스

Self-managed 인스턴스의 경우, 레지스트리는 기본적으로 GitLab 데이터베이스와 동일한 PostgreSQL 인스턴스/클러스터에 별도의 논리적 데이터베이스를 가질 것입니다. 그러나 필요에 따라 레지스트리를 별도의 인스턴스/클러스터로 구성하는 것도 가능할 것입니다.

PostgreSQL

초기 데이터베이스 스키마에 관한 토의 중에 주로 다른 데이터베이스 엔진 대신에 PostgreSQL을 선택하기로 결정한 이유는 주로 다음과 같습니다:

  • RDBMS의 ACID 보증 및 파티셔닝을 포함한 필요한 모든 기능을 제공합니다;
  • 이미 GitLab에서 사용 중이므로 필요한 경험과 관리를 위한 도구가 이미 마련되어 있습니다;
  • Self-managed 고객에게 이미 가지고 있는 GitLab을 위한 PostgreSQL 인스턴스 내에서 레지스트리 데이터베이스를 호스팅할 수 있는 가능성을 제공하고 싶습니다.
버전 12

PostgreSQL의 버전 12에서 파티셔닝에 대한 중요한 개선 사항이 소개되었는데, 그 중에서는 다음을 강조합니다:

  • 이제 외래 키가 파티션 된 테이블을 참조할 수 있게 되었습니다. 이것은 이 프로젝트에 있어 일관성과 무결성을 보장할 뿐만 아니라 데이터베이스 수준에서의 캐스케이드된 삭제를 가능하게 합니다;
  • Inserts, selects 및 updates에 대한 주요 성능 향상 및 적은 잠금 및 대규모 파티션에 대한 일관된 성능을 제공함으로써 일반적인 성능 개선이 이뤄졌습니다 (벤치마크);
  • 기존의 많은 파티션을 가진 테이블에 대한 계획 알고리즘에 대한 주요 개선이 이뤄졌으며, 일부 테스트에서 최대 10,000 배까지의 가속을 찾아내는 것도 있습니다 (출처);
  • 기존 테이블에 새로운 파티션을 추가하는 것은 이제 전체 테이블을 잠그지 않아도 됩니다;
  • Bulk load (COPY)는 이제 한 번에 한 행씩 삽입하는 것이 아니라 대량 삽입을 사용하게 되었습니다;

이러한 기능과 성능 개선을 활용하기 위해 처음부터 PostgreSQL 12를 사용해야 합니다. GitLab 14.0 이상부터는 PostgreSQL 12가 함께 제공됩니다. PostgreSQL 12로 업그레이드할 수 없는 고객에게는 두 가지 옵션이 있습니다:

  • 관리자는 레지스트리를 위한 별도의 PostgreSQL 12 데이터베이스를 수동으로 프로비저닝하고 구성할 수 있습니다. 이를 통해 새로운 레지스트리 및 해당 메타데이터 데이터베이스에서 제공하는 기능을 활용할 수 있습니다.
  • 온라인 가비지 수집이 관련이 없거나 별도의 데이터베이스를 프로비저닝할 수 없는 경우, 현재 버전의 레지스트리를 계속 사용할 수 있습니다. GitLab은 현재 버전을 보안 역전 및 버그 수정으로 지원합니다.

온라인 가비지 수집 이외에도 메타데이터 데이터베이스의 가용성은 GitLab 컨테이너 레지스트리에 대한 많은 요청된 기능들의 구현을 허용합니다. 이러한 기능들은 새로운 버전을 사용하는 인스턴스에서만 사용할 수 있습니다.

가용성

인증 서비스 및 블롭 저장소 백엔드 외에도, 레지스트리는 새로운 아키텍처에서 한 가지 종속성을 더 얻습니다 - 데이터베이스. 레지스트리는 종속성과 같이 신뢰할 수 있는만큼만 가용할 수 있기 때문에, 데이터베이스 배포는 고가용성을 위해 예상되어야 합니다. 점진적인 마이그레이션 방식은 고가용성 환경에서의 구현 및 리소스 제약 사항을 식별하고 완화하는 데 도움이 될 것입니다.

HTTP API

다음은 레지스트리 HTTP API 작업과 그것들이 저장소 백엔드 및 새 데이터베이스에 얼마나 의존하는지에 대한 목록입니다. 요청을 처리할 때, 레지스트리는 어떤 종속성이 사용 불가능하면 오류 응답을 반환할 것입니다.

작업 방법 경로 데이터베이스 요구 저장소 요구 GitLab Rails에서 사용 *
API 버전 확인 GET /v2/ 아니요 아니요
저장소 목록 GET /v2/_catalog 아니요 아니요
저장소 태그 목록 GET /v2/<name>/tags/list 아니요
태그 삭제 DELETE /v2/<name>/manifests/<reference> 아니요
매니페스트 존재 확인 HEAD /v2/<name>/manifests/<reference> 아니요
매니페스트 가져오기 GET /v2/<name>/manifests/<reference> 아니요
매니페스트 푸시 PUT /v2/<name>/manifests/<reference> 아니요 아니요
매니페스트 삭제 DELETE /v2/<name>/manifests/<reference> 아니요 아니요
블롭 존재 확인 HEAD /v2/<name>/blobs/<digest> 아니요 아니요
블롭 가져오기 GET /v2/<name>/blobs/<digest>
블롭 삭제 DELETE /v2/<name>/blobs/<digest> 아니요 아니요
블롭 업로드 시작 POST /v2/<name>/blobs/uploads/ 아니요
블롭 업로드 상태 확인 GET /v2/<name>/blobs/uploads/<uuid> 아니요
블롭 청크 푸시 PATCH /v2/<name>/blobs/uploads/<uuid> 아니요
블롭 업로드 완료 PUT /v2/<name>/blobs/uploads/<uuid> 아니요
블롭 업로드 취소 DELETE /v2/<name>/blobs/uploads/<uuid> 아니요

* GitLab Rails에서 레지스트리로의 상호 작용 목록을 참조하여 그 이유와 방법을 알아보십시오.

실패 시나리오

데이터베이스 추가로 인해 가능한 실패 시나리오를 강조하고, 해당 조건에서 레지스트리가 어떻게 동작할 것으로 예상되는지, 그리고 레지스트리의 가용성과 기능에 미치는 영향을 설명하는 것이 중요합니다.

데이터베이스 장애 조치

데이터베이스에 연결을 시도하는 동안 거부된 연결 또는 타임아웃이 발생할 수 있는 경우(장애 조치 시나리오), 레지스트리는 먼저 끊어진 연결을 폐기하고 풀에서 즉시 새 연결을 시도합니다.

이 시나리오에서 애플리케이션은 패닉 상태에 빠지지 않습니다. 각 요청에 대해 새 연결을 시도합니다. 실패한 경우, HTTP 503 Service Unavailable 오류가 클라이언트에 반환되고, 오류는 로그에 기록되어 Sentry에 보고됩니다. 재시도 주기는 없습니다. 레지스트리는 데이터베이스 액세스를 필요로 하는 다른 요청이 수신될 때만 새 연결을 시도합니다.

또한, TCP 건강 검사기를 사용하여 데이터베이스 서버의 건강 상태를 주기적으로 확인하도록 레지스트리를 구성하는 것도 가능합니다. 이를 통해 건강 검사 실패 시, 수신된 요청은 HTTP 503 Service Unavailable 오류와 함께 중지됩니다.

데이터베이스 서버가 다시 사용 가능한 경우, 레지스트리는 다음 수신된 요청에 대해 새 연결을 우아하게 재연결하여 인간의 개입 없이 전체 API 기능을 복원합니다.

예상되는 레지스트리 동작은 프로그램 가능한 TCP 프록시를 사용하여 레지스트리와 데이터베이스 서버 간의 장애 조치 시나리오를 모의하는 통합 테스트로 확인될 것입니다.

연결 풀 포화

특정 요청을 처리하기 위해 풀에서 연결을 가져올 수 없는 경우, 레지스트리는 타임아웃되어 클라이언트에게 HTTP 500 Internal Server Error 오류를 반환하고, 해당 오류를 Sentry에 보고합니다. 이러한 문제는 풀이 과도하게 소비되는 이유를 조사하기 위해 개발 단계를 거쳐야 합니다. 사전 구성된 풀 크기에 대한 부하가 너무 많이 걸리거나, 트랜잭션을 너무 오래 연결에 보유하고 있는 경우가 있을 수 있습니다.

애플리케이션이 오류를 반환하기 전에 가능한 포화에 대응하는 경고를 생성하기 위해 Prometheus 메트릭을 사용해야 합니다. GitLab.com 레지스트리의 점진적인 마이그레이션 중에 이러한 시나리오에 특별히 주의를 기울여야 합니다. 이 과정에서 사용 패턴을 식별하고 메트릭을 관찰하며 부하가 증가함에 따라 인프라 및 응용 프로그램 설정을 조정할 수 있습니다. 필요한 경우 영향을 제한하기 위해 속도 제한 알고리즘을 적용할 수 있습니다. 과도하게 제한적인 조치와 조기 최적화를 피하기 위해 실제 데이터를 기반으로 결정해야 합니다.

예상되는 레지스트리 동작은 풀 크기를 조절하고 API에 대해 여러 동시 요청을 생성하여 풀에 압력을 가하고, 결국 그 용량을 초과시키는 통합 테스트로 확인될 것입니다.

지연

확립된 연결에서의 과도한 지연은 일반적인 상황에서 응용 프로그램 오류나 네트워크 타임아웃을 유발하지 않을 수 있어서 탐지 및 디버깅하기 어렵습니다.

이러한 이유로 HTTP API 요청을 처리하는 데 사용되는 데이터베이스 쿼리의 지속 시간을 메트릭을 사용하여 측정하여, 비정상적인 변동을 감지하고 적절한 시점에 경고를 발생시켜 지나치게 지연이 타임아웃이나 서비스 사용 불능이 되기 전에 조치를 취할 수 있도록 해야 합니다.

예상되는 레지스트리 동작은 프로그램 가능한 TCP 프록시를 사용하여 레지스트리와 데이터베이스 서버 간의 지연 증가 시나리오를 모의하는 통합 테스트로 확인될 것입니다.

문제 있는 마이그레이션

네트워크 및 시스템의 비정상적인 조건 외에도, 문제 있는 마이그레이션 및 데이터 오류도 데이터베이스 가용성 및 따라서 레지스트리 가용성에 영향을 미칠 수 있습니다.

GitLab Rails를 위해 사용된 동일한 개발 최상의 사례를 따르되, 레지스트리는 Go 애플리케이션이므로 ORM 없이 순수한 SQL 문으로 마이그레이션이 표현될 것입니다. 그러나 모든 변경 사항은 데이터베이스 팀의 검토와 승인이 필요합니다.

데이터베이스 마이그레이션은 Idempotent하며, 필요할 때마다 가드 절을 사용합니다. 또한, 앞으로 대응되기를 보장하기도 합니다. 클러스터 환경에서 노드가 버전 N의 레지스트리를 실행하는 경우, 데이터베이스 스키마가 버전 N+1인 경우에 문제가 발생하지 않아야 합니다.

관측 가능성

시스템에 구성 요소를 추가하는 경우, 레지스트리의 동작 및 의존성에 대한 적절한 관측을 보장하는 것이 더욱 중요해집니다. 새 메타데이터 데이터베이스를 백업하는 새 레지스트리를 배포하기 전에 필요한 모든 도구가 있는지 보장해야 합니다.

이를 위해, Sentry를 사용한 오류 보고, 개선된 구조화된 로깅, 개선된 HTTP 메트릭이 이미 구현 및 릴리스되었습니다. 작성 당시, GitLab.com rollout이 진행 중입니다.

추가적으로, Prometheus 메트릭은 데이터베이스 연결 풀에 대한 자세한 정보로 보강됩니다. 이러한 메트릭은 기존의 HTTP API, 배포 및 저장 메트릭에 추가해서 레지스트리 Grafana 대시보드에 추가될 것입니다. 레지스트리의 데이터베이스 클러스터에는 메트릭과 경고도 적용될 것입니다.

이러한 자원을 통해 레지스트리의 성능과 동작에 대해 적절한 수준의 통찰력을 제공할 것으로 기대됩니다.

새로운 기능 및 판독 변경 사항

타사 컨테이너 레지스트리

GitLab은 기본적으로 GitLab 컨테이너 레지스트리를 함께 제공하지만, 도커 분배 V2 사양을 준수하는 경우 타사 레지스트리와 호환됩니다. 해당 사양은 이제 OCI(Open Container Initiative) 이미지 사양으로 대체되었습니다.

지금까지 새로운 기능을 추가할 때 타사 레지스트리와의 완전한 호환성을 유지하려고 노력해왔습니다. 예를 들어, 12.8에서는 태그 삭제 기능을 도입하여 배포된 매니페스트를 삭제하지 않고 단일 태그를 삭제했습니다. 이 기능은 Docker 또는 OCI 사양의 일부가 아니기 때문에 타사 레지스트리와의 호환성 유지를 위해 이전 동작을 대안 옵션으로 유지했습니다.

그러나 이는 향후 변경될 것으로 보입니다. 온라인 가비지 수집 외에도 도전 과제에서 설명한대로 메타데이터 데이터베이스는 GitLab 컨테이너 레지스트리의 많은 요청된 기능의 구현을 중장기적으로 가능케할 것으로 예상됩니다. 이러한 기능 대부분은 GitLab 컨테이너 레지스트리를 사용하는 인스턴스에서만 사용할 수 있을 것입니다. 이러한 기능은 Docker Distribution 또는 OCI 사양의 일부가 아니며 호환 대체 옵션을 제공할 수도 없을 것입니다.

이러한 이유로 GitLab 컨테이너 레지스트리를 사용해야 하는 기능은 타사 레지스트리를 사용하는 경우 비활성화될 것입니다. 당분간 타사 레지스트리가 지원되는 한.

GitLab Rails과의 변경 사항 동기화

현재, GitLab Rails와 GitLab 컨테이너 레지스트리의 릴리스 및 배포는 완전히 독립적으로 이루어졌으며, 위에서 설명한 태그 삭제 기능 외에는 새로운 API 기능이나 판독 변경 사항을 도입한 적이 없습니다.

레지스트리는 GitLab Rails 변경 사항과 독립적으로 유지될 것이지만, 중장기적으로 새로운 기능이나 판독 변경 사항의 구현은 GitLab Rails에 해당 레지스트리의 특정 최소 버전의 종속성을 의미할 것입니다.

예를 들어, 각 저장소의 크기를 추적하기 위해 메타데이터 데이터베이스를 확장하고 GitLab Rails에서 사용하는 HTTP API를 통해 정보를 전파할 수 있을 것입니다. GitLab Rails에서 이 새로운 정보는 해당 데이터베이스에 저장되어 UI/API 수준에서 새로운 기능을 제공하는 데 활용될 것입니다.

이러한 변경 사항은 GitLab Rails과 GitLab 컨테이너 레지스트리의 릴리스 및 배포 간에 동기화를 필요로 할 것이며, 전자는 후자의 특정 버전에 종속될 것입니다.

기능 토글

특정 레지스트리 버전에 의존하는 모든 GitLab Rails 기능은 레지스트리 공급업체 및 버전을 확인하여 보호되어야 합니다.

이미 이론상으로 이는 태그를 삭제해야 하는지 여부를 결정하기 위해 사용됩니다(이 기능은 GitLab 컨테이너 레지스트리 v2.8.1+에서만 사용 가능하며 이전 방법은 다른 대안입니다). 이 경우 GitLab Rails는 OPTIONS 요청을 레지스트리 태그 경로로 보내어 DELETE 방법을 지원하는지 여부를 확인합니다.

또는 장기적인 일반적인 해결책으로, 레지스트리 공급업체, 버전 및 지원되는 기능을 결정하고(마지막 두 항목은 공급업체가 GitLab일 경우에만 해당됨) GitLab Rails 데이터베이스에 유지해야 합니다. 이 정보는 실시간으로 기능을 전환하거나 가능한 경우 대체 방법으로 반환하는 데 사용될 수 있습니다. 이 접근 방식의 초기 구현은 #204839의 일환으로 소개되었습니다. 현재 이는 메트릭 목적으로만 사용되고 있습니다. 레지스트리가 핫 스왑될 수 있는 Self-Managed 인스턴스에서 버전 정보가 최신 상태로 유지되도록 보장하려면 추가 개선이 필요합니다.

릴리스 및 배포

위에서 설명한대로, 기능 토글은 릴리스 및 배포 간의 비동기화를 방지하여 GitLab Rails이 새로운 기능을 지원하는 레지스트리 버전이 아직 사용 가능하지 않은 경우에도 기능을 유지할 수 있도록 하는 마지막 수단을 제공합니다.

그러나 GitLab Rails 및 GitLab 컨테이너 레지스트리의 릴리스와 배포는 지연을 피하기 위해 동기화되어야 합니다. GitLab Rails과 달리, 레지스트리의 릴리스와 배포는 수동 프로세스이므로 유지자들은 GitLab Rails 변경 사항이 해당 레지스트리 변경 사항 이후에만 릴리스 및 배포되도록 보장해야 합니다.

이 프로세스를 강화하기 위한 해결책으로, GitLab Rails 코드베이스에 레지스트리의 최소 요구 버전을 포함한 파일을 추가할 수 있습니다. 변경에 따라 해당 파일을 업데이트하고, 특정 레지스트리 버전에 따라 의존성을 갖는 모든 변경 사항을 고려해야 합니다. GitLab Rails의 릴리스 및 배포 시에도 이를 고려하여 지정된 최소 요구 레지스트리 버전이 배포되기 전에 파이프라인이 단 한 번만 통과되도록 보장해야 합니다.

반복 과정

  1. 메타데이터 데이터베이스 스키마 설계;
  2. 데이터베이스를 사용하여 메타데이터 관리 지원 추가;
  3. 작은, 중간 및 큰 저장소의 마이그레이션을 용이하게하는 계획 및 도구 설계;
  4. 온라인 가비지 수집 구현;
  5. GitLab.com을 위한 스테이징 및 프로덕션용 데이터베이스 클러스터 만들기;
  6. GitLab.com을 위한 자동화된 배포 파이프라인 생성;
  7. 기존 레지스트리의 배포 및 점진적인 마이그레이션;
  8. Self-Managed 설치에 대한 메타데이터 데이터베이스 지원 전개.

모든 작업의 상세 목록 및 주기적인 진행 상황 업데이트는 에픽 &2313에서 찾을 수 있습니다.

관련 링크