Gitaly 클러스터(Praefect) 문제 해결
Offering: GitLab Self-Managed
Gitaly 클러스터(Praefect) 문제를 해결할 때 아래 정보를 참조하십시오. check Praefect 하위 명령은 Gitaly 클러스터(Praefect)의 상태를 확인하기 위한 일련의 검사를 실행합니다. Praefect가 Praefect 차트를 사용하여 배포된 경우 바이너리를 직접 실행합니다.
Gitaly 클러스터(Praefect) 문제를 해결할 때 아래 정보를 참조하십시오. Gitaly 문제 해결에 대한 정보는 Gitaly 문제 해결을 참조하십시오.
사전 요건#
관리자 액세스가 있어야 합니다.
클러스터 상태 확인#
check Praefect 하위 명령은 Gitaly 클러스터(Praefect)의 상태를 확인하기 위한 일련의 검사를 실행합니다.
gitlab-ctl praefect check
Praefect가 Praefect 차트를 사용하여 배포된 경우 바이너리를 직접 실행합니다.
/usr/local/bin/praefect check
다음 섹션에서는 실행되는 검사를 설명합니다.
Praefect 마이그레이션#
Praefect가 올바르게 작동하려면 데이터베이스 마이그레이션이 최신 상태여야 하므로 Praefect 마이그레이션이 최신 상태인지 확인합니다.
이 검사가 실패하면:
- 실행된 마이그레이션을 확인하기 위해 데이터베이스의
schema_migrations테이블을 참조합니다. praefect sql-migrate를 실행하여 마이그레이션을 최신 상태로 만듭니다.
노드 연결 및 디스크 액세스#
Praefect가 모든 Gitaly 노드에 도달할 수 있는지, 그리고 각 Gitaly 노드가 모든 스토리지에 대한 읽기 및 쓰기 액세스 권한이 있는지 확인합니다.
이 검사가 실패하면:
- 네트워크 주소와 토큰이 올바르게 설정되어 있는지 확인합니다:
- Praefect 구성에서.
- 각 Gitaly 노드의 구성에서.
- Gitaly 노드에서
gitaly프로세스가git으로 실행되고 있는지 확인합니다. Gitaly가 스토리지 디렉토리에 액세스하지 못하게 하는 권한 문제가 있을 수 있습니다. - Praefect를 Gitaly 노드에 연결하는 네트워크에 문제가 없는지 확인합니다.
데이터베이스 읽기 및 쓰기 액세스#
Praefect가 데이터베이스를 읽고 쓸 수 있는지 확인합니다.
이 검사가 실패하면:
-
Praefect 데이터베이스가 복구 모드인지 확인합니다. 복구 모드에서는 테이블이 읽기 전용일 수 있습니다. 확인하려면 다음을 실행합니다:
select pg_is_in_recovery() -
Praefect가 PostgreSQL에 연결하는 데 사용하는 사용자가 데이터베이스에 대한 읽기 및 쓰기 액세스 권한이 있는지 확인합니다.
-
데이터베이스가 읽기 전용 모드로 설정되었는지 확인합니다. 확인하려면 다음을 실행합니다:
show default_transaction_read_only
액세스 불가능한 저장소#
프라이머리 할당이 없거나 프라이머리를 사용할 수 없어 액세스할 수 없는 저장소 수를 확인합니다.
이 검사가 실패하면:
- Gitaly 노드가 다운되었는지 확인합니다. 확인하려면
praefect ping-nodes를 실행합니다. - Praefect 데이터베이스에 높은 부하가 있는지 확인합니다. Praefect 데이터베이스 응답이 느리면 상태 확인이 데이터베이스에 유지되지 않아 Praefect가 노드가 비정상적이라고 생각하게 됩니다.
로그에서 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 서버에서
gitlab_rails['repositories_storages']스토리지 구성이 누락되어 있습니다.
- GitLab 서버에서
Unable to save project. Error: 7:permission denied- GitLab 서버의
praefect['configuration'][:virtual_storage]에 있는 시크릿 토큰이 하나 이상의 Gitaly 서버의gitaly['auth_token']값과 일치하지 않습니다.
- GitLab 서버의
- 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를 설정합니다. - 읽기 분산 캐싱이 비활성화되어 사용자 트래픽이 높을 때 데이터베이스에 대한 쿼리 수가 증가합니다. 읽기 분산 캐싱이 활성화되어 있는지 확인합니다.
프라이머리 Gitaly 노드 확인#
저장소의 프라이머리 노드를 확인하려면 praefect metadata 하위 명령을 사용합니다.
저장소 메타데이터 보기#
Gitaly 클러스터(Praefect)는 클러스터에 저장된 저장소에 대한 정보가 포함된 메타데이터 데이터베이스를 유지합니다. praefect metadata 하위 명령을 사용하여 문제 해결을 위한 메타데이터를 검사합니다.
다음 중 하나로 저장소의 메타데이터를 검색할 수 있습니다:
- 가상 스토리지 및 상대 경로.
- Praefect 할당 저장소 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>
저장소 ID는 프로젝트 ID와 동일하지 않습니다.
Praefect 할당 저장소 ID로 저장소 메타데이터를 검색하려면:
-
저장소 레플리카 경로의 마지막 구성 요소를 기록합니다. 예를 들어
@cluster/repositories/6f/96/54771의 경우 저장소 ID는54771입니다. -
해당 값을 사용하여 다음 명령을 실행합니다:
sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id <repository-id>
예시#
가상 스토리지 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
Praefect 할당 저장소 ID가 1인 저장소 메타데이터를 검색하려면:
sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id 1
이 예시 중 어느 것도 예시 저장소의 다음 메타데이터를 검색합니다:
Repository ID: 54771
Virtual Storage: "default"
Relative Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
Replica Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
Primary: "gitaly-1"
Generation: 1
Replicas:
- Storage: "gitaly-1"
Assigned: true
Generation: 1, fully up to date
Healthy: true
Valid Primary: true
Verified At: 2021-04-01 10:04:20 +0000 UTC
- Storage: "gitaly-2"
Assigned: true
Generation: 0, behind by 1 changes
Healthy: true
Valid Primary: false
Verified At: unverified
- Storage: "gitaly-3"
Assigned: true
Generation: replica not yet created
Healthy: false
Valid Primary: false
Verified At: unverified
사용 가능한 메타데이터#
praefect metadata로 검색된 메타데이터는 다음 표의 필드를 포함합니다.
| 필드 | 설명 |
|---|---|
Repository ID |
Praefect에 의해 저장소에 할당된 영구적인 고유 ID. GitLab이 저장소에 사용하는 ID와 다릅니다. |
Virtual Storage |
저장소가 저장된 가상 스토리지의 이름. |
Relative Path |
가상 스토리지에서 저장소의 경로. |
Replica Path |
Gitaly 노드 디스크에서 저장소 레플리카가 저장되는 위치. |
Primary |
저장소의 현재 프라이머리. |
Generation |
저장소 변경 사항을 추적하기 위해 Praefect에서 사용됩니다. 저장소의 각 쓰기는 저장소의 세대를 증가시킵니다. |
Replicas |
존재하거나 존재해야 하는 레플리카 목록. |
각 레플리카에 대해 다음 메타데이터를 사용할 수 있습니다:
Replicas 필드 |
설명 |
|---|---|
Storage |
레플리카가 포함된 Gitaly 스토리지의 이름. |
Assigned |
레플리카가 스토리지에 존재해야 하는지 여부를 나타냅니다. Gitaly 노드가 클러스터에서 제거되거나 저장소의 복제 계수가 감소된 후 스토리지에 추가 복사본이 있는 경우 false일 수 있습니다. |
Generation |
레플리카의 최신 확인된 세대. 다음을 나타냅니다: - 세대가 저장소의 세대와 일치하면 레플리카가 완전히 최신 상태입니다. - 레플리카의 세대가 저장소의 세대보다 낮으면 레플리카가 오래된 것입니다. - 레플리카가 스토리지에 아직 전혀 존재하지 않으면 replica not yet created입니다. |
Healthy |
이 레플리카를 호스팅하는 Gitaly 노드가 Praefect 노드의 합의에 의해 정상적으로 간주되는지 여부를 나타냅니다. |
Valid Primary |
레플리카가 프라이머리 노드로 서비스할 수 있는지 여부를 나타냅니다. 저장소의 프라이머리가 유효한 프라이머리가 아닌 경우 유효한 프라이머리인 다른 레플리카가 있으면 저장소에 대한 다음 번 쓰기 시 페일오버가 발생합니다. 레플리카가 유효한 프라이머리인 경우: - 정상적인 Gitaly 노드에 저장되어 있습니다. - 완전히 최신 상태입니다. - 복제 계수 감소로 인한 보류 중인 삭제 잡의 대상이 아닙니다. - 할당되어 있습니다. |
Verified At |
검증 작업자에 의한 레플리카의 마지막 성공적인 검증을 나타냅니다. 레플리카가 아직 검증되지 않은 경우 마지막 성공적인 검증 시간 대신 unverified가 표시됩니다. |
'저장소를 찾을 수 없음'으로 명령 실패#
-virtual-storage에 제공된 값이 올바르지 않으면 명령은 다음 오류를 반환합니다:
get metadata: rpc error: code = NotFound desc = repository not found
문서화된 예시는 -virtual-storage default를 지정합니다. /etc/gitlab/gitlab.rb에서 Praefect 서버 설정 praefect['configuration'][:virtual_storage]를 확인합니다.
저장소가 동기화되어 있는지 확인#
일부 경우 Praefect 데이터베이스가 기본 Gitaly 노드와 동기화되지 않을 수 있습니다. 특정 저장소가 모든 노드에서 완전히 동기화되었는지 확인하려면 Rails 노드에서 gitlab:praefect:replicas Rake 작업을 실행합니다.
이 Rake 작업은 모든 Gitaly 노드에서 저장소의 체크섬을 계산합니다.
Praefect dataloss 명령은 Praefect 데이터베이스에서 저장소 상태만 확인하며 이 시나리오에서 동기화 문제를 감지하는 데 의존할 수 없습니다.
dataloss 명령에서 @failed-geo-sync 저장소가 동기화되지 않음으로 표시#
@failed-geo-sync는 GitLab 16.1 이하에서 프로젝트 동기화가 실패했을 때 Geo에서 사용한 레거시 경로로 더 이상 사용되지 않습니다.
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)
'저장소 범위: 잘못된 저장소' 오류로 요청 실패#
이는 Praefect 구성에서 사용된 가상 스토리지 이름이 GitLab의 gitaly['configuration'][:storage][<index>][:name] 설정에서 사용된 스토리지 이름과 일치하지 않음을 나타냅니다.
Praefect와 GitLab 구성에서 사용된 가상 스토리지 이름을 일치시켜 이를 해결합니다.
클라우드 플랫폼에서 Gitaly 클러스터(Praefect) 성능 문제#
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 노드 중 하나에 저장소의 정상적인 복사본이 있는 한 이러한 문제는 다음을 통해 수정할 수 있습니다:
- Praefect 데이터베이스에서 저장소 제거.
- Praefect
track-repository하위 명령을 사용하여 다시 추적합니다.
이렇게 하면 신뢰할 수 있는 Gitaly 노드의 저장소 복사본을 사용하여 다른 모든 Gitaly 노드의 복사본을 덮어씁니다. 이 명령을 실행하기 전에 저장소의 최근 백업이 만들어졌는지 확인합니다.
-
잘못된 저장소를 이동합니다:
run `mv .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 -
복제를 트리거하기 위한 Praefect 명령을 실행합니다:
# Validate you have the correct repository. 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 # Run again with '--apply' flag to remove repository from the Praefect tracking database 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 # Re-track the repository, overwriting the secondary nodes 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 데이터베이스 불일치로 인한 것일 수 있습니다. 불일치를 확인하려면:
-
Praefect 데이터베이스에 연결합니다.
-
다음 쿼리를 실행합니다:
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
이 오류의 원인을 조사하려면:
-
Rails 콘솔을 사용하여 프로젝트가 풀의 일부인지 확인합니다:
project = Project.find_by_id(<project id>) project.pool_repository -
풀 저장소 경로가 디스크에 존재하고
alternates파일 내용과 일치하는지 확인합니다. -
alternates파일의 경로가 프로젝트의objects디렉토리에서 도달 가능한지 확인합니다.
이러한 확인을 수행한 후 수집된 정보와 함께 GitLab 지원에 문의합니다.
실패한 저장소 스토리지 이동 후 프로젝트가 읽기 전용 상태로 고착#
Sidekiq 파드와 함께 수평 파드 자동 확장기(HPA)를 사용할 때 저장소 스토리지 이동이 파드 확장 중에 자동으로 실패할 수 있습니다. 이 문제로 인해 저장소 스토리지 이동이 실패한 경우 실패한 프로젝트가 읽기 전용 상태로 고착될 수 있습니다.
영향받은 저장소를 복구하려면:
- 영향받은 프로젝트를 읽기-쓰기 상태로 재설정합니다.
- Sidekiq 파드에 대한 HPA를 비활성화합니다.
- 개별 프로젝트에 대해 REST API를 사용하여 스토리지 이동을 다시 실행합니다.
- 마이그레이션이 완료된 후 HPA 구성을 복원합니다.
