Gitaly Cluster 복구 옵션 및 도구

Gitaly Cluster는 기본 노드의 장애 및 사용 불가능한 리포지터리에서 복구할 수 있습니다. Gitaly Cluster는 데이터 복구를 수행하며 Praefect 추적 데이터베이스 도구를 보유하고 있습니다.

Gitaly Cluster의 Gitaly 노드 관리

Gitaly Cluster에서 Gitaly 노드를 추가하고 교체할 수 있습니다.

새로운 Gitaly 노드 추가

새로운 Gitaly 노드를 Gitaly Cluster에 추가하는 단계는 사용자 지정 복제 요소가 설정되어 있는지에 따라 달라집니다.

사용자 지정 복제 요소

사용자 지정 복제 요소가 설정된 경우, set-replication-factor Praefect 명령을 사용하여 각 리포지터리의 복제 요소를 설정합니다. 새로운 리포지터리는 복제 요소를 기반으로 복제됩니다. Praefect는 기존 리포지터리를 자동으로 새로운 Gitaly 노드로 복제하지 않습니다.

기본 복제 요소

기본 복제 요소를 사용하는 경우, 새로운 노드를 praefect['virtual_storages']에서 Praefect 구성에 추가합니다. Praefect는 구성에 추가된 새로운 Gitaly 노드로 모든 데이터를 자동으로 복제합니다.

기존 Gitaly 노드 교체

기존 Gitaly 노드를 동일한 이름 또는 다른 이름의 새 노드로 교체할 수 있습니다.

동일한 이름의 노드로

교체 노드에 동일한 이름을 사용하려면 리포지터리 확인기를 사용하여 리포지터리를 스캔하고 불필요한 메타데이터 레코드를 제거합니다. 교체된 리포지터리의 검증을 매뉴얼으로 우선순위를 지정하여 프로세스를 가속화하세요.

다른 이름의 노드로

Gitaly Cluster에서 교체 노드에 대해 다른 이름을 사용하는 단계는 사용자 정의 복제 요소가 설정되어 있는지에 따라 다릅니다.

사용자 정의 복제 요소 설정

사용자 지정 복제 요소가 설정된 경우, 새 리포지터리가 할당되도록 다시 각 리포지터리마다 복제 요소를 설정하기 위해 praefect set-replication-factor를 사용합니다. 예시:

$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage default -relative-path @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git -replication-factor 2

현재 할당: gitaly-1, gitaly-2

새로운 Gitaly 노드를 구성한 후 이전 리포지터리의 모든 리포지터리를 새로운 리포지터리로 재할당하려면:

  1. Praefect 데이터베이스에 연결:

    /opt/gitlab/embedded/bin/psql -h <psql 호스트> -U <사용자> -d <데이터베이스 이름>
    
  2. repository_assignments 테이블을 업데이트하여 이전 Gitaly 노드 이름(예: old-gitaly)을 새 Gitaly 노드 이름(예: new-gitaly)으로 대체합니다:

    UPDATE repository_assignments SET storage='new-gitaly' WHERE storage='old-gitaly';
    
기본 복제 요소 설정

기본 복제 요소를 사용하는 경우, 구성에서 노드를 교체합니다. 이전 노드의 상태는 Praefect 데이터베이스에 남지만 무시됩니다.

기본 노드 장애

기본 Gitaly 노드의 장애를 복구하려면 Gitaly Cluster가 건강한 보조 노드를 새 기본으로 승격합니다. Gitaly Cluster는 다음을 수행합니다:

  • 리포지터리의 최신 복사본이 있는 건강한 보조를 새 기본으로 선택합니다.
  • 완전히 최신화되지 않은 보조가 없는 경우, 미완료된 복제 라이트가 가장 적은 보조를 새 기본으로 선택합니다.
  • 건강한 보조에 최신 복사본이 없는 경우 리포지터리는 사용 불가능해집니다. Praefect dataloss 하위 명령을 사용하여 이를 감지합니다.

사용 불가능한 리포지터리

모든 최신 복제본의 사용 불가능한 리포지터리입니다. 사용 불가능한 리포지터리는 자동화된 도구를 망가뜨릴 수 있는 낡은 데이터를 제공하지 않도록 Praefect를 통해 액세스할 수 없습니다.

데이터 손실 확인

Praefect dataloss 하위 명령은 사용 불가능한 리포지터리를 식별합니다. 이를 통해 잠재적인 데이터 손실과 더 이상 액세스할 수 없는 리포지터리를 식별합니다.

