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
proposed @toon @mjwood @jcaigitlab devops systems 2023-08-04

번들-URI를 활용하여 Gitaly CPU 부하 감소

요약

bundle-URI는 Git에서 비교적 새로운 컨셉으로, 클라이언트가 남은 객체를 가져오기 전에 객체 데이터베이스를 미리 부트스트랩하기 위해 하나 이상의 번들을 다운로드할 수 있는 기능입니다. 클라이언트가 미리 간단한 HTTP(S) 서버에서 정적 파일을 다운로드함으로써 원격 측에서 수행해야 하는 작업을 줄일 수 있습니다.

Git 번들은 팩파일과 일부 추가 메타데이터(참조 세트 및 필요한 커밋 집합)를 저장하는 파일입니다. 사용자가 저장소를 복제할 때 서버는 이러한 번들을 제공하는 하나 이상의 URI를 광고할 수 있습니다. 클라이언트는 이를 다운로드하여 Git 객체 데이터베이스를 채울 수 있습니다. 이를 수행한 후, 서버와 클라이언트 간의 협상 프로세스가 시작되어 가져와야 하는 객체를 확인합니다. 클라이언트가 번들에서 데이터를 미리 채워넣었을 때, 서버의 객체 협상 및 전송이 줄어들어 서버의 CPU 부하가 덜어집니다.

동기

사용자가 변경 사항을 푸시하면 일반적으로 CI 파이프라인이 여러 작업을 실행합니다. CI 러너가 모두 저장소를 처음부터 복제할 때 git clone를 사용하면 서버와의 각각 협상을 시작합니다. 이는 서버에 대한 CPU 부하가 상당히 많이 발생합니다.

얼마 전에 우리는 pack-objects를 도입했으나 몇 가지 문제점이 있었습니다. 브랜치의 끝이 변경되면 새 팩파일을 계산하고 캐시를 새로 고쳐야 합니다.

Git 번들은 더 유연합니다. 번들에 가장 최신 객체가 모두 없어도 큰 문제가 되지 않습니다. 번들에 상당히 최근 상태가 포함되어 있지만 최신 참조가 누락된 경우 클라이언트(즉, CI 러너)가 “따라잡기”를 할 것이며 번들을 적용한 후 추가 객체를 가져올 것입니다. 번들에서 가져와야 하는 객체 집합은 훨씬 작아질 것입니다.

목표

클라이언트가 저장소를 복제할 때 Gitaly 서버에서 수행해야 하는 작업을 줄입니다. 이는 서버에 푸시된 각 커밋에서 생성되는 많은 트래픽을 생성하는 CI 빌드 파이프라인에 특히 유용합니다.

번들을 사용함으로써 서버는 번들을 사용하지 않을 때보다 더 작은 델타 팩파일을 만들어냅니다. 이로써 서버의 CPU 부하가 줄어듭니다. 팩파일 캐시에도 혜택이 있으며, 이제 팩파일이 더 작고 생성이 빨라졌기 때문에 캐시 미스의 가능성이 줄어듭니다.

비목표

번들-URI를 사용하더라도 저장소의 크기를 줄이지는 않습니다. 이 기능은 저장소의 데이터를 Gitaly 노드에서 클라우드 저장소로 완전히 또는 부분적으로 오프로드하지 않습니다. 오히려 번들은 다른 곳에 저장되기 때문에 일부 데이터가 중복되어 저장 비용이 증가합니다.

현재 단계에서는 점진적인 가져오기의 성능을 향상시키는 것이 목표가 아닙니다. 클라이언트가 이미 저장소를 복제한 경우 번들을 사용하여 새 데이터를 최적화하지 않습니다.

현재 번들-URI는 얕은 복제와 완전히 호환되지 않으므로 이 부분은 제외합니다. 관련 정보는 Git 이슈 #170에서 확인할 수 있습니다.

제안

클라이언트가 저장소를 복제할 때 Gitaly는 번들 URI를 광고합니다. 이 URI는 정기적으로 갱신되는 번들을 가리킵니다. 예를 들어, 정기적인 housekeeping 중에 새 번들이 생성되면 이전 번들이 무효화됩니다.

번들은 클라우드 객체 저장소에 저장될 것입니다. 번들을 사용하려면 관리자가 Gitaly에서 이를 구성해야 합니다.

설계 및 구현 세부사항

클라이언트가 git clone을 초기화할 때, 서버 측 Gitaly는 git upload-pack 프로세스를 생성합니다. Gitaly는 추가적인 Git 구성을 전달할 수 있습니다. git upload-pack이 번들 URI를 광고하려면 다음 구성을 전달해야 합니다:

  • uploadpack.advertiseBundleURIs :: 이 구성은 광고된 번들을 사용하도록 설정해야 합니다.
  • bundle.version :: 현재는 1만 허용됩니다.
  • bundle.mode :: any 또는 all 중 하나일 수 있습니다. 초기 복제에만 번들을 사용하고자 하는 것이므로 any가 권장됩니다.
  • bundle.<id>.uri :: 이것은 <id>로 식별된 번들의 실제 URI입니다. 처음에는 저장소당 하나의 번들만 가질 것입니다.

클라이언트 측에서 광고된 번들 사용 가능하게 하기

현재 버전의 Git은 원격에서 복제하거나 가져올 때 광고된 번들을 기본적으로 사용하지 않습니다. 다행히도, 대부분의 CI 러너를 우리가 직접 제어할 수 있습니다. 따라서 번들 URI를 사용하려면 러너에 의해 사용되는 Git 구성을 수정하고 transfer.bundleURI=true를 설정할 수 있습니다.

접근 제어

