관리
GitLab은 Git 리포지터리의 가장 효율적인 상태로 유지되도록 하기 위해 Git 리포지터리의 관리 작업을 지원하고 자동화합니다. 관리 작업에는 다음이 포함됩니다:
- Git 객체 및 리비전 압축.
- 연결할 수 없는 객체 제거.
- 잠겨 있는 파일과 같은 오래된 데이터 제거.
- 성능을 향상시키는 데이터 구조 관리.
- 포크 간 객체 중복을 개선하기 위해 객체 풀 업데이트.
관리 전략
Gitaly는 Git 리포지터리에서 관리 작업을 두 가지 방법으로 수행할 수 있습니다:
- Eager housekeeping은 리포지터리 상태와 관계없이 특정 관리 작업을 실행합니다.
- Heuristical housekeeping은 리포지터리 상태에 따라 실행할 관리 작업을 결정하는 휴리스틱 집합에 기초하여 관리 작업을 실행합니다.
Eager housekeeping
“eager” 관리 전략은 리포지터리의 상태와 관계없이 관리 작업을 실행합니다. 이는 매뉴얼 트리거 및 푸시 기반 트리거에서 사용하는 기본 전략입니다.
Eager 관리 전략은 GitLab 애플리케이션에서 제어됩니다. 관리 작업이 실행된 트리거에 따라서 GitLab은 Gitaly에게 특정 관리 작업을 수행하도록 요청합니다. 리포지터리가 최적화된 상태인 경우에도 Gitaly는 이러한 작업을 수행합니다. 결과적으로 이 전략은 관리 작업이 느릴 수 있는 대형 리포지터리에서 비효율적일 수 있습니다.
Heuristical housekeeping
- GitLab 14.9에서 도입, 기본적으로
optimized_housekeeping
이라는 플래그로 매뉴얼 트리거 및 푸시 기반 트리거에 대해 실행됨.- GitLab 14.10에서 GitLab.com에 활성화.
- GitLab 15.8에서 일반적으로 사용 가능. 피처 플래그
optimized_housekeeping
제거됨.
휴리스틱(또는 “기회주의”) 관리 전략은 리포지터리 상태를 분석하고 하나 이상의 데이터 구조가 충분히 최적화되지 않았을 때만 관리 작업을 실행합니다. 이는 scheduled housekeeping에서 사용되는 전략입니다.
휴리스틱 관리 작업은 다음 정보를 사용하여 실행할 작업을 결정합니다:
- 느슨하고 오래된 객체의 수.
- 이미 압축된 객체를 포함하는 팩 파일의 수.
- 느슨한 참조의 수.
- 커밋 그래프의 존재.
분석된 데이터 구조 중 어떤 것이 최적화되어야 하는지 여부는 리포지터리의 크기를 기반으로 결정됩니다:
- 객체는 총 객체 크기가 클수록 자주 다시 패킹됩니다.
- 참조가 총 참조가 많을수록 객체는 덜 자주 다시 패킹됩니다.
이렇게 함으로써 Gitaly는 해당 데이터 구조를 최적화하는 데 걸리는 시간이 커질수록 더 큰 데이터가 된다는 사실을 상쇄시킵니다. 이는 특히 많은 트래픽을 받는 대규모 모노레포에서 그것들을 너무 자주 최적화하지 않도록 하는 데 중요합니다.
Gitaly를 요청하여 리포지터리를 최적화하도록 요청하는 빈도를 변경할 수 있습니다.
- 왼쪽 사이드바에서 하단에 관리 영역을 선택합니다.
- 설정 > 리포지터리를 선택합니다.
- 리포지터리 유지 관리를 확장합니다.
- Housekeeping 섹션에서 관리 옵션을 구성합니다.
- 변경 사항 저장을 선택합니다.
- 자동 리포지터리 관리 활성화: 정기적으로 Gitaly에게 리포지터리 최적화를 실행하도록 요청합니다. 이 설정을 장시간 비활성화하는 경우 GitLab 서버에서 Git 리포지터리 액세스가 느려지고 리포지터리가 더 많은 디스크 공간을 사용합니다.
- 리포지터리 최적화 기간: Gitaly에게 리포지터리 최적화를 요청하는 Git 푸시 횟수.
관리 작업 실행
GitLab은 다양한 방법으로 관리 작업을 실행합니다:
- 프로젝트의 관리자는 리포지터리 수동으로 트리거할 수 있습니다.
- GitLab은 일정 수의 Git 푸시 후 자동으로 관리 작업을 예약할 수 있습니다.
- GitLab은 구성 가능한 시간 범위 내에서 모든 리포지터리에 대한 관리 작업을 실행하는 작업을 예약할 수 있습니다.
Manual trigger
리포지터리의 관리자는 리포지터리에서 관리 작업을 수동으로 트리거할 수 있습니다. 일반적으로 GitLab은 자동으로 관리 작업을 실행하지만 다음 경우에 매뉴얼 트리거를 실행하는 것이 유용할 수 있습니다:
- 리포지터리가 관리 필요한 경우.
- 관리 작업이 자동 푸시 기반 스케줄링이 비활성화되어 있는 경우.
매뉴얼으로 관리 작업을 트리거하려면:
- 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
- 설정 > 일반을 선택합니다.
- 고급을 확장합니다.
- 관리 작업 실행을 선택합니다.
이렇게 하면 프로젝트의 리포지터리에 대한 비동기 백그라운드 워커가 시작됩니다. 이 백그라운드 워커는 Gitaly에게 최적화를 수행하라고 요청합니다.
관리 작업은 또한 프로젝트의 참조되지 않는 LFS 파일을 약 200
번의 푸시마다 제거하여 프로젝트의 저장 공간을 확보합니다.
Prune unreachable objects
참조할 수 없는 객체는 예약된 관리 작업의 일환으로 가지 않을 수 있습니다. 그러나 매뉴얼으로 가지는 참조 도렉을 수행할 수도 있습니다. 예를 들어, 민감한 정보를 포함하는 커밋을 제거하는 경우입니다. 관리 작업을 트리거하여 참조할 수 없는 객체를 제거하면 2주의 유예 기간이 있습니다. 매뉴얼으로 참조할 수 없는 객체를 가지는 경우에는 유예 기간이 30분으로 줄어듭니다.
git push
)가 객체를 생성했지만 해당 객체에 대한 참조를 아직 만들지 않은 경우, 개체가 삭제된 후에 참조가 추가되면 리포지터리가 손상될 수 있습니다. 유예 기간은 이러한 경합 조건의 가능성을 줄이기 위해 존재합니다.
예를 들어, 가끔 아주 느린 연결로 자주 대량의 큰 객체를 푸시하는 경우, 참조할 수 없는 객체를 가지는 리스크가 회사 내부에서만 효율적인 연결을 통해 프로젝트에 접속할 수 있는 기업 환경보다 훨씬 높아집니다. 이 옵션을 사용할 때 프로젝트 사용 프로필을 고려하고 조용한 기간을 선택하십시오.참조할 수 없는 객체의 매뉴얼 가지를 트리거하려면:
- 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
- 설정 > 일반을 선택합니다.
- 고급을 확장합니다.
- 관리 작업 실행을 선택합니다.
- 운영이 완료되기까지 30분을 기다립니다.
- 관리 작업 실행을 선택한 페이지로 돌아가 참조할 수 없는 객체 제거를 선택합니다.
예약된 하우스키퍼링
GitLab은 푸시(push)의 횟수에 따라 자동으로 하우스키퍼링 작업을 수행하지만 전혀 푸시를 받지 않는 리포지터리는 유지하지 않습니다. 결과적으로 활성화되지 않은 리포지터리나 오직 읽기 요청만 받는 리포지터리는 리포지터리 하우스키퍼링 전략의 개선에서 이득을 못 보게 됩니다.
관리자는 모든 리포지터리에 대해 맞춤형 간격으로 하우스키퍼링을 수행하는 백그라운드 작업을 활성화하여 이러한 상황을 해소할 수 있습니다. 이 백그라운드 작업은 랜덤한 순서로 Gitaly 노드에서 호스팅되는 모든 리포지터리에 대해 빠르게 하우스키퍼링 작업을 수행합니다. 구성된 간격보다 시간이 더 걸리면 Gitaly 노드는 리포지터리 처리를 중단합니다.
예약된 하우스키퍼링 구성
Git 리포지터리의 백그라운드 유지 관리는 Gitaly에서 구성됩니다. 기본적으로 Gitaly는 매일 정오 12:00에 10분 동안 백그라운드 리포지터리 유지 관리를 수행합니다.
Gitaly 구성에서 이 기본값을 변경할 수 있습니다.
Gitaly Cluster를 사용하는 환경에서 예약된 하우스키퍼링 시작 시간을 Gitaly 노드 간에 어긋나게 설정하여 여러 노드에서 동시에 예약된 하우스키퍼링이 실행되지 않도록 할 수 있습니다.
예약된 하우스키퍼링 실행이 지정된 지속 시간
에 도달하면 실행 중인 작업이 원활하게 취소됩니다. 이후 예약된 하우스키퍼링 실행에서 Gitaly는 리포지터리 디렉터리을 랜덤하게 섞어 처리합니다.
다음 스니펫은 default
스토리지에 대해 23:00에 1시간 동안 매일 백그라운드 리포지터리 유지 관리를 활성화합니다:
[daily_maintenance]
start_hour = 23
start_minute = 00
duration = 1h
storages = ["default"]
다음 스니펫은 백그라운드 리포지터리 유지 관리를 완전히 비활성화합니다:
[daily_maintenance]
disabled = true
gitaly['configuration'] = {
daily_maintenance: {
disabled: false,
start_hour: 23,
start_minute: 00,
duration: '1h',
storages: ['default'],
},
}
다음 스니펫은 백그라운드 리포지터리 유지 관리를 완전히 비활성화합니다:
gitaly['configuration'] = {
daily_maintenance: {
disabled: true,
},
}
예약된 하우스키퍼링이 실행되면 Gitaly 로그에서 다음 항목을 볼 수 있습니다:
# 예약된 하우스키퍼링이 시작될 때
{"level":"info","msg":"maintenance: daily scheduled","pid":197260,"scheduled":"2023-09-27T13:10:00+13:00","time":"2023-09-27T00:08:31.624Z"}
# 예약된 하우스키퍼링이 완료된 때
{"actual_duration":321181874818,"error":null,"level":"info","max_duration":"1h0m0s","msg":"maintenance: daily completed","pid":197260,"time":"2023-09-27T00:15:21.182Z"}
actual_duration
(나노초 단위)은 예약된 유지 관리를 실행하는 데 걸린 시간을 나타냅니다. 위 예에서는 예약된 하우스키퍼링이 5분 넘게 걸려 완료되었습니다.
객체 풀 리포지터리
객체 풀 리포지터리는 리포지터리의 fork들 사이에서 객체를 중복으로 저장하기 위해 GitLab에서 사용됩니다. 첫 번째 fork를 생성할 때 우리는:
- fork할 리포지터리의 모든 객체가 포함된 객체 풀 리포지터리를 생성합니다.
- 새로운 리포지터리를 이 새로운 객체 풀에 대한 alternate 메커니즘을 통해 연결합니다.
- 리포지터리를 다시 패킹하여 객체 풀의 객체를 사용하도록 합니다. 결과적으로 객체 풀로부터 객체에 대한 자체 복사본을 삭제할 수 있습니다.
이 리포지터리의 어떤 fork도 이제 객체 풀에 링크되어 있으므로 기본 리포지터리에서 벗어난 객체만 유지해야 합니다.
GitLab은 객체 풀에서 특별한 하우스키퍼링 작업을 수행해야 합니다:
- Gitaly는 객체 풀에서 도달할 수 없는 객체를 삭제해서는 안 되므로, 그 객체들은 어떤 fork에서도 사용될 수 있습니다.
- 동일한 이유로 Gitaly는 도달 가능한 모든 객체를 유지해야 합니다. 따라서 객체 풀은 객체가 삭제되지 않도록 도달할 수 없는 “dangling” 객체에 대한 참조를 계속 유지합니다.
- GitLab은 주기적으로 객체 풀을 업데이트하여 기본 리포지터리에 추가된 새 객체를 가져와야 합니다. 그렇지 않으면 객체 풀은 객체 중복 방지에 점점 비효율적해집니다.
이러한 하우스키퍼링 작업은 특화된 FetchIntoObjectPool
RPC에 의해 수행됩니다. 이 RPC는 표준 Git 리포지터리에 대해 실행하는 일반적인 하우스키퍼링 작업과 함께 모든 이러한 특별한 작업을 처리합니다.
객체 풀은 기본 멤버가 가비지 수집될 때 자동으로 최적화됩니다. 따라서 프로젝트에서 동일한 Git GC 주기를 사용하여 cadence를 구성할 수 있습니다.
Rails 콘솔에서 RPC를 매뉴얼으로 호출해야 하는 경우 project.pool_repository.object_pool.fetch
를 호출할 수 있습니다. 이 작업은 잠재적으로 오랜 시간이 걸리지만 Gitaly는 약 8시간 후에 타임아웃됩니다.