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. The development, release, and timing of any products, features, or functionality may be subject to change or delay and 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 프로젝트가 자체 Docker 이미지를 저장할 수 있는 공간을 갖게 됩니다. 레지스트리를 사용하여 Docker 클라이언트, CI/CD 또는 GitLab API를 사용하여 이미지를 빌드, 푸시하고 공유할 수 있습니다.

매일 GitLab.com에는 150,000에서 200,000개의 이미지가 레지스트리에 푸시되며, 약 700,000개의 API 이벤트가 생성됩니다(https://app.periscopedata.com/app/gitlab/527857/Package-GitLab.com-Stage-Activity-Dashboard?widget=7601761&udv=0). 또한, 다른 레지스트리 공급업체를 사용하는 고객도 있지만, 96% 이상의 사례가 GitLab 컨테이너 레지스트리를 사용하고 있음을 유의해야 합니다.

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

현재 아키텍처

컨테이너 레지스트리는 Go 애플리케이션으로, 이미지와 메타데이터가 저장되는 스토리지 백엔드만을 의존합니다.

graph LR C((클라이언트)) -- HTTP 요청 --> R(컨테이너 레지스트리) -- Blob 업로드/다운로드 --> 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에서 토큰을 가져오도록 지시합니다. 그런 다음 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: 응답에는 토큰을 가져올 수 있는 Realm(예: 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 버전 확인 전역적으로 사용되며, 레지스트리가 Docker Distribution V2 API를 지원하는지 확인하고, GitLab Rails이 GitLab 컨테이너 레지스트리와 아닌 다른 상호 작용자와 특정 기능을 전용으로 토글하는 데 사용됨
리포지터리 태그 디렉터리 확인 UI에서 태그를 나열하고 표시하는 데 사용됨. 정리 정책Geo 복제를 위해 배경에서 태그를 나열하는 데 사용됨
매니페스트의 존재 여부 확인 아니오 태그별 매니페스트의 다이제스트를 가져오기 위해 사용됨. 이는 그런 다음 UI에서 매니페스트를 끌어오고 태그 세부 정보를 보여주는 데 사용됨
매니페스트 끌어오기 아니오 태그 세부 정보 UI에서 이미지 크기와 매니페스트 다이제스트를 표시하는 데 사용됨
블롭 끌어오기 아니오 태그 세부 정보 UI에서 구성 다이제스트와 생성 날짜를 표시하는 데 사용됨
태그 삭제 UI 및 배경에서(정리 정책) 태그 삭제에 사용됨

모든 이러한 요청 전에 GitLab Rails에서 유효한 인증 토큰이 생성되어 해당 요청에 포함됩니다.

레지스트리에서 GitLab Rails로

레지스트리는 이미지 푸시와 같은 이벤트가 발생할 때 외부 애플리케이션에 알림을 보내기 위해 웹훅 알림을 지원합니다.

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

도전과제

Garbage Collection

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

마크 단계에서 레지스트리는 모든 리포지터리를 분석하여 각 리포지터리에서 참조 또는 연결된 구성, 레이어 및 매니페스트의 디렉터리을 작성합니다. 그런 다음 레지스트리는 모든 기존 구성, 레이어 및 매니페스트(중앙에 저장됨)를 나열하고 어떤 리포지터리에도 참조 또는 연결되지 않은 것들의 디렉터리을 얻습니다. 이는 삭제할 수 있는 블롭의 디렉터리입니다.

마크 단계의 결과물을 통해 레지스트리는 스윕 단계를 시작하며, 여기서 삭제 가능한 모든 블롭을 하나씩 리포지터리 백엔드에서 삭제합니다.

대규모 레지스트리에 대해 이 작업을 완료하는 데는 여러 시간/일이 걸릴 수 있으며, 레지스트리는 읽기 전용 모드로 유지해야 합니다. GitLab.com과 같이 엄격한 가용성 요구 사항이 있는 플랫폼에는 불가능합니다.

이 제약은 상위 Docker Distribution 문서에서도 설명되어 있습니다.

성능

현재 아키텍처와 (가능한 원격) 리포지터리 백엔드에 대한 의존성으로 인해 리포지터리 또는 이미지 메타데이터와 같은 가장 기본적인 작업인 리포지터리 또는 태그 디렉터리 만들기와 같은 작업조차도 금지될 정도로 느려질 수 있으며, 레지스트리의 크기가 커질수록 더욱 심해집니다.

예를 들어 어떤 리포지터리가 있는지 확인하려면 레지스트리는 리포지터리 백엔드의 모든 폴더를 훑어가며 그 안의 리포지터리를 식별해야 합니다. 모든 폴더를 방문한 후에야 레지스트리가 클라이언트에게 리포지터리 디렉터리을 응답할 수 있습니다. 원격 리포지터리 백엔드(GCS 또는 S3와 같은)를 사용하는 경우 여러 HTTP 요청이 필요하므로 성능이 더욱 나빠집니다.

일관성

S3와 같은 일부 리포지터리 백엔드는 최종 일관성만 제공할 수 있습니다. 예를 들어 삭제한 후 블롭을 읽을 수 있는 경우가 짧은 시간 동안 발생할 수 있습니다. 최종 일관성은 API 수준의 읽기 요청이 삭제된 블롭에 대해 계속 성공할 수 있다는 문제점을 야기할 수 있습니다.

인텔리전스

위에서 강조한 이유로 현재 레지스트리에서 리포지터리가 사용하는 공간, 가장 많은 공간을 사용하는 리포지터리, 더 활발한 리포지터리, 각 이미지 또는 태그에 대한 자세한 푸시/풀 메트릭과 같은 가치 있는 정보를 추출하는 것은 현재 불가능합니다. 이러한 통찰력과 메트릭에 접근할 수 없는 것은 제품 전략에 대한 정보된 결정을 내릴 능력을 크게 약화시킵니다.

추가 기능

메타데이터 제약으로 인해 HTTP API에 대한 페이징, 필터링 및 정렬과 같은 가치 있는 기능을 구현하는 것은 현재 불가능합니다. 그리고 Docker 및 Helm 차트 이미지를 구분하는 기능과 같은 고급 기능을 포함하여 더 많은 고급 기능도 불가능합니다.

모든 이러한 제약 때문에 우리는 이러한 기본 제약을 극복할 솔루션이 마련될 때까지 새로운 기능의 개발을 중단하기로 결정했습니다.

새 아키텍처

위에서 설명한 모든 도전적제를 극복하기 위해, 우리는 레지스트리 메타데이터(블롭 디렉터리, 리포지터리 및 각각의 매니페스트/레이어에 참조/연결된 디렉터리)를 PostgreSQL 데이터베이스로 마이그레이션하기 위한 작업을 시작했습니다.

새 아키텍처의 궁극적인 목표는 온라인 가비지 수집을 가능하게 하는 것입니다 (&2313). 그러나 데이터베이스가 마련되면 메타데이터 제약에 의해 차단된 모든 기능을 구현할 수 있게 될 것입니다. 기존 API의 성능도 크게 향상될 것입니다.

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

레지스트리와 그 클라이언트(예: GitLab Rails 및 Docker 클라이언트) 간의 상호작용은 현재 아키텍처 섹션에 문서화된 것과 동일할 것입니다. 아키텍처 변경 및 데이터베이스는 내부적인 것으로만 제한될 것이며, 레지스트리 HTTP API 및 웹훅 알림도 그대로 유지될 것입니다.

데이터베이스

GitLab Go 표준 및 스타일 가이드에 따라 데이터베이스를 관리하는 데 ORM은 사용되지 않습니다. 대신 Go 표준 라이브러리의 database/sql 패키지, PostgreSQL 드라이버인 lib/pq 및 원시 SQL 쿼리만 사용됩니다. 데이터베이스를 지원하기 위해 필요한 Go 애플리케이션은 데이터베이스 마이그레이션을 실행하기 위해 개발될 것입니다.

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

파티셔닝

레지스트리 데이터베이스는 데이터 양을 제한하고 병렬 실행을 가능하게 하여 성능을 향상시키기 위해 시작부터 파티셔닝될 것입니다. 작은 단위로 테이블 및 인덱스를 분할하여 유지 관리를 쉽게 하고 파티션 독립성을 통해 고가용성을 제공합니다. 시작부터 데이터베이스를 파티셔닝함으로써 필요에 따라 후에 샤딩 구현을 용이하게할 수도 있습니다.

블롭은 리포지터리를 통해 공유되지만 매니페스트와 태그 메타데이터는 리포지터리별로 범위가 있습니다. 이는 API 수준에서도 나타나며, 모든 쓰기 및 읽기 요청(리포지터리 디렉터리 만들기를 제외)이 리포지터리별로 범위가 있으며, 해당 네임스페이스가 요청 URI의 일부임을 의미합니다. 따라서 액세스 패턴을 식별한 후에, 매니페스트와 태그를 리포지터리별로, 블롭을 다이제스트로 파티셔닝하기로 결정했습니다. 이를 통해 조회가 항상 최적의 성능으로 수행되도록 파티션 키로 수행될 것입니다. 파티셔닝된 스키마의 초기 버전은 Merge Request에 문서화되어 있습니다.

GitLab.com

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

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

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

예상 속도 및 크기 요구 사항

Ratesize 요구 사항은 dev.gitlab.org 레지스트리를 기반으로 추정되었으며, 관련된 이슈에서 확인할 수 있습니다.

Self-Managed 인스턴스

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

PostgreSQL

최초 데이터베이스 스키마의 토론 중 주로 다른 데이터베이스 엔진보다 PostgreSQL을 선택한 이유는 다음과 같습니다.

  • RDBMS의 ACID 보장과 파티셔닝을 포함한 필요한 모든 기능을 제공합니다.
  • 이미 GitLab에서 사용되고 있으므로 필요한 경험과 관리를 위한 도구가 갖춰져 있습니다.
  • Self-Managed 고객에게 이미 GitLab에 대한 PostgreSQL 인스턴스를 사용하여 레지스트리 데이터베이스를 호스팅할 수 있는 가능성을 제공하고자 합니다.
버전 12

PostgreSQL 12에서는 파티셔닝에 대한 중요한 개선 사항이 소개되었는데, 그 중 일부는 다음과 같습니다.

  • 이제 외래 키가 파티션된 테이블을 참조할 수 있습니다. 이것은 일관성과 무결성을 보장하는 데 있어 이 프로젝트에 대한 강력한 요구 사항이며 데이터베이스 수준에서의 연쇄적 삭제를 가능하게 합니다.
  • 많은 파티션의 대규모 삽입, 선택 및 업데이트에 대한 주요 성능 개선이 이루어졌으며 더 적은 잠금 및 대규모 파티션에 대해 일관된 성능을 제공합니다 (벤치마크 참조).
  • 대규모 파티션을 가진 테이블에 대한 계획 알고리즘에 대한 주요 개선이 이루어졌으며 일부 테스트에서 최대 10,000 배까지의 가속이 확인되었으며 (출처).
  • 기존 테이블에 새로운 파티션을 붙이는 것은 더 이상 전체 테이블을 잠그지 않아도 됩니다.
  • Bulk load(COPY)는 이제 한 번에 하나의 행을 삽입하는 대신 대량 삽입을 사용합니다.

이러한 기능 및 성능 개선을 활용하기 위해 시작부터 PostgreSQL 12를 사용해야 합니다. Self-Managed 인스턴스에 대해 GitLab 14.0 및 이후 버전에서는 PostgreSQL 12가 함께 제공됩니다. PostgreSQL 12로 업그레이드할 수 없는 고객에게 두 가지 옵션이 있습니다.

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

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

가용성

인증 서비스 및 블롭 리포지터리 백엔드 외에도 새로운 아키텍처에서 레지스트리는 하나의 더 많은 의존성을 얻고 있는데, 바로 데이터베이스입니다. 레지스트리는 의존성이 제공되는 한에만 신뢰할 수 있으므로 데이터베이스 배포는 고가용성으로 계획되어야 할 것입니다. 점진적인 이주 접근법은 고가용성 환경에 대한 구현 및 리소스 제약 사항을 식별하고 완화하는 데 도움이 될 것입니다.

HTTP API

레지스트리 HTTP API 작업 디렉터리과 리포지터리 백엔드 및 새 데이터베이스에 의존하는 방식을 보여주는 것입니다. 레지스트리는 요청 처리 시 사용할 수 없는 의존성이 있는 경우 오류 응답을 반환할 것입니다.

Operation Method Path Requires Database Requires Storage Used by GitLab Rails *
API 버전 확인 GET /v2/ No No Yes
리포지터리 디렉터리 GET /v2/_catalog Yes No No
리포지터리 태그 디렉터리 GET /v2/<name>/tags/list Yes No Yes
태그 삭제 DELETE /v2/<name>/manifests/<reference> Yes No Yes
매니페스트 존재 확인 HEAD /v2/<name>/manifests/<reference> Yes No Yes
매니페스트 가져오기 GET /v2/<name>/manifests/<reference> Yes No Yes
매니페스트 푸시 PUT /v2/<name>/manifests/<reference> Yes No No
매니페스트 삭제 DELETE /v2/<name>/manifests/<reference> Yes No No
블롭 존재 확인 HEAD /v2/<name>/blobs/<digest> Yes No No
블롭 가져오기 GET /v2/<name>/blobs/<digest> Yes Yes Yes
블롭 삭제 DELETE /v2/<name>/blobs/<digest> Yes No No
블롭 업로드 시작 POST /v2/<name>/blobs/uploads/ Yes Yes No
블롭 업로드 상태 확인 GET /v2/<name>/blobs/uploads/<uuid> Yes Yes No
블롭 청크 푸시 PATCH /v2/<name>/blobs/uploads/<uuid> Yes Yes No
블롭 업로드 완료 PUT /v2/<name>/blobs/uploads/<uuid> Yes Yes No
블롭 업로드 취소 DELETE /v2/<name>/blobs/uploads/<uuid> Yes Yes No

* 왜 그리고 어떻게에 대한 레지스트리 및 Rails 간 상호작용 디렉터리을 보려면 GitLab Rails에서 레지스트리까지를 참조하세요.

실패 시나리오

데이터베이스 추가로 인해 잠재적인 실패 시나리오를 강조하는 것이 중요합니다. 어떠한 상황에서 레지스트리의 동작이 예상대로 이루어지는지, 그것이 레지스트리의 가용성과 기능에 미치는 영향을 알아보는 것이 핵심입니다.

데이터베이스 장애 조치

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

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

TCP 건강 검사기를 사용하여 데이터베이스 서버의 건강 상태를 정기적으로 확인하도록 레지스트리를 구성할 수도 있습니다. 이는 구성 가능한 간격과 임계값을 갖는 TCP 건강 검사기를 사용하여 수행됩니다(문서). 건강 검사에 실패하는 경우, 수신되는 요청은 HTTP 503 Service Unavailable 오류로 중단됩니다.

데이터베이스 서버가 다시 이용 가능한 상태가 되면, 레지스트리는 다음 수신되는 요청에서 다음 들어오는 연결에 대해 응답을 정상적으로 재연결하여 API의 전체 기능을 복구합니다. 이러한 동작은 통합 테스트를 통해 확인될 것이며, 레지스트리와 데이터베이스 서버 간의 프로그래밍 가능한 TCP 프록시를 사용하여 장애 조치 시나리오를 시뮬레이션할 것입니다.

연결 풀 포화

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

응용 프로그램이 오류를 반환하기 전에 포화 상태에 대응하기 위해 Prometheus 메트릭을 사용하여 경고를 생성해야 합니다. 새로운 레지스트리 노드에 제한된 범위와 점진적인 노출을 가질 예정인 GitLab.com 레지스트리의 점진적인 이동 중에 이러한 시나리오에 주의를 기울여야 합니다. 이 과정에서 우리는 사용 패턴을 식별하고 메트릭을 관찰하며 부하가 증가함에 따라 인프라 및 응용 프로그램 설정을 조율할 것입니다. 필요한 경우, 영향을 제한하기 위해 속도 제한 알고리즘이 적용될 수 있습니다. 과도하게 제한적인 조치나 조기 최적화를 피하기 위해 실제 데이터를 기반으로 결정될 것입니다.

기존의 기능은 풀 크기를 조작하고 API에 대해 여러 동시 요청을 생성하여 테스트될 것입니다. 그 결과, 풀에 압력이 가해지고 결국 그 용량이 고갈될 것입니다.

지연

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

이러한 이유로 HTTP API 요청을 처리하는 데 사용되는 데이터베이스 쿼리의 기간을 지표화함으로써 비정상적인 변화를 감지하고 그에 따라 경고를 표시함으로써 과도한 지연이 타임아웃 또는 서비스 가용성으로 이어지기 전에 대응할 수 있어야 합니다.

예상된 레지스트리 동작은 테스트를 통해 확인될 것입니다. 데이터베이스 서버와 레지스트리 간의 프로그래밍 가능한 TCP 프록시를 사용하여 지연 시나리오를 시뮬레이션할 것입니다.

문제가 있는 마이그레이션

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

데이터베이스 마이그레이션은 GitLab Rails에서 사용된 개발 최선의 규칙과 동일하게 준수될 것입니다(개발 최선의 규칙). 단, 레지스트리는 ORM이 없는 Go 응용 프로그램이므로 마이그레이션은 원시 SQL 문으로 표현될 것입니다. 그러나 모든 변경 사항은 데이터베이스 팀의 리뷰와 승인이 필요합니다.

데이터베이스 마이그레이션이 멱등성을 가지며 필요할 때마다 가드 절을 사용하여 처리될 것입니다. 또한, 앞으로 호환 가능하도록 보장할 것입니다. 클러스터 환경에서 레지스트리 버전 N을 실행하는 노드가 데이터베이스 스키마가 버전 N+1인 경우 어떠한 이슈도 발생하지 않아야 합니다.

관측 가능성

시스템에 컴포넌트를 추가함으로써 레지스트리의 동작 및 의존성에 대한 적절한 관측 가능성을 보장하는 것이 더욱 중요해집니다. 새로운 메타데이터 데이터베이스로 백업된 새 레지스트리를 배포하기 전에 필요한 모든 도구를 갖추고 있는지 보장해야 합니다.

이를 위해 Sentry를 사용한 오류 보고개선된 구조화된 로깅, 그리고 개선된 HTTP 메트릭이 이미 구현 및 배포되었습니다. 글을 작성하는 시점에 따라, GitLab.com 배포가 진행 중입니다.

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

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

새로운 기능 및 팽패 변경

서드파티 컨테이너 레지스트리

GitLab은 기본적으로 GitLab 컨테이너 레지스트리와 함께 제공되지만, Docker Distribution V2 사양을 준수하는 한 제3자 레지스트리와 호환됩니다. 해당 사양은 이제 Open Container Initiative (OCI) 이미지 사양으로 대체되었습니다.

지금까지 새로운 기능을 추가할 때 제3자 레지스트리와의 완전한 호환성을 유지하기 위해 노력하고 있습니다. 예를 들어, 12.8 버전에서는 함께 배포된 manifest를 삭제하지 않고 단일 태그를 삭제하기 위한 태그 삭제 기능을 도입했습니다. 이 기능은 Docker 또는 OCI 사양의 일부가 아니기 때문에 제3자 레지스트리와의 호환성을 유지하기 위해 이전 동작을 유지했습니다.

그러나 이러한 상황은 향후 변경될 가능성이 있습니다. 온라인 가비지 컬렉션 외에도 도전 사항에서 설명한 대로 메타데이터 데이터베이스를 통해 GitLab 컨테이너 레지스트리에 대한 많은 요청된 기능의 구현을 가로막을 것으로 예상됩니다. 이러한 대부분의 기능은 GitLab 컨테이너 레지스트리를 사용하는 인스턴스에서만 사용할 수 있을 것입니다. 이러한 기능들은 Docker Distribution이나 OCI 사양의 일부가 아니며, 우리는 제3자 레지스트리와 호환되는 대체 옵션을 제공할 수 없을 것입니다.

이러한 이유로 GitLab 컨테이너 레지스트리의 사용을 요구하는 기능은 제3자 레지스트리를 사용하는 경우 비활성화되며, 제3자 레지스트리의 지원이 계속되는 한 계속 그렇게 유지될 것입니다.

GitLab Rails와의 변경 사항 동기화

현재 GitLab Rails와 GitLab 컨테이너 레지스트리의 릴리스 및 배포는 완전히 독립적으로 이루어져 왔습니다. 이전에 설명한 태그 삭제 기능을 제외하고 API 기능이나 팽패 변경 사항을 도입하지 않았기 때문입니다.

레지스트리는 GitLab Rails의 변경 사항에서 독립적으로 유지될 것이지만, 중장기적으로 새로운 기능이나 팽패 변경 사항을 구현할 경우 GitLab Rails와의 동기화가 요구될 것입니다. 이 경우, GitLab Rails가 레지스트리의 특정 최소 버전에 의존하게 될 것입니다.

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

이러한 변경 사항은 후방 호환성을 보장하기 위해 GitLab Rails에서 새로운 기능을 위해 필요한 특정 버전에 따라 레지스트리의 릴리스 및 배포 사이에 동기화가 필요할 것입니다.

기능 토글링

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에서 찾을 수 있습니다.

관련 링크