Gitaly 클러스터 Troubleshooting

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

Gitaly 클러스터 (Praefect)를 Troubleshooting할 때 아래 정보를 참조하십시오. Gitaly의 Troubleshooting 정보는 Troubleshooting Gitaly를 참조하십시오.

클러스터 상태 확인

check Praefect 하위 명령어는 Gitaly 클러스터의 상태를 확인하기 위해 일련의 체크를 실행합니다.

gitlab-ctl praefect check

Praefect가 Praefect 차트를 사용하여 배포된 경우에는 바이너리를 직접 실행하십시오.

/usr/local/bin/praefect check

다음 섹션에서 실행되는 체크를 설명합니다.

Praefect 마이그레이션

Praefect가 올바르게 작동하려면 데이터베이스 마이그레이션이 최신 상태여야 하므로, Praefect 마이그레이션이 최신 상태인지 확인합니다.

이 체크가 실패하는 경우:

  1. 데이터베이스의 schema_migrations 테이블을 확인하여 실행된 마이그레이션을 확인하십시오.
  2. 마이그레이션을 최신 상태로 가져오려면 praefect sql-migrate를 실행하십시오.

노드 연결 및 디스크 접근

Praefect가 모든 Gitaly 노드에 도달할 수 있는지, 각 Gitaly 노드가 모든 스토리지에 대해 읽고 쓰기 액세스를 가지고 있는지 확인합니다.

이 체크가 실패하는 경우:

  1. 네트워크 주소 및 토큰이 올바르게 설정되어 있는지 확인하십시오:
    • Praefect 구성에서
    • 각 Gitaly 노드의 구성에서
  2. Gitaly 노드에서 실행 중인 gitaly 프로세스가 git으로 실행되는지 확인하십시오. Gitaly가 스토리지 디렉터리에 액세스하는 데 문제가 될 수 있는 권한 문제가 있을 수 있습니다.
  3. Praefect를 Gitaly 노드에 연결하는 네트워크에 문제가 없는지 확인하십시오.

데이터베이스 읽기 및 쓰기 액세스

Praefect가 데이터베이스에서 읽기 및 쓰기를 할 수 있는지 확인합니다.

이 체크가 실패하는 경우:

  1. Praefect 데이터베이스가 복구 모드인지 확인하십시오. 복구 모드에서는 테이블이 읽기 전용일 수 있습니다. 확인하려면 다음을 실행하십시오:

    select pg_is_in_recovery()
    
  2. PostgreSQL에 연결하는 Praefect 사용자가 데이터베이스에 대해 읽기 및 쓰기 액세스 권한을 가지고 있는지 확인하십시오.
  3. 데이터베이스가 읽기 전용 모드로 설정되었는지 확인하십시오. 확인하려면 다음을 실행하십시오:

    show default_transaction_read_only
    

액세스할 수 없는 저장소

주(primary) 할당이 없거나 primary가 사용할 수 없는 경우, 액세스할 수 없는 저장소가 몇 개 있는지 확인합니다.

이 체크가 실패하는 경우:

  1. Gitaly 노드 중 어떤 것이 다운되었는지 확인하십시오. 확인하려면 praefect ping-nodes를 실행하십시오.
  2. Praefect 데이터베이스의 부하가 있는지 확인하십시오. Praefect 데이터베이스가 응답이 지연되면 건강 상태 체크가 데이터베이스에 지속적으로 실패하여 Praefect가 노드가 비정상적이라고 판단할 수 있습니다.

시계 동기화 확인

Praefect와 Gitaly 서버 간의 인증에는 서버 시간이 서로 60초 이내여야 하므로 토큰 확인이 성공해야 합니다.

이 체크는 permission denied 에러의 근본 원인을 식별하는 데 도움이 됩니다 저장소에 액세스할 때 Gitaly 또는 Praefect 로그에 기록된 permission denied 에러가 있습니다.

공인 pool.ntp.org 서버에 액세스할 수 없는 오프라인 환경의 경우, Praefect check 하위 명령어는 다음과 유사한 오류 메시지와 함께이 체크가 실패합니다:

