하우스키핑

Tier: Free, Premium, Ultimate Offering: Self-managed

GitLab은 Git 저장소에서 하우스키핑 작업을 지원하고 자동화하여
가능한 한 효율적으로 서비스될 수 있도록 합니다. 하우스키핑 작업에는 다음이 포함됩니다:

  • Git 객체 및 수정본 압축.
  • 접근할 수 없는 객체 제거.
  • 잠금 파일과 같은 오래된 데이터 제거.
  • 성능을 향상시키는 데이터 구조 유지.
  • 포크 간 객체 중복 제거를 개선하기 위한 객체 풀 업데이트.
caution
GitLab에서 관리하는 Git 저장소에서 하우스키핑을 수행하기 위해 Git 명령을 수동으로 실행하지 마십시오.
이렇게 하면 손상된 저장소와 데이터 손실이 발생할 수 있습니다.

하우스키핑 전략

Gitaly는 Git 저장소에서 하우스키핑 작업을 두 가지 방법으로 수행할 수 있습니다:

  • Eager housekeeping는 저장소 상태와 관계없이
    특정 하우스키핑 작업을 수행합니다.
  • Heuristical housekeeping
    저장소 상태에 따라 어떤 하우스키핑 작업이 수행되어야 하는지를 결정하는
    일련의 휴리스틱을 기반으로 하우스키핑 작업을 실행합니다.

Eager housekeeping

“eager” 하우스키핑 전략은 저장소 상태와 관계없이
저장소에서 하우스키핑 작업을 실행합니다. 이는 수동 트리거
푸시 기반 트리거에서 사용되는 기본 전략입니다.

eager 하우스키핑 전략은 GitLab 애플리케이션에 의해 제어됩니다.
하우스키핑 작업을 실행한 트리거에 따라 GitLab은 Gitaly에게
특정 하우스키핑 작업을 수행하도록 요청합니다. Gitaly는
저장소가 최적화된 상태에 있더라도 이러한 작업을 수행합니다.
결과적으로 이 전략은 하우스키핑 작업 수행이 느릴 수 있는
대형 저장소에서 비효율적일 수 있습니다.

Heuristical housekeeping

휴리스틱(또는 “기회적”) 하우스키핑 전략은
저장소의 상태를 분석하고 데이터 구조가 최적화되어 있지 않다고 판단할 때만
하우스키핑 작업을 실행합니다. 이는 예약된 하우스키핑에서 사용되는 전략입니다.

휴리스틱 하우스키핑은 실행해야 할 작업을 결정하기 위해
다음 정보를 사용합니다:

  • 느슨한 객체 및 오래된 객체 수.
  • 이미 압축된 객체를 포함하는 팩파일 수.
  • 느슨한 참조 수.
  • 커밋 그래프의 존재.

분석된 데이터 구조를 최적화해야 할지 여부는
저장소의 크기에 따라 결정됩니다:

  • 모든 객체의 총 크기가 클수록 객체가 자주 재포장됩니다.
  • 전체 참조 수가 많을수록 참조는 덜 자주 재포장됩니다.

Gitaly는 이러한 데이터 구조를 최적화하는 데 더 많은 시간이 소요되는
경우를 상쇄하기 위해 이를 수행합니다. 대형 모노레포(많은 트래픽을 받는 경우)에서는
너무 자주 최적화하는 것을 피하는 것이 특히 중요합니다.

Gitaly에게 저장소 최적화를 요청하는 빈도를 변경할 수 있습니다.

  1. 왼쪽 사이드바에서 하단의 Admin을 선택합니다.
  2. Settings > Repository를 선택합니다.
  3. Repository maintenance를 확장합니다.
  4. Housekeeping 섹션에서 하우스키핑 옵션을 구성합니다.
  5. Save changes를 선택합니다.
  • 자동 저장소 하우스키핑 활성화: Gitaly에게 정기적으로
    저장소 최적화를 실행하도록 요청합니다. 이 설정을 오랫동안 비활성화하면
    GitLab 서버에서 Git 저장소 접근 속도가 느려지고 저장소가 더 많은 디스크 공간을 사용하게 됩니다.
  • 저장소 최적화 기간: Gitaly에게 저장소 최적화를 요청하는 Git 푸시 수.