다음 매개변수가 사용 가능합니다:

  • 출력된 리포지터리가 관리자 개입이 필요할 수 있기 때문에 기본 동작은 사용 불가능한 리포지터리를 표시하는 것입니다.
  • -부분적으로 사용 불가능은 사용 가능하지만 일부 할당된 복사본이 사용 불가능한 리포지터리를 출력에 포함해야 하는지를 지정합니다.
note
dataloss는 여전히 베타 단계이며 출력 형식이 변경될 수 있습니다.

이전 처리 방식이나 사용 불가능한 리포지터리를 확인하려면 다음을 실행하세요:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <가상 리포지터리>]

지정되지 않으면 모든 구성된 가상 리포지터리가 확인됩니다:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss

사용 불가능한 최신 복제본이 포함된 리포지터리가 출력됩니다. 다음 정보가 각 리포지터리에 대해 인쇄됩니다:

  • 리포지터리의 리포지터리 디렉터리 상대 경로는 각 리포지터리를 식별하고 관련 정보를 그룹화합니다.
  • 사용 불가능한 경우 디스크 경로 옆에 (사용 불가능)이 인쇄됩니다.
  • 기본 필드는 리포지터리의 현재 기본을 나열합니다. 리포지터리에 기본이 없으면 필드에 기본 없음이 표시됩니다.
  • 동기화된 리포지터리는 최신 성공적인 라이트 및 그 이전 모든 라이트를 복제한 복제본을 나열합니다.
  • 구식 리포지터리는 리포지터리의 오래된 사본을 포함한 복제본을 나열합니다. 복제본은 리포지터리의 최대 변경 수가 오른쪽에 표시됩니다. 구식 복제본은 완전히 최신화되었을 수 있거나 나중의 변경 사항을 포함할 수 있지만 Praefect는 보장하지 않습니다.

추가 정보는 다음을 포함합니다:

  • 노드가 리포지터리를 호스트로 할당되어 있는지를 나타내는 정보가 각 노드의 상태와 함께 나열됩니다. 리포지터리를 저장할 노드에 할당된 호스트가 인쇄됩니다. 노드에 리포지터리의 사본이 포함되어 있지만 리포지터리를 저장할 노드로 할당되지 않은 경우 텍스트가 표시됩니다. 이러한 사본은 Praefect에 의해 동기화되지 않지만 할당된 사본을 최신 상태로 유지하는 복제 소스로 작용할 수 있습니다.
  • 비정상은 건강하지 않은 Gitaly 노드에 위치한 사본 옆에 인쇄됩니다.

예시 출력:

가상 리포지터리: default
  구식 리포지터리:
    @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git (사용 불가능):
      기본: gitaly-1
      동기화된 리포지터리:
        gitaly-2, 할당된 호스트, 비정상
      구식 리포지터리:
        gitaly-1은 3개 이하의 변경 사항으로 뒤처져 있음, 할당된 호스트
        gitaly-3은 3개 이하의 변경 사항으로 뒤처져 있음

모든 리포지터리가 사용 가능한 경우 확인이 출력됩니다. 예를 들어:

가상 리포지터리: default
  모든 리포지터리가 사용 가능합니다!

사용 불가능한 복제본의 사용 가능 리포지터리

일부 할당된 노드에서 사용 불가능하지만 사용 가능한 리포지터리의 정보도 나열하려면 -partially-unavailable 플래그를 사용하세요.

최신 변경 사항을 복제하는 동안 일부 할당된 보조 복제본은 일시적으로 액세스할 수 없을 수 있지만, 리포지터리가 건강하고 최신 상태인 경우 사용 가능합니다.

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <가상-리포지터리>] [-partially-unavailable]

예시 출력:

가상 리포지터리: default
  오래된 리포지터리:
    @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git:
      기본: gitaly-1
      동기화된 리포지터리:
        gitaly-1, 할당된 호스트
      오래된 리포지터리:
        gitaly-2는 3개 이하의 변경으로 뒤처져 있음, 할당된 호스트
        gitaly-3는 3개 이하의 변경으로 뒤처져 있음

-partially-unavailable 플래그가 설정되면, 모든 할당된 복제본이 완전히 최신이고 건강하면 확인이 출력됩니다.

예를 들어:

가상 리포지터리: default
  모든 리포지터리가 모든 할당된 리포지터리에서 완전히 사용 가능합니다!

리포지터리 체크섬 확인

모든 Gitaly 노드에서 프로젝트의 리포지터리 체크섬을 확인하려면, 메인 GitLab 노드에서 복제본 레이크 태스크를 실행하세요.

데이터 손실 승인

경고: accept-dataloss는 리포지터리의 다른 버전을 덮어쓰는 방식으로 영구적인 데이터 손실을 유발합니다. 사용하기 전에 데이터 복구 작업을 수행해야 합니다.

최신의 복제본을 다시 온라인으로 가져올 수 없는 경우에 데이터 손실을 받아들여야 할 수 있습니다. 데이터 손실을 받아들일 때 Praefect는 리포지터리의 선택한 복제본을 최신 버전으로 표시하고 다른 할당된 Gitaly 노드에 복제합니다. 이 과정에서 다른 리포지터리의 어떠한 다른 버전도 덮어쓰므로 주의가 필요합니다.

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss -virtual-storage <가상-리포지터리> -relative-path <상대-경로> -authoritative-storage <리포지터리-이름>

쓰기 기능 사용 또는 데이터 손실 승인

경고: accept-dataloss는 리포지터리의 다른 버전을 덮어쓰는 방식으로 영구적인 데이터 손실을 유발합니다. 사용하기 전에 데이터 복구 작업을 수행해야 합니다.

Praefect는 쓰기 기능을 다시 사용하거나 데이터 손실을 받아들일 수 있는 다음과 같은 하위 명령을 제공합니다. 최신 상태의 노드 중 하나를 다시 온라인으로 가져올 수 없는 경우에 데이터 손실을 받아들여야 할 수 있습니다:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss -virtual-storage <가상-리포지터리> -relative-path <상대-경로> -authoritative-storage <리포지터리-이름>

데이터 손실을 받아들일 때, Praefect는:

  1. 리포지터리의 선택한 복사본을 최신 버전으로 표시합니다.
  2. 다른 할당된 Gitaly 노드에 복사본을 복제합니다.

이 과정에서 다른 복사본을 덮어쓰므로 주의가 필요합니다.

데이터 복구

Gitaly 노드가 어떠한 이유로 복제 작업을 실패하면, 해당 리포지터리에 영향을 받는 오래된 버전을 호스팅하게 됩니다. Praefect는 자동 조정을 위한 도구를 제공합니다. 이 도구는 오래된 리포지터리를 완전히 최신으로 만들기 위해 조정 작업을 수행합니다.

Praefect는 기본적으로 모든 5분마다 최신이 아닌 리포지터리를 자동으로 조정합니다. 건강한 Gitaly 노드의 각 오래된 리포지터리에 대해, Praefect는 다른 건강한 Gitaly 노드에 있는 리포지터리의 임의로 선택된 완전히 최신 복사본을 복제합니다. 대상 리포지터리에 대기 중인 다른 복제 작업이 없는 경우에만 복제 작업이 예약됩니다.

조정 빈도는 구성을 통해 변경할 수 있습니다. 값은 유효한 Go 기간 값 일 수 있습니다. 0 이하의 값을 입력하면 기능이 비활성화됩니다.

예시:

praefect['configuration'] = {
   # ...
   reconciliation: {
      # ...
      scheduling_interval: '5m', # 기본 값
   },
}
praefect['configuration'] = {
   # ...
   reconciliation: {
      # ...
      scheduling_interval: '30s', # 30초마다 조정
   },
}
praefect['configuration'] = {
   # ...
   reconciliation: {
      # ...
      scheduling_interval: '0', # 기능 비활성화
   },
}

매뉴얼으로 리포지터리 제거

  • GitLab 15.3에 도입, Praefect 추적 데이터베이스에서 리포지터리를 제거하는 기능을 지원합니다.

remove-repository Praefect 하위 명령은 Gitaly 클러스터에서 리포지터리와 해당 리포지터리에 연결된 모든 상태를 제거합니다:

  • 관련 Gitaly 노드의 디스크 상의 리포지터리
  • Praefect가 추적하는 데이터베이스 상의 모든 상태