checking with NTP service at  and allowed clock drift 60000ms [correlation_id: <XXX>]
Failed (fatal) error: gitaly node at tcp://[gitlab.example-instance.com]:8075: rpc error: code = DeadlineExceeded desc = context deadline exceeded

이 문제를 해결하려면 Praefect 서버의 모든 환경 변수를 접근 가능한 내부 Network Time Protocol (NTP) 서버를 가리키도록 설정하십시오. 예:

export NTP_HOST=ntp.example.com

Praefect 로그의 오류

오류가 발생하면 /var/log/gitlab/gitlab-rails/production.log을 확인하십시오.

일반적인 오류 및 잠재적인 원인은 다음과 같습니다:

  • 500 응답 코드
    • ActionView::Template::Error (7:permission denied)
      • GitLab 서버에서 praefect['configuration'][:auth][:token]gitlab_rails['gitaly_token']이 일치하지 않습니다.
      • Sidekiq 서버에서 git_data_dirs 스토리지 구성이 누락되었습니다.
    • Unable to save project. Error: 7:permission denied
      • GitLab 서버의 praefect['configuration'][:virtual_storage]에 있는 시크릿 토큰이 하나 이상의 Gitaly 서버의 gitaly['auth_token'] 값과 일치하지 않습니다.
  • 503 응답 코드
    • GRPC::Unavailable (14:failed to connect to all addresses)
      • GitLab이 Praefect에 도달하지 못했습니다.
    • GRPC::Unavailable (14:all SubCons are in TransientFailure...)
      • Praefect가 하나 이상의 하위 Gitaly 노드에 도달하지 못했습니다. 진단을 위해 Praefect 연결 확인기를 실행하십시오.

Praefect 데이터베이스의 고용량 CPU 부하

Praefect 데이터베이스가 고용량 CPU 사용량을 경험하는 일반적인 이유는 다음과 같습니다:

  • Prometheus 메트릭 스크랩 및 비용이 드는 쿼리 실행. gitlab.rb에서 praefect['configuration'][:prometheus_exclude_database_from_default_metrics] = true를 설정하십시오.
  • 사용자 트래픽이 많아질 때 데이터베이스로의 쿼리 횟수가 증가함으로써 Read distribution caching이 비활성화될 수 있습니다. 읽기 분배 캐싱이 활성화되어 있는지 확인하십시오.

주(primary) Gitaly 노드 결정

저장소의 주(primary) 노드를 결정하려면 praefect metadata 하위 명령어를 사용하십시오.

저장소 메타데이터 보기

Gitaly 클러스터는 클러스터에 저장된 저장소에 대한 메타데이터 데이터베이스를 유지합니다. 메타데이터를 Troubleshooting할 때 praefect metadata 하위 명령어를 사용하십시오.

Praefect가 할당한 저장소 ID로 저장소의 메타데이터를 검색할 수 있습니다:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id <repository-id>

물리적 저장소의 물리적 경로가 @cluster로 시작하는 경우 물리적 경로에서 저장소 ID를 찾을 수 있습니다.

또는 가상 스토리지와 상대 경로로 저장소의 메타데이터를 검색할 수 있습니다:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage <virtual-storage> -relative-path <relative-path>

예시

Praefect가 할당한 저장소 ID가 1인 저장소의 메타데이터를 검색하려면:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id 1

가상 저장소 default와 상대 경로 @hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git를 사용하는 저장소의 메타데이터를 검색하려면:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage default -relative-path @hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git

이러한 예시 중 하나를 사용하여 예시 저장소의 다음 메타데이터를 검색합니다:

저장소 ID: 54771
가상 저장소: "default"
상대 경로: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
복제본 경로: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
기본: "gitaly-1"
세대: 1
복제본:
- 저장소: "gitaly-1"
  할당: true
  세대: 1, 완전히 최신
  건강 상태: true
  유효한 기본: true
  확인 시간: 2021-04-01 10:04:20 +0000 UTC
- 저장소: "gitaly-2"
  할당: true
  세대: 0, 1개의 변경 뒤쳐짐
  건강 상태: true
  유효한 기본: false
  확인 시간: 미확인