우리는 개인 저장소에서 데이터 유출을 원치 않습니다. 이를 극복할 수 있는 몇 가지 옵션이 있습니다:

  • 공개 저장소에서만 Bundle-URI 사용 활성화
  • signed-URLs와 같은 솔루션 사용

공개 저장소 전용

Gitaly 자체는 프로젝트와 해당 저장소가 공개인지를 알지 못합니다. 따라서 번들을 사용할 수 있는지 여부를 결정하기 위해 GitLab Rails가 Gitaly에게 알려주어야 합니다. 이 정보를 Gitaly에게 전달하는 것은 복잡하며, 이 방법을 사용하면 이 기능은 공개 프로젝트에서만 사용할 수 있게 됩니다. 따라서 이 솔루션을 진행하지 않겠습니다.

Signed URLs

signed-URLs의 사용은 번들에 대한 액세스를 제어하는 또 다른 옵션입니다. Google Cloud에서 제공하는 이 기능을 통해 Gitaly는 수명이 짧은 URI를 생성할 수 있습니다.

이 방법의 단점은 이것이 클라우드별로 다르게 제공되거나 제공되지 않을 수 있기 때문에, 각 클라우드 제공업체마다 이러한 기능이 약간 다르게 제공될 수 있다는 점입니다. 그러나 우리는 먼저 Google Cloud에서 호스팅되는 GitLab.com에 이 기능을 롤아웃하고자 합니다. 따라서 첫 번째 반복에서는 이를 사용하겠습니다.

번들 생성

서버 측 백업 사용

현재 Gitaly는 저장소를 클라우드 저장소에 번들로 백업하는 방법을 알고 있습니다. 이 문서에서 그 방법에 대해 설명하고 있습니다.

번들-URI의 초기 구현에서 우리는 이 기능을 도입할 것입니다. 관리자는 번들-URI를 사용할 저장소에 대해 백업을 생성해야 합니다. 기존의 백업 구성으로, Gitaly는 클라우드 저장소에 액세스할 수 있습니다.

정리 작업의 일환으로

Gitaly에는 매일 최적화할 저장소를 찾는 정리 작업 워커가 있습니다. 이상적으로는 정리(쓰레기 수집 및 다시 패킹)가 완료된 직후에 번들을 생성합니다. 이렇게 하면 가장 최적의 번들 파일을 확보할 수 있습니다.

번들을 자동으로 생성할 때 명심해야 할 몇 가지 사항이 있습니다:

  • 번들을 다시 생성해야 할 필요가 있는가? 저장소에 활동이 많지 않았다면 새로운 번들 파일을 생성할 필요가 없을 것입니다. 클라이언트는 어차피 Gitaly로부터 누락된 객체를 직접 가져올 수 있기 때문입니다. 정리 작업은 정리 작업을 위해 어떤 전략을 취할 지 결정하기 위해 다양한 휴리스틱을 사용합니다. 번들 생성에 이러한 로직의 일부를 재사용할 수 있습니다.
  • 번들을 생성할 필요가 있는가? 일부 저장소는 매우 작거나 활동이 매우 적을 수 있습니다. 이러한 저장소에 대해 번들을 생성하고 객체 저장소에 데이터를 복제하는 것은 큰 가치를 제공하지 않을 뿐만 아니라 비용과 유지관리만 발생시킬 뿐입니다.

GitLab Rails에 의해 제어됨

번들은 저장 공간에 대한 비용을 증가시키기 때문에, 최종적으로는 GitLab 관리자에게 번들 생성에 대한 완전한 제어권을 부여하고자 합니다. 이를 위해 번들-URI 설정은 GitLab 관리자 인터페이스에서 사용할 수 있게 될 것입니다. 여기서 관리자는 개별 프로젝트 단위로 번들-URI가 활성화된 저장소를 구성할 수 있습니다.

구성

이 기능을 사용하려면 Gitaly를 구성해야 합니다. 이를 위해 다음과 같은 설정을 Gitaly의 구성 파일에 추가할 것입니다:

  • bundle_uri.strategy :: 이는 번들-URI를 만들고 제공하는 데 사용할 전략을 나타냅니다. 현재 지원되는 값은 “backups”뿐입니다. 이 설정을 해당 값으로 지정하면 Gitaly는 서버 측 백업이 있는지 확인하고 그것을 사용합니다.
  • bundle_uri.sign_urls :: true로 설정하면 클라우드 저장소 URL은 직접 클라이언트에게 전달되지 않고, 서명된 URL로 변환됩니다. 이 설정은 선택 사항이며 현재는 Google Cloud Storage만 지원합니다.

클라우드 저장소에 액세스하기 위한 자격 증명은 Gitaly 백업 문서에 설명된 대로 재사용됩니다.

메타데이터 저장

현재 클라우드에 번들을 저장하기 위해 필요한 모든 메타데이터는 Gitaly 서버 측 백업에 의해 관리됩니다.

번들 정리

어느 순간에는 관리자가 하나 이상의 저장소의 번들을 정리하기로 결정할 수 있습니다. 이를 위해 관리자 명령이 추가되어야 합니다. 우리는 이제 gitaly-backup에 의해 생성된 번들만 사용하고 있기 때문에 이 작업은 대상에서 제외하겠습니다.

Gitaly 클러스터 호환성

서버 측 백업 생성은 현재 Praefect를 통해 이루어지지 않습니다. 백업을 생성할 노드를 관리자가 직접 다룰 것입니다. 노드를 최신 상태로 유지하는 것만으로 모든 노드가 최신 번들에 액세스할 수 있고 적절한 번들-URI 매개변수를 클라이언트에게 전달할 수 있습니다. 번들-URI로 서버 측 백업 번들을 다시 사용하기 위해서는 추가 작업이 필요하지 않습니다.

대체 솔루션

현재는 대체 솔루션이 제안되지 않았습니다.