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 @jcai-gitlab @toon devops systems 2023-05-19

저렴한 리포지터리로 데이터 언로드

요약

Git 데이터 저장 비용 관리는 저희 비즈니스의 중요한 부분입니다. Git 데이터를 저렴한 리포지터리로 옮기면 저장 비용을 줄일 수 있습니다.

동기

GitLab에서는 데이터 접근을 빠르게 유지하기 위해 대부분의 Git 데이터를 SSD에 저장합니다. 이것은 자주 액세스해야 하는 데이터에 대한 이치가 있습니다. 그러나 저장 비용이 데이터 성장과 함께 증가하기 때문에, 어떤 종류의 데이터를 SSD에, 어떤 종류의 데이터를 저렴한 리포지터리에 옮길지에 대해 더 스마트하게 할 수 있습니다.

예를 들어, 큰 파일(또는 Git 용어로 “블롭”)은 일반적으로 수정되지 않으며(이미지, 비디오, 이진 파일 등의 비텍스트 파일), 자주 액세스되지 않습니다. 종종, 이러한 대형 블롭을 포함하는 리포지터리에는 Git LFS가 사용되어 큰 파일을 Git 서버에 푸시할 필요가 없게 됩니다. 그러나 이것은 클라이언트 측 설정에 의존합니다.

또는, 프로젝트가 “잠자기 모드”이고 오랜 시간동안 액세스되지 않았다면, 해당 프로젝트에 대해 빠른 리포지터리에 지불할 필요가 없습니다.

대신, 우리는 그 잠자기 모드에 있는 프로젝트의 모든 블롭을 저렴한 리포지터리로 옮기는 선택을 할 수 있습니다. 이렇게 하면 애플리케이션은 커밋 히스토리와 트리에 여전히 액세스할 수 있으므로 프로젝트 탐색 경험이 영향을 받지 않지만, 파일은 거의 액세스되지 않기 때문에 느린 리포지터리에 있습니다.

만약 우리가 Git 데이터를 다양한 범주로 분리할 방법을 가지고 있다면, 우리는 특정 데이터를 더 저렴한 보조 위치로 옮길 수 있습니다. 예를 들어, 자주 액세스되지 않을 수 있는 대형 파일들을 나머지 Git 데이터와 분리하여 HDD에 저장할 수 있습니다.

요구 사항

특정 해결책에 대한 요구 사항과 불변 조건이 있습니다.

저장 비용 절감

이 해결책은 궁극적으로 저장 비용을 절약해야 합니다. 더 저렴한 리포지터리로 특정 Git 데이터를 분리하는 것은 이러한 절약에 도움이 될 수 있습니다.

저장 비용의 절감을 위해 데이터를 저렴한 리포지터리로 옮기는 것에 대한 추가 비용을 평가해야 합니다. 여기에 고려해야 할 몇 가지 기준이 있습니다:

  • X보다 큰 모든 큰 블롭이 HDD에 저장된다면 얼마나 많은 비용을 절약할까요?
  • 모든 잠자기 모드 프로젝트의 블롭이 HDD에 저장된다면 얼마나 많은 비용을 절약할까요?
  • 추가 CPU/메모리 비용과 같은 운영 오버헤드가 오프로딩 메커니즘을 실행하는 데 필요한가요?
  • 네트워크 오버헤드는 얼마나 될까요? 예를 들어, 큰 블롭을 검색하기 위해 네트워크를 통해 다른 노드로 추가 라운드트립이 있나요?
  • 액세스 비용, 예를 들어 블롭이 객체 리포지터리에 저장될 때.

Gitaly의 하향 스트림 소비자에게는 불투명해야 함

이 기능은 순수한 리포지터리 최적화이며, 잠재적인 성능 저하를 제외하고 Gitaly의 하향 스트림 소비자에게는 영향을 미치지 않아야 합니다. 예를 들어, GitLab 애플리케이션은 이 기능을 지원하기 위해 로직을 변경할 필요가 없어야 합니다.

이 기능은 Gitaly를 호출하는 모든 호출자에 대해 완전히 투명해야 합니다. Rails나 다른 소비자는 이에 대해 알 필요가 없으며 어떻게든 이를 관리할 필요가 없어야 합니다.

운영적으로 간단함

Git 데이터를 다룰 때, 리포지터리 손상의 위험을 최소화하기 위해 가능한 한 간단하게 유지하고 Git 자체 외부의 움직이는 조각을 최소화하고자 합니다. 리포지터리 데이터를 수정하는 어떠한 로직도 Git 자체에서 상위로 이동되어야 합니다.

제안

우리는 Git 대체 메카니즘을 통해 연결된 각 리포지터리를 위해 별도의 객체 데이터베이스를 유지할 것입니다.

이러한 보조 객체 데이터베이스(ODB)를 기준에 따라 특정 Git 객체로 채웁니다. Git 필터를 기반으로 옵션이 있습니다.

우리는 어떤 한계를 기반으로 대형 블롭을 보조 ODB로, 또는 모든 블롭을 보조 ODB로 넣기를 선택할 수 있습니다.

설계 및 구현 세부 정보

Git

git-repack(1)에 특정 유형의 블롭을 다른 객체 데이터베이스로 분할할 수 있는 기능을 추가해야 합니다. 이 노력은 이 이슈에서 추적하고 있습니다.

Gitaly

Gitaly 가정 관리 중에, 다음을 할 수 있습니다.

  1. git-repack(1)을 사용하여 메인 리포지터리의 객체 데이터베이스와 보조 객체 데이터베이스에 팩 파일을 작성합니다. 각 리포지터리는 기준에 따라 블롭을 보조 객체 데이터베이스로 옮깁니다.
  2. .git/objects/info/alternates 파일이 (1)에서의 보조 객체 데이터베이스를 가리켜야 합니다.