- 저장소: "gitaly-3"
  할당: true
  세대: 복제본 아직 생성되지 않음
  건강 상태: false
  유효한 기본: false
  확인 시간: 미확인

사용 가능한 메타데이터

praefect metadata에 의해 검색된 메타데이터에는 다음 표에 나와 있는 필드가 포함됩니다.

필드 설명
저장소 ID Praefect가 저장소에 할당한 영구 고유 ID. GitLab이 저장소에 사용하는 ID와 다름.
가상 저장소 저장소가 저장된 가상 저장소의 이름.
상대 경로 가상 저장소 내의 저장소 경로.
복제본 경로 Gitaly 노드의 디스크에 저장된 저장소의 복제본이 있는 위치.
기본 저장소의 현재 기본.
세대 Praefect에서 저장소 변경을 추적하기 위해 사용됨. 저장소에 작성할 때마다 저장소의 세대가 증가함.
복제본 존재하거나 예상되는 복제본 목록.

각 복제본에 대해 다음 메타데이터를 사용할 수 있습니다:

복제본 필드 설명
저장소 복제본을 포함하는 Gitaly 저장소의 이름.
할당 복제본이 해당 저장소에 존재할 것으로 예상되는지를 나타냄. 저장소의 복제본 요소가 감소된 후 추가적인 복사본이 있는 경우 또는 Gitaly 노드가 클러스터에서 제거된 경우 false가 될 수 있음.
세대 복제본의 최신 확인된 세대. 세대가 저장소의 세대와 일치하는 경우 복제본이 완전히 최신 상태임을 나타냄.

세대가 저장소의 세대보다 작은 경우 복제본이 오래됨을 나타냄.

replica not yet created는 복제본이 저장소에 아직 존재하지 않음을 나타냄.
건강 상태 이 복제본을 호스팅하는 Gitaly 노드가 Praefect 노드의 합의에 의해 건강하다고 간주되는지를 나타냄.
유효한 기본 복제본이 주 노드로서의 역할을 할 수 있는지를 나타냄. 저장소의 주 노드가 유효한 주 노드가 아닌 경우, 또 다른 복제본이 유효한 주 노드인 경우 저장소에 쓰기가 발생할 때 장애 조치가 발생함.

- 건강한 Gitaly 노드에 저장됨
- 완전히 최신임
- 감소 복제 요소의 보류 중인 삭제 작업에 대상으로 지정되지 않음
- 할당됨
확인 시간 복제본의 마지막 성공적인 확인 시간을 나타냄. 확인 worker에 의해 아직 확인되지 않았다면, 마지막 성공적인 확인 시간 대신에 unverified가 표시됨. GitLab 15.0 버전에서 도입됨.

‘저장소를 찾을 수 없음’과 함께 명령어 실행 실패

-virtual-storage에 제공된 값이 잘못된 경우, 명령어는 다음 오류를 반환합니다:

메타데이터 받기: rpc 오류: code = NotFound desc = repository not found

문서화된 예시는 -virtual-storage default를 지정합니다. Praefect 서버 설정 /etc/gitlab/gitlab.rbpraefect['configuration'][:virtual_storage]를 확인하세요.

저장소 동기화 확인하기

일부 경우에는 Praefect 데이터베이스가 기본 Gitaly 노드와 동기화되지 않을 수 있습니다. 특정 저장소가 모든 노드에서 완전히 동기화되었는지 확인하려면 Rails 노드에서 gitlab:praefect:replicas Rake 작업을 실행하세요. 이 Rake 작업은 모든 Gitaly 노드에서 저장소를 체크섬합니다.

Praefect dataloss 명령어는 Praefect 데이터베이스의 저장소 상태만을 확인하며, 이 상황에서는 동기화 문제를 감지하는 데 신뢰할 수 없습니다.

dataloss 명령어는 @failed-geo-sync 리포지토리를 동기화되지 않은 것으로 표시합니다.

@failed-geo-sync는 Geo가 프로젝트 동기화에 실패했을 때 GitLab 16.1 및 이전 버전에서 사용된 레거시 경로이며 deprecated되었습니다.