점검 작업 실행

GitLab이 점검 작업을 실행하는 방법은 여러 가지가 있습니다:

  • 프로젝트의 관리자는 수동으로 트리거하여 저장소 점검 작업을 수행할 수 있습니다.
  • GitLab은 일정 수의 Git 푸시 후에 자동으로 점검 작업을 예약할 수 있습니다.
  • GitLab은 작업을 예약할 수 있으며, 이는 설정 가능한 시간 범위 내에서 모든 저장소에 대한 점검 작업을 실행합니다.

수동 트리거

저장소의 관리자는 저장소에서 점검 작업을 수동으로 트리거할 수 있습니다. 일반적으로 GitLab이 자동으로 점검 작업을 실행하는 방법을 알고 있기 때문에 이는 필요하지 않습니다. 다음과 같은 경우에 수동 트리거가 유용할 수 있습니다:

  • 저장소에서 점검이 필요하다고 알려진 경우.
  • 저장소 점검 작업의 자동 푸시 기반 일정이 비활성화된 경우.

점검 작업을 수동으로 트리거하려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > 일반을 선택합니다.
  3. 고급을 확장합니다.
  4. 점검 실행을 선택합니다.

이렇게 하면 프로젝트의 저장소에 대한 비동기 백그라운드 작업자가 시작됩니다. 백그라운드 작업자는 Gitaly에 여러 가지 최적화를 수행하도록 요청합니다.

점검은 또한 매 200 푸시마다 프로젝트에서 참조되지 않은 LFS 파일을 제거합니다, 저장소의 공간을 확보합니다.

도달 불가능한 객체 정리

도달 불가능한 객체는 예약된 점검의 일환으로 정리됩니다. 그러나 수동 정리도 트리거할 수 있습니다. 예를 들어, 민감한 정보를 포함하는 커밋을 제거하는 경우입니다. 점검을 트리거하면 도달 불가능한 객체가 2주에 걸쳐 정리됩니다. 도달 불가능한 객체 정리를 수동으로 트리거할 경우, 유예 기간은 30분으로 단축됩니다.

경고: 동시 프로세스(예: git push)가 객체를 생성했지만 아직 객체에 대한 참조를 생성하지 않은 경우, 객체가 삭제된 후에 객체에 대한 참조가 추가되면 저장소가 손상될 수 있습니다. 유예 기간은 이러한 경쟁 조건의 가능성을 줄이기 위해 존재합니다.

예를 들어, 때때로 매우 느린 연결을 통해 많은 대용량 객체를 자주 푸시하는 경우, 도달 불가능한 객체를 정리할 때 위험이 기업 환경에서 프로젝트에 접근할 수 있는 빠른 연결과 다르게 훨씬 높습니다. 이 옵션을 사용할 때는 프로젝트 사용 프로필을 고려하고 조용한 시간을 선택하세요.

도달 불가능한 객체의 수동 정리를 트리거하려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > 일반을 선택합니다.
  3. 고급을 확장합니다.
  4. 점검 실행을 선택합니다.
  5. 작업이 완료될 때까지 30분을 기다립니다.
  6. 점검 실행을 선택했던 페이지로 돌아가 도달 불가능한 객체 정리를 선택합니다.

예약된 점검

GitLab은 푸시 수에 따라 자동으로 점검 작업을 수행하지만, 푸시가 전혀 이루어지지 않는 저장소에 대해서는 점검 작업을 유지하지 않습니다. 그 결과 비활성 저장소나 읽기 요청만 발생하는 저장소는 점검 작업의 개선 혜택을 누리거나 수혜를 받을 수 없습니다.

관리자는 모든 저장소에서 사용자 정의 간격으로 점검을 수행하는 백그라운드 작업을 활성화하여 이 상황을 해결할 수 있습니다. 이 백그라운드 작업은 랜덤한 순서로 Gitaly 노드에서 호스팅되는 모든 저장소를 처리하고, 해당 저장소에 대해 점검 작업을 적극적으로 수행합니다. Gitaly 노드는 설정된 간격보다 오래 걸리면 저장소 처리 작업을 중단합니다.