기준

객체가 다른 객체 데이터베이스로 옮겨지는 여부는 다음 중 하나 이상의 기준을 기반으로 결정될 수 있습니다.

등급별

무료 프로젝트는 저렴한 리포지터리로 많은 블롭을 옮길지도 모르지만, Ultimate 프로젝트는 모든 객체를 가장 빠른 리포지터리에 놓을지도 모릅니다.

히스토리에 따라

오랜 시간 전에 블롭이 추가되었으며 최근 커밋에서 언급되지 않았다면 옮겨질 수 있으나, 새로운 블롭은 메인 ODB에 남을 수 있습니다.

크기에 따라

큰 블롭은 비싼 리포지터리 크기를 줄이는 빠른 승리입니다. 따라서 더 저렴한 리포지터리로 옮겨지는 경우가 높습니다.

액세스 빈도

자주 사용되는 프로젝트는 빠른 리포지터리에 완전히 유지될 수 있으며, 비활성화 된 프로젝트는 블롭이 옮겨질 수 있습니다.

미해결된 문제

객체를 어떻게 삭제할 것인가요?

접근할 수 없는 객체를 삭제하고 싶을 때, 리팩은 메인 ODB 또는 보조 ODB와 관계없이 접근할 수 없는 객체를 삭제할 수 있어야 합니다. 만약 메인 ODB에 객체 풀이 있다면 이 형태가 복잡해집니다. 왜냐하면 우리는 객체 풀에서 객체를 삭제하고 싶지 않기 때문입니다.

잠재적인 해결책: 대체에서 객체 삭제 허용

우리는 리팩에게 대체 디렉터리에서 어떻게 행동할지 말할 수 있는 repack 구성 repack.alternates.*를 추가할 필요가 있습니다. 예를 들어, repack 구성 repack.alternates.explodeUnreachable을 추가하여 대체 ODB에서 -A처럼 행동하도록 할 수 있습니다.

객체 풀과의 작업 방식

대체를 사용할 때, 이것이 객체 풀과 상호 작용하는 방식은 어떠한가요? 객체 풀은 보조 리포지터리로 데이터를 옮기는가요? 객체 풀 멤버는 어떨까요? 가장 복잡한 경우에는 단일 리포지터리가 네 가지 다른 객체 데이터베이스를 가지고 있는데, 이는 복잡성을 증가시킬 수 있습니다.

우리는 약간의 팩 파일을 “유지” 표시하여 일부 공간 이용을 향상시킬 수 있습니다. 이를 위해서 --keep-pack--honor-pack-keep 옵션을 사용할 수 있습니다.

잠재적인 해결책: 객체 풀이 블롭을 옮기지 못하게 함

너무 많은 복잡성을 추가하지 않기 위해, 객체 풀이 블롭을 이동하지 못하도록 할 수 있습니다. 대신, 객체 풀과의 중복을 방지하기 전에 리포지터리에서 블롭을 옮기는 하우스키프잉을 설계할 수 있습니다. 이론적으로, 이렇게 하면 옮겨진 블롭이 객체 풀에 저장되지 않을 수 있습니다.

Raft 및 WAL과의 작동 방식

이 메커니즘은 Raft와 래드 얼헤드 로그와 어떻게 상호 작용하나요?

WAL은 하드링크와 복사 무료 이동을 사용하여 느린 복사 작업을 피합니다. 그러나 이것은 다른 파일 시스템 사이에서 작동하지 않습니다. 언젠가는 리팩 및 이와 같은 것들이 로그를 통해 지나게 될 가능성이 높습니다. 파일 시스템간에 데이터를 전송하는 것은 트랜잭션 처리의 지연을 야기할 수 있습니다.

이상적으로는 사용 가능한 공간을 고려해 배치 결정을 할 수 있도록 내부 노드에서만 사용하고, 그 복잡성을 클러스터의 나머지로 유출시키지 않도록 유지하는 것이 좋습니다. 이것은 내부만 보여줌으로써 가능할 수 있지만, 이는 비효율적인 리포지터리 사용으로 이어질 수도 있습니다.

디자인 문제점

추가된 복잡성

다른 객체 풀을 추가하면 시스템이 복잡해지는데, 특히 리포지터리 복제와 관련해서 데이터를 복제할 새로운 위치가 추가되기 때문입니다.

시간이 지남에 따른 비용 변동 가능성

다양한 리포지터리 유형의 비용은 시간이 지남에 따라 변할 수 있습니다. 이에 대비하기 위해 이러한 변화에 쉽게 적응할 수 있어야 합니다.

더 많은 고장 지점

별도의 저장 장치에 일부 blob을 두면 대용량 blob을 호스팅하는 장치가 고장나는 또 다른 시나리오가 추가됩니다.

대안적인 해결책

전체 프로젝트를 더 저렴한 리포지터리에 배치

저렴한 리포지터리에 Git 데이터를 배치하는 대신에, Rails 애플리케이션은 프로젝트 전체를 장착된 HDD 드라이브로 이동할 수도 있습니다.

가능한 최적화

저렴한 리포지터리를 가지고 있는 이 기계들에게 추가 RAM을 제공하는 것은 페이지 캐시의 사용으로 인해 느린 읽기/쓰기 속도에 대처하는 데 도움이 될 수 있습니다. 하지만 전반적으로 더 저렴해질 것인지는 확실하지 않습니다.