GitLab 16.2 이상에서는 이 경로를 안전하게 삭제할 수 있습니다. @failed-geo-sync 디렉터리는 Gitaly 노드의 저장소 경로 아래에 위치합니다.

관계가 존재하지 않는 오류

기본적으로 Praefect 데이터베이스 테이블은 gitlab-ctl reconfigure 작업에 의해 자동으로 생성됩니다.

그러나 초기 재구성시 Praefect 데이터베이스 테이블이 생성되지 않을 수 있으며 다음 사항으로 인해 관계가 존재하지 않는 오류가 발생할 수 있습니다:

  • gitlab-ctl reconfigure 명령이 실행되지 않은 경우.
  • 실행 중에 오류가 발생한 경우.

예를 들어:

  • ERROR: relation "node_status" does not exist at character 13
  • ERROR: relation "replication_queue_lock" does not exist at character 40
  • 다음 오류:

    {"level":"error","msg":"Error updating node: pq: relation \"node_status\" does not exist","pid":210882,"praefectName":"gitlab1x4m:0.0.0.0:2305","time":"2021-04-01T19:26:19.473Z","virtual_storage":"praefect-cluster-1"}
    

이를 해결하려면 praefect 명령어의 sql-migrate 하위 명령을 사용하여 데이터베이스 스키마 마이그레이션을 수행할 수 있습니다:

$ sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
praefect sql-migrate: OK (applied 21 migrations)

‘repository scoped: invalid Repository’ 오류로 요청 실패

이는 Praefect 구성에서 사용된 가상 저장소 이름이 GitLab의 gitaly['configuration'][:storage][<index>][:name] 설정 에 사용된 저장소 이름과 일치하지 않음을 나타냅니다.

Praefect 및 GitLab 구성에서 사용된 가상 저장소 이름을 일치시켜 이 문제를 해결하십시오.

클라우드 플랫폼에서의 Gitaly 클러스터 성능 문제

Praefect에는 많은 CPU 또는 메모리가 필요하지 않으며, 소형 가상 머신에서 실행할 수 있습니다. 클라우드 서비스는 디스크 IO 및 네트워크 트래픽과 같은 리소스에 대한 소형 VM의 사용 제한을 둘 수 있습니다.

Praefect 노드는 많은 네트워크 트래픽을 생성합니다. 클라우드 서비스에 의해 네트워크 대역폭이 제한되면 다음과 같은 증상이 나타날 수 있습니다:

  • Git 작업의 성능이 저하됨.
  • 높은 네트워크 지연.
  • Praefect에 의한 높은 메모리 사용.

가능한 해결책:

  • 더 큰 VM을 프로비저닝하여 더 큰 네트워크 트래픽을 얻을 수 있도록 함.
  • 클라우드 서비스의 모니터링 및 로깅을 사용하여 Praefect 노드가 트래픽 할당량을 초과하지 않는지 확인함.

gitlab-ctl reconfigure이 Praefect 구성 오류로 실패하는 경우

gitlab-ctl reconfigure가 실패하면 다음 오류를 볼 수 있습니다:

STDOUT: praefect: configuration error: error reading config file: toml: cannot store TOML string into a Go int

이 오류는 praefect['database_port'] 또는 praefect['database_direct_port']가 정수가 아닌 문자열로 구성된 경우에 발생합니다.

일반적인 복제 오류

다음은 일반적인 복제 오류와 가능한 해결책입니다.

잠금 파일이 존재함

잠금 파일은 동일한 ref에 대한 여러 업데이트를 방지하는 데 사용됩니다. 때로는 잠금 파일이 오래되어 error: cannot lock ref와 같은 복제 실패 오류가 발생할 수 있습니다.

잽금 *.lock 파일을 지우려면 Rails 콘솔에서 OptimizeRepositoryRequest를 트리거할 수 있습니다:

p = Project.find <Project ID>
client = Gitlab::GitalyClient::RepositoryService.new(p.repository)
client.optimize_repository

