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

Gitaly CPU 부하를 줄이기 위한 번들 URI 활용

요약

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

Git 번들은 팩 파일과 일부 추가 메타데이터를 저장하며, 참조 집합 및 (비어 있을 수도 있는) 필요한 커밋 집합을 포함합니다. 사용자가 리포지터리를 복제하면 서버가 이러한 번들을 제공하는 하나 이상의 URI를 광고할 수 있습니다. 클라이언트는 이를 다운로드하여 Git 객체 데이터베이스를 채울 수 있습니다. 이 작업을 마친 후에는 서버와 클라이언트 간의 협상 프로세스가 시작되어 가져올 필요가 있는 객체를 확인합니다. 번들에서 데이터베이스를 미리 채우면 서버에서 객체를 가져오는 협상 및 전송이 줄어들어 서버의 CPU 부하가 줄어듭니다.

동기

사용자가 변경 사항을 푸시하면 일반적으로 CI 파이프라인이 여러 작업을 실행합니다. CI 러너가 리포지터리를 처음부터 복제하면, git clone을 사용하면 모두 서버와 협상을 시작하여 복제해야 할 내용을 확인합니다. 이는 서버에 대해서 실제로 CPU를 많이 사용합니다.

얼마 전에 pack-objects를 도입했지만 일부 문제점이 있습니다. 브랜치의 끝 부분이 변경되면 새로운 팩 파일을 계산하고 캐시를 새로 고쳐야 합니다.

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

목표

클라이언트가 리포지터리를 복제할 때 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 :: 사용 광고할 경우 true로 설정해야 합니다.
  • bundle.version :: 현재는 1만 허용됩니다.
  • bundle.mode :: 이는 any 또는 all일 수 있습니다. 초기 복제에만 번들을 사용하려면 any를 권장합니다.
  • bundle.<id>.uri :: <id>로 식별된 번들의 실제 URI입니다. 초기에는 각 리포지터리당 하나의 번들만 가지게 될 것입니다.

클라이언트 측에서 광고된 번들 사용 활성화

현재의 Git 버전은 기본적으로 광고된 번들을 사용하지 않습니다. 다행히 대부분의 CI 러너를 직접 제어할 수 있습니다. 따라서 번들 URI를 사용하려면 러너에서 사용하는 Git 구성을 수정하고 transfer.bundleURI=true로 설정할 수 있습니다.

접근 제어

비공개 리포지터리의 데이터가 공개 HTTP(S) 호스트를 통해 유출되지 않도록 하고 싶습니다. 이를 극복하기 위한 몇 가지 옵션이 있습니다.

  • 번들 URI 사용을 공개 리포지터리에만 활성화합니다.
  • signed-URLs와 같은 솔루션을 사용합니다.

공개 리포지터리 전용

Gitaly 자체에서 프로젝트와 해당 리포지터리가 공개인지 여부를 알 수 없으므로 번들 사용 가능 여부를 결정하려면 GitLab Rails가 Gitaly에게 이 정보를 전달해야 합니다. 이 접근 방식을 사용하면 프로젝트가 공개된 경우에만이 기능을 사용할 수 있고, 이는 복잡하므로 이 접근 방식은 사용하지 않을 것입니다.

서명된 URL

signed-URLs의 사용은 번들에 대한 액세스를 제어하는 또 다른 옵션입니다. Google Cloud에서 제공하는 이 기능은 지원이 끊기진 않지만 클라우드마다 이러한 기능을 조금씩 다르게 제공하거나 이 기능을 제공하지 않을 수 있습니다. 그러나 먼저 Google Cloud에서 호스팅되는 GitLab.com에 이 기능을 먼저 롤아웃하고 싶으므로 처음에는 이를 사용할 것입니다.

번들 생성

서버측 백업 사용

현재 Gitaly는 리포지터리를 번들로 클라우드 리포지터리에 백업하는 방법을 알고 있습니다. 초기 번들-URI 구현에는 이 기능을 이용할 수 있습니다. 관리자는 번들-URI를 사용하고 싶은 리포지터리를 위해 백업을 만들어야 합니다. 기존의 백업 구성을 사용하면 Gitaly가 클라우드 리포지터리에 액세스할 수 있습니다.

housekeeping의 일환으로

Gitaly에는 매일 리포지터리를 최적화하기 위해 housekeeping worker가 있습니다. housekeeping(가비지 수집 및 다시 패킹)이 완료된 직후 번들을 만들면 가장 최적의 번들 파일이 되도록합니다. 번들을 자동으로 만들 때 고려해야 할 몇 가지 사항이 있습니다.

  • 번들을 다시 만들어야 할 필요가 있습니까? 리포지터리에 활동이 많지 않았다면 새로운 번들 파일을 만들 필요가 없을 것입니다. 클라이언트가 빠진 객체를 바로 Gitaly에서 가져올 수 있기 때문입니다. housekeeping 작업은 housekeeping 작업의 전략을 결정하기 위해 여러 가지 휴리스틱을 사용하므로 번들 작성에 이러한 로직의 일부를 재사용할 수 있습니다.
  • 번들을 만드는 것이 필요한가요? 일부 리포지터리는 매우 작거나 활동이 거의 없을 수 있습니다. 이러한 리포지터리에 대해 번들을 만들고 데이터를 객체 리포지터리에 중복하여 저장하면 큰 가치를 제공하지 않으며 비용과 유지 관리만 발생시키게 됩니다.

GitLab Rails에서 제어됨

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

설정

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

  • bundle_uri.strategy :: 이는 어떤 전략을 사용하여 번들-URI를 생성하고 제공해야 하는지를 나타냅니다. 현재 유일하게 지원되는 값은 “backups”입니다. 이 설정을 해당 값으로 설정하면 Gitaly는 서버 측 백업이 있는지 확인하고 해당 백업을 사용합니다.
  • bundle_uri.sign_urls :: true로 설정되면, 클라우드 리포지터리 URL은 그대로 클라이언트에 전달되는 것이 아니라 서명된 URL로 변환됩니다. 이 설정은 옵션으로, 현재 구글 클라우드 리포지터리만 지원합니다.

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

메타데이터 저장

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

번들 정리

언젠가 관리자는 하나 이상의 리포지터리에 대해 번들을 정리하기로 결정할 수 있습니다. 이를 위해 관리자용 명령이 추가되어야 합니다. 현재는 gitaly-backup에 의해 생성된 번들만 사용하고 있기 때문에, 이는 범위에서 제외합니다.

Gitaly 클러스터 호환성

현재 서버 측 백업을 생성하는 것은 Praefect를 통해 이루어지지 않습니다. 백업을 생성하려는 노드를 관리자가 다룰 것입니다. 노드가 최신 상태인지 확인하면, 모든 노드가 최신 번들에 액세스하여 올바른 번들-URI 매개변수를 클라이언트에 전달할 수 있습니다. 따라서 서버 측 백업 번들을 번들-URI와 함께 재사용하기 위해 추가 작업이 필요하지 않습니다.

대안적 해결책

현재는 어떤 대안적 해결책도 제시되지 않았습니다.