예약된 점검 구성

Git 저장소의 배경 유지 관리는 Gitaly에서 구성됩니다. 기본적으로 Gitaly는 매일 정오 12:00에 10분 동안 백그라운드 저장소 유지 관리를 수행합니다.

Gitaly 구성에서 이 기본값을 변경할 수 있습니다.

Gitaly 클러스터가 있는 환경에서는 예약된 점검 시작 시간을 Gitaly 노드 간에 분산시켜 여러 노드에서 예약된 점검이 동시에 실행되지 않도록 할 수 있습니다.

예약된 점검 실행이 지정된 duration에 도달하면 실행 중인 작업이 정상적으로 취소됩니다. 이후 예약된 점검에서 Gitaly는 저장소 목록을 무작위로 셔플하여 처리합니다.

다음 스니펫을 사용하여 default 저장소에 대해 매일 23:00부터 1시간 동안 백그라운드 저장소 유지 관리를 활성화합니다:

소스 컴파일(자체 컴파일)
[daily_maintenance]
start_hour = 23
start_minute = 00
duration = 1h
storages = ["default"]

다음 스니펫을 사용하여 백그라운드 저장소 유지 관리를 완전히 비활성화할 수 있습니다:

[daily_maintenance]
disabled = true
리눅스 패키지(Omnibus)
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분 이상 걸리지 않고 완료되었습니다.

오브젝트 풀 리포지토리

오브젝트 풀 리포지토리는 GitLab이 리포지토리의 포크 간에 오브젝트를 중복 제거하는 데 사용됩니다. 첫 번째 포크를 생성할 때, 우리는:

  1. 포크하려는 리포지토리의 모든 오브젝트를 포함하는 오브젝트 풀 리포지토리를 생성합니다.
  2. Git의 alternates 메커니즘을 통해 이 새로운 오브젝트 풀에 리포지토리를 연결합니다.
  3. 리포지토리를 다시 패킹하여 오브젝트 풀의 오브젝트를 사용하도록 합니다. 따라서 자체 오브젝트 사본을 삭제할 수 있습니다.

이 리포지토리의 모든 포크는 이제 오브젝트 풀에 연결할 수 있으며, 따라서 기본 리포지토리에서 분기된 오브젝트만 유지하면 됩니다.

GitLab은 오브젝트 풀에서 특별한 관리 작업을 수행해야 합니다:

  • Gitaly는 언제든지 오브젝트 풀에서 도달 불가능한 오브젝트를 삭제할 수 없습니다. 왜냐하면 이러한 오브젝트는 연결된 포크 중 어떤 것에서도 사용될 수 있기 때문입니다.

  • Gitaly는 같은 이유로 도달 가능한 모든 오브젝트를 유지해야 합니다. 따라서 오브젝트 풀은 도달 불가능한 “맨손” 오브젝트에 대한 참조를 유지하여 삭제되지 않도록 합니다.

  • GitLab은 기본 리포지토리에 추가된 새로운 오브젝트를 가져오기 위해 오브젝트 풀을 정기적으로 업데이트해야 합니다. 그렇지 않으면 오브젝트 풀은 오브젝트 중복 제거에서 점점 비효율적이게 됩니다.

이러한 관리 작업은 모든 특별 작업을 처리하면서도 표준 Git 리포지토리에 대해 수행하는 일반 관리 작업을 실행하는 특수화된 FetchIntoObjectPool RPC에 의해 수행됩니다.

오브젝트 풀은 기본 멤버가 가비지 수집될 때 자동으로 최적화됩니다. 따라서 주기는 해당 프로젝트의 동일한 Git GC 주기를 사용하여 구성할 수 있습니다.

레이얼 콘솔에서 RPC를 수동으로 호출해야 하는 경우, project.pool_repository.object_pool.fetch를 호출할 수 있습니다. 이는 잠재적으로 긴 작업이지만, Gitaly는 약 8시간 후에 시간 초과됩니다.