OptimizeRepositoryRequest를 트리거해도 작동하지 않으면 생성 날짜를 확인하고 *.lock 파일을 수동으로 삭제할 수 있습니다. 24시간 이상 전에 생성된 잠금 파일은 안전하게 제거할 수 있습니다.

Git fsck 오류

유효하지 않은 객체가 있는 Gitaly 리포지토리는 Gitaly 로그의 오류와 함께 복제 실패로 이어질 수 있습니다:

  • exit status 128, stderr: "fatal: git upload-pack: not our ref".
  • "fatal: bad object 58....e0f... ssh://gitaly/internal.git did not send all necessary objects.

적어도 하나의 Gitaly 노드에 여전히 리포지토리의 건전한 사본이 남아 있는 경우 다음과 같이 이 문제를 해결할 수 있습니다:

  1. Praefect 데이터베이스에서 리포지토리 제거.
  2. Praefect track-repository 하위 명령을 사용하여 다시 추적합니다.

이렇게 하면 권위있는 Gitaly 노드에 있는 리포지토리의 사본을 모든 다른 Gitaly 노드에 덮어씁니다. 이 명령을 실행하기 전에 리포지토리의 최신 백업이 수행되었는지 확인하십시오.

  1. 잘못된 리포지토리를 제 위치에서 이동:

    run `mv <REPOSITORY_PATH> <REPOSITORY_PATH>.backup`
    

    예:

    mv /var/opt/gitlab/git-data/repositories/@cluster/repositories/de/74/2335 /var/opt/gitlab/git-data/repositories/@cluster/repositories/de/74/2335.backup
    
  2. 복제를 트리거하기 위해 Praefect 명령을 실행합니다:

    # 올바른 리포지토리를 사용하는지 확인합니다.
    sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage gitaly -relative-path '<relative_path>' -db-only
    
    # '--apply' 플래그와 함께 다시 실행하여 Praefect 추적 데이터베이스에서 리포지토리를 제거합니다.
    sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage gitaly -relative-path '<relative_path>' -db-only --apply
    
    # 다른 노드에 덮어씌우기 위해 리포지토리를 다시 추적합니다
    sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage gitaly -authoritative-storage '<healthy_gitaly>' -relative-path '<relative_path>' -replica-path '<replica_path>'-replicate-immediately
    

복제 실패 시 조용한 문제 발견

만일 Praefect dataloss에서 저장소가 일부 사용 불가능한 것으로 나타나는 경우, 그리고 accept-dataloss 명령이 로그에 오류가 표시되지 않은 채로 저장소를 동기화하지 못하는 경우, 이는 storage_repositories 테이블의 repository_id 필드의 Praefect 데이터베이스 불일치로 인한 것일 수 있습니다. 불일치 여부를 확인하려면:

  1. Praefect 데이터베이스에 연결합니다.
  2. 다음 쿼리를 실행합니다:

    select * from storage_repositories where relative_path = '<relative-path>';
    

    <relative-path> @hashed으로 시작하는 저장소 경로로 대체합니다.

대체 디렉토리가 존재하지 않음

GitLab은 Git 대체 메커니즘을 사용하여 중복 제거를 수행합니다. alternates@pool 저장소의 objects 디렉토리를 가리키는 텍스트 파일입니다. 이 파일이 잘못된 경로를 가리키고 있다면, 다음과 같은 오류 중 하나로 복제가 실패할 수 있습니다:

  • "error":"no alternates directory exists", "warning","msg":"alternates file does not point to valid git repository"
  • "error":"unexpected alternates content:
  • remote: error: unable to normalize alternate object path

이 오류의 원인을 조사하려면:

  1. Rails 콘솔을 사용하여 프로젝트가 풀의 일부인지 확인합니다:

    project = Project.find_by_id(<project id>)
    project.pool_repository
    
  2. 디스크에서 풀 저장소 경로가 존재하며 이 경로가 alternates 파일의 내용과 일치하는지 확인합니다.
  3. 프로젝트의 objects 디렉토리에서 alternates 파일의 경로가 도달 가능한지 확인합니다.

이러한 확인을 수행한 후, 수집한 정보와 함께 GitLab 지원팀에 문의하십시오.