명령은 기본적으로 시뮬레이션 모드에서 작동합니다. 예를 들어:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage <가상-리포지터리> -relative-path <리포지터리>
  • <가상-리포지터리>를 리포지터리를 포함하는 가상 리포지터리의 이름으로 대체하세요.
  • <리포지터리>를 제거할 리포지터리의 상대 경로로 대체하세요.
  • GitLab 15.3 이상에서는 -db-only를 추가하여 시뮬레이션에서 데이터베이스 추적 항목을 제거하고 올바른 리포지터리가 실수로 지정된 경우, 온디스크 리포지터리 데이터를 보호하기 위해 사용합니다. 데이터베이스 항목이 실수로 삭제된 경우, track-repository 명령을 사용하여 리포지터리를 다시 추적합니다.
  • 리포지터리를 제거하려면 명령을 시뮬레이션 모드 이외로 실행하도록 -apply를 추가합니다. 예를 들어:

    sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage <가상-리포지터리> -relative-path <리포지터리> -apply
    
  • -virtual-storage는 리포지터리가 위치한 가상 리포지터리입니다. 가상 리포지터리는 /etc/gitlab/gitlab.rb에 있는 praefect['configuration']['virtual_storage]에서 구성되며 다음과 같이 보입니다:

    praefect['configuration'] = {
      # ...
      virtual_storage: [
        {
          # ...
          name: 'default',
        },
        {
          # ...
          name: 'storage-1',
        },
      ],
    }
    

    이 예에서 가상 리포지터리는 default 또는 storage-1을 지정합니다.

  • -repository해시된 리포지터리 경로로 시작하는 리포지터리의 상대 경로입니다. 예를 들어:

    @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
    

remove-repository를 실행한 후에도 리포지터리 일부가 여전히 존재할 수 있습니다.

이는 삭제 오류나 리포지터리를 대상으로 하는 비행중인 RPC 호출로 인한 것일 수 있습니다.

이 경우 remove-repository를 다시 실행하세요.

Praefect 추적 데이터베이스 유지 관리

Praefect 추적 데이터베이스의 일반 유지 관리 작업은 이 섹션에 문서화되어 있습니다.

추적되지 않은 리포지터리 디렉터리

  • older-than 옵션은 GitLab 15.0에 추가되었습니다.

list-untracked-repositories Praefect 하위 명령어는 다음에 해당하는 Gitaly 클러스터의 리포지터리를 나열합니다:

  • 적어도 하나의 Gitaly 리포지터리에 존재합니다.
  • Praefect 추적 데이터베이스에 추적되지 않습니다.

-older-than 옵션을 추가하여 다음을 표시하는 것을 피할 수 있습니다:

  • 생성 중인 리포지터리들입니다.
  • Praefect 추적 데이터베이스에 아직 레코드가 없는 리포지터리들입니다.

<duration>을 시간 기간(예: 5s, 10m, 또는 1h)으로 대체합니다. 기본값은 6h입니다.

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-untracked-repositories -older-than <duration>

지정된 기간 이전에 생성된 리포지터리만을 고려합니다.

해당 명령은 다음을 출력합니다:

  • STDOUT 및 명령의 로그를 결과로 출력합니다.
  • STDERR로 오류를 출력합니다.

각 항목은 다음과 같이 완전한 JSON 문자열로 출력됩니다 (설정에 따라 변경 가능) :

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-untracked-repositories
{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567890.git"}
{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567891.git"}

단일 리포지터리를 추적 데이터베이스에 매뉴얼으로 추가

caution
Praefect 생성된 복제 경로(@cluster)로 Praefect 추적 데이터베이스에 리포지터리를 추가할 수 없는 알려진 문제로 인해 이러한 리포지터리들은 GitLab이 사용하는 리포지터리 경로와 연결되지 않으며 접근할 수 없습니다.

track-repository Praefect 하위 명령어는 디스크의 리포지터리를 Praefect 추적 데이터베이스에 추가하여 추적되도록 합니다.

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage <virtual-storage> -authoritative-storage <storage-name> -relative-path <repository> -replica-path <disk_path> -replicate-immediately
  • -virtual-storage는 리포지터리가 위치한 가상 리포지터리입니다. 가상 리포지터리는 /etc/gitlab/gitlab.rb에 있는 praefect['configuration'][:virtual_storage]에 구성되며 다음과 같은 형식을 가지고 있습니다:

    praefect['configuration'] = {
      # ...
      virtual_storage: [
        {
          # ...
          name: 'default',
        },
        {
          # ...
          name: 'storage-1',
        },
      ],
    }
    

    이 예에서 지정해야 하는 가상 리포지터리는 default 또는 storage-1입니다.

  • -relative-path는 가상 리포지터리의 상대 경로입니다. 보통 @hashed로 시작합니다. 예시:

    @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
    
  • -replica-path는 물리적 리포지터리의 상대 경로입니다. @cluster로 시작하거나 relative_path와 일치합니다.
  • -authoritative-storage는 Praefect가 주 리포지터리로 취급해야 하는 리포지터리입니다. 리포지터리별 복제가 복제 전략으로 설정된 경우 필요합니다.
  • -replicate-immediately 명령을 통해 리포지터리를 즉시 이차 복제할 수 있습니다. 그렇지 않으면 복제 작업은 데이터베이스에서 예약되어 Praefect 백그라운드 프로세스에서 실행됩니다.

명령은 다음을 출력합니다:

  • STDOUT 및 명령의 로그를 결과로 출력합니다.
  • STDERR로 오류를 출력합니다.

이 명령은 리포지터리가 이미 Praefect 추적 데이터베이스에서 추적 중인 경우, 또는 리포지터리가 디스크에 존재하지 않는 경우 실패합니다.

다수의 리포지터리를 추적 데이터베이스에 매뉴얼으로 추가

caution
Praefect 생성된 복제 경로(@cluster)로 Praefect 추적 데이터베이스에 리포지터리를 추가할 수 없는 알려진 문제로 인해 이러한 리포지터리들은 GitLab이 사용하는 리포지터리 경로와 연결되지 않으며 접근할 수 없습니다.

API를 사용한 마이그레이션은 자동적으로 리포지터리를 Praefect 추적 데이터베이스에 추가합니다.

대신 기존 인프라에서 매뉴얼으로 리포지터리를 복사하는 경우, track-repositories Praefect 하위 명령어를 사용할 수 있습니다. 이 하위 명령어는 디스크에 대규모 리포지터리를 Praefect 추적 데이터베이스에 추가합니다.

# Omnibus GitLab 설치
sudo gitlab-ctl praefect track-repositories --input-path /path/to/input.json

# 소스 설치
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repositories -input-path /path/to/input.json

명령은 모든 항목이 다음을 확인합니다:

  • 올바르게 형식이 지정되었으며 필요한 필드가 포함되어 있는지 확인합니다.
  • 유효한 Git 리포지터리에 해당하는지 확인합니다.
  • Praefect 추적 데이터베이스에 추적되지 않는지 확인합니다.

이러한 검사에 실패하는 경우 해당 리포지터리를 추적하지 않고 명령은 중단됩니다.

  • input-path는 개행으로 구분된 JSON 객체 디렉터리이 포함된 파일의 경로입니다. 객체는 다음 키를 포함해야 합니다:
    • relative_path: track-repositoryrepository와 일치합니다.
    • authoritative-storage: Praefect가 주 리포지터리로 취급하는 리포지터리입니다.
    • virtual-storage: 리포지터리가 위치한 가상 리포지터리입니다.

    예시:

    {"relative_path":"@hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git","replica_path":"@cluster/fe/d3/1","authoritative_storage":"gitaly-1","virtual_storage":"default"}
    {"relative_path":"@hashed/f8/9f/f89f8d0e735a91c5269ab08d72fa27670d000e7561698d6e664e7b603f5c4e40.git","replica_path":"@cluster/7b/28/2","authoritative_storage":"gitaly-2","virtual_storage":"default"}
    
  • -replicate-immediately, 명령을 통해 리포지터리를 즉시 이차 복제할 수 있습니다. 그렇지 않으면 복제 작업은 데이터베이스에서 예약되어 Praefect 백그라운드 프로세스에서 실행됩니다.

가상 리포지터리 세부 정보 디렉터리

list-storages Praefect 하위 명령어는 가상 리포지터리 및 해당 리포지터리 노드를 나열합니다. 가상 리포지터리가:

  • -virtual-storage를 사용하여 지정된 경우 지정된 가상 리포지터리의 리포지터리 노드만을 탭 형식으로 나열합니다.
  • 지정되지 않은 경우, 모든 가상 리포지터리 및 해당 리포지터리 노드를 탭 형식으로 나열합니다.
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-storages -virtual-storage <virtual_storage_name>

명령은 다음을 출력합니다:

  • STDOUT 및 명령의 로그를 결과로 출력합니다.
  • STDERR로 오류를 출력합니다.