Geo 동기화 문제 해결

Tier: Premium, Ultimate Offering: Self-Managed

모든 업로드 재확인(또는 확인된 SSF(스스로 서비스 프레임워크) 데이터 유형)

  1. 기본 Geo 사이트의 GitLab Rails 노드에 SSH로 로그인합니다.
  2. Rails 콘솔을 엽니다.
  3. 모든 업로드를 “검증 대기”로 표시합니다:
caution
데이터를 변경하는 명령은 올바르게 실행되지 않거나 적절한 조건에서 실행되지 않으면 손상을 일으킬 수 있습니다. 항상 테스트 환경에서 명령을 실행하고 복원할 수 있는 인스턴스를 준비하세요.
   Upload.verification_state_table_class.each_batch do |relation|
     relation.update_all(verification_state: 0)
   end
  1. 이로써 기본 사이트에서 모든 업로드의 체크섬을 시작합니다.
  2. 기본 사이트가 레코드의 체크섬을 성공적으로 확인하면, 모든 보조 사이트도 체크섬을 다시 계산하고 해당 값을 비교합니다.

이미 구현된 Geo Self-Service Framework에 의해 처리되는 다른 모델에서도 유사한 작업을 수행할 수 있습니다:

  • LfsObject
  • MergeRequestDiff
  • Packages::PackageFile
  • Terraform::StateVersion
  • SnippetRepository
  • Ci::PipelineArtifact
  • PagesDeployment
  • Upload
  • Ci::JobArtifact
  • Ci::SecureFile
note
GroupWikiRepository는 이전 디렉터리에 없으므로 검증이 구현되지 않았습니다. 관리자 영역 UI에서 이 기능을 구현하는 문제가 있습니다.

메시지: 동기화 실패 - 리포지터리 동기화 중 오류

caution
이 문제에 영향을 받는 큰 리포지터리의 경우, 재동기화에 시간이 오래 걸릴 수 있으며 Geo 사이트, 리포지터리 및 네트워크 시스템에 중대한 부하를 일으킬 수 있습니다.

리포지터리 동기화시 일관성 검사 오류를 나타내는 다음 오류 메시지가 보입니다:

동기화 실패 - 리포지터리 동기화 중 오류 [..] fatal: fsck error in packed object

이 오류는 여러 문제를 유발할 수 있습니다. 예를 들어, 이메일 주소와 관련된 문제:

리포지터리 동기화 오류: 13:fetch remote: "error: object <SHA>: badEmail: invalid author/committer line - bad email
   fatal: fsck error in packed object
   fatal: fetch-pack: invalid index-pack output

이 오류를 유발할 수 있는 다른 문제는 object <SHA>: hasDotgit: contains '.git'입니다. 특정 오류를 확인하십시오. 모든 리포지터리에서 하나 이상의 문제가 발생할 수 있습니다.

리포지터리 체크 문제로 인해 두 번째 동기화 오류가 발생할 수도 있습니다:

리포지터리 동기화 오류: 13:Received RST_STREAM with error code 2.

이러한 오류는 모든 실패한 리포지터리를 즉시 동기화하여 확인할 수 있습니다.

일관성 오류를 일으키는 잘못된 객체를 제거하려면 보통 리포지터리 히스토리를 다시 작성해야 합니다. 이것은 일반적으로 선택할 수 없는 옵션입니다.

이러한 일관성 검사를 무시하려면 보조 Geo 사이트에서 Gitaly를 다음과 같이 다시 구성하세요.

Gitaly 문서에 자세한 내용이 있습니다. Git의 다른 체크 실패 및 GitLab의 이전 버전에 대해 더 많은 정보를 얻을 수 있습니다.

gitaly['configuration'] = {
  git: {
    config: [
      { key: "fsck.duplicateEntries", value: "ignore" },
      { key: "fsck.badFilemode", value: "ignore" },
      { key: "fsck.missingEmail", value: "ignore" },
      { key: "fsck.badEmail", value: "ignore" },
      { key: "fsck.hasDotgit", value: "ignore" },
      { key: "fetch.fsck.duplicateEntries", value: "ignore" },
      { key: "fetch.fsck.badFilemode", value: "ignore" },
      { key: "fetch.fsck.missingEmail", value: "ignore" },
      { key: "fetch.fsck.badEmail", value: "ignore" },
      { key: "fetch.fsck.hasDotgit", value: "ignore" },
      { key: "receive.fsck.duplicateEntries", value: "ignore" },
      { key: "receive.fsck.badFilemode", value: "ignore" },
      { key: "receive.fsck.missingEmail", value: "ignore" },
      { key: "receive.fsck.badEmail", value: "ignore" },
      { key: "receive.fsck.hasDotgit", value: "ignore" },
    ],
  },
}

GitLab 16.1 이후로는 이 문제들 중 일부를 해결할 수 있는 개선 사항이 포함되어 있습니다.

Gitaly issue 5625는 출처 리포지터리에 문제가 있는 커밋이 있더라도 Geo가 리포지터리를 복제하도록 하는 것을 제안합니다.

관련 오류 git 리포지터리가 아닌 것으로 보입니다

또한 다음 로그 메시지와 함께 동기화 실패 - 리포지터리 동기화 중 오류 메시지를 얻을 수 있습니다. 이 오류는 예상된 Geo 원격이 리포지터리의 .git/config 파일에 없음을 나타냅니다.

{
  "created": "@1603481145.084348757",
  "description": "Error received from peer unix:/var/opt/gitlab/gitaly/gitaly.socket",
  
  "grpc_message": "exit status 128",
  "grpc_status": 13
}
{  
  "grpc.request.fullMethod": "/gitaly.RemoteService/FindRemoteRootRef",
  "grpc.request.glProjectPath": "<namespace>/<project>",
  
  "level": "error",
  "msg": "fatal: 'geo' does not appear to be a git repository
          fatal: Could not read from remote repository. …",
}

이를 해결하려면:

  1. 보조 Geo 사이트의 웹 인터페이스에 로그인합니다.

  2. .git 폴더를 백업합니다.

  3. 선택 사항. 몇 가지 ID를 검사하여 알려진 Geo 복제 실패가 있는 프로젝트와 일치하는지 확인합니다. fatal: 'geo'grep 용어로 사용하고 다음 API 호출을 사용하세요.

    curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<first_failed_geo_sync_ID>"
    
  4. Rails 콘솔에 들어가 다음을 실행합니다:

    failed_geo_syncs = Geo::ProjectRegistry.failed.pluck(:id)
    failed_geo_syncs.each do |fgs|
      puts Geo::ProjectRegistry.failed.find(fgs).project_id
    end
    
  5. 각 프로젝트의 Geo 관련 속성을 재설정하고 새로운 동기화를 실행하기 위해 다음 명령을 실행합니다:

    failed_geo_syncs.each do |fgs|
      registry = Geo::ProjectRegistry.failed.find(fgs)
      registry.update(resync_repository: true, force_to_redownload_repository: false, repository_retry_count: 0)
      Geo::RepositorySyncService.new(registry.project).execute
    end
    

백필 중 실패

백필 중에 실패가 다시 백필 대기열의 끝으로 예약되므로, 이러한 실패는 백필이 완료된 후에만 해소됩니다.

메시지: curl 18 전송이 아직 남은 데이터를 처리하는 동안 종료됨 및 fetch-pack: 사이드밴드 패킷을 읽는 동안 예기치 않은 연결 해제

불안정한 네트워크 환경은 피처 브랜치에서 대상 브랜치로 변경 사항을 통합하는 제안을 시도할 때 Gitaly가 실패하는 원인이 될 수 있습니다. 이는 리포지터리가 사이트 간에 처음부터 복제되어야 할 때 더 자주 발생할 가능성이 있습니다.

Geo는 여러 차례 다시 시도하지만 네트워크 지연으로 전송이 일관적으로 중단된 경우, rsync와 같은 대체 방법을 사용하여 git을 우회하고 실패한 리포지터리를 복제할 수 있습니다.

각 실패한 리포지터리를 개별적으로 전송하고 각 전송 후 일관성을 확인하는 것을 권장합니다. 단일 대상 rsync 지침을 따라 기본 사이트에서 각 영향을 받는 리포지터리를 보조 사이트로 전송하세요.

프로젝트 또는 프로젝트 위키 리포지터리

리포지터리 검증 실패 찾기

더 많은 정보를 수집하려면 보조 Geo 사이트에서 Rails 콘솔 세션을 시작하세요.

caution
데이터를 변경하는 명령은 올바르게 실행되지 않거나 적절한 조건에서 실행되지 않으면 손상을 일으킬 수 있습니다. 항상 먼저 테스트 환경에서 명령을 실행하고 복원할 수 있는 백업 인스턴스가 준비되어 있는지 확인하세요.

검증 실패 리포지터리 수 얻기

Geo::ProjectRegistry.verification_failed('repository').count

검증 실패 리포지터리 찾기

Geo::ProjectRegistry.verification_failed('repository')

동기화에 실패한 리포지터리 찾기

Geo::ProjectRegistry.sync_failed('repository')

프로젝트 및 프로젝트 위키 리포지터리 다시 동기화

다음 변경 사항을 수행하려면 보조 Geo 사이트에서 Rails 콘솔 세션을 시작하세요.

caution
데이터를 변경하는 명령은 올바르게 실행되지 않거나 적절한 조건에서 실행되지 않으면 손상을 일으킬 수 있습니다. 항상 먼저 테스트 환경에서 명령을 실행하고 복원할 수 있는 백업 인스턴스가 준비되어 있는지 확인하세요.

모든 리포지터리를 다시 동기화 대기열에 추가

이 작업을 실행하면 동기화는 Sidekiq에서 백그라운드에서 처리됩니다.

Geo::ProjectRegistry.update_all(resync_repository: true, resync_wiki: true)

지금 개별 리포지터리 동기화 실행

project = Project.find_by_full_path('<group/project>')

Geo::RepositorySyncService.new(project).execute

현재 실패한 리포지터리 모두 동기화 실행

다음 스크립트:

  • 현재 실패한 리포지터리를 모두 반복합니다.
  • 프로젝트 세부 정보와 마지막 실패 이유를 표시합니다.
  • 리포지터리를 다시 동기화하려고 시도합니다.
  • 실패가 발생하면 실패 이유를 다시 보고합니다.
  • 완료하는 데 시간이 걸릴 수 있습니다. 각 리포지터리 확인이 완료되어야 결과를 다시 보고합니다. 세션이 시간 초과되면 screen 세션을 시작하거나 Rails runnernohup을 사용하여 프로세스를 계속 실행할 수 있도록 조치하세요.
Geo::ProjectRegistry.sync_failed('repository').find_each do |p|
   begin
     project = p.project
     puts "#{project.full_path} | id: #{p.project_id} | last error: '#{p.last_repository_sync_failure}'"
     Geo::RepositorySyncService.new(project).execute
   rescue => e
     puts "ID: #{p.project_id} failed: '#{e}'", e.backtrace.join("\n")
   end
end ; nil

Geo 보조 사이트에서 리포지터리 확인 실패 찾기

모든 프로젝트에 대해 활성화된 경우, Geo 보조 사이트에서도 리포지터리 확인이 수행됩니다. 메타데이터는 Geo 추적 데이터베이스에 저장됩니다.

Geo 보조 사이트에서의 리포지터리 확인 실패는 반드시 복제 문제를 나타내지는 않습니다. 이러한 실패를 해결하기 위한 일반적인 방법은 다음과 같습니다.

  1. 아래에서 언급된 영향을 받는 리포지터리와 기록된 오류를 찾으세요.
  2. 특정 git fsck 오류를 진단해 보세요. 가능한 오류 범위가 넓기 때문에 검색 엔진에 입력해 보세요.
  3. 영향을 받는 리포지터리의 일반 기능을 테스트해 보세요. 보조에서 풀을 받고 파일을 보세요.
  4. 기본 사이트의 리포지터리 사본이 동일한 git fsck 오류를 가지고 있는지 확인하세요. 장애 조치를 계획 중이라면 보조 사이트에 기본 사이트와 동일한 정보가 있는지 우선 고려하세요. 기본 사이트의 백업이 있는지 확인하고 계획된 장애 조치 지침을 따르세요.
  5. 기본으로 푸시하여 변경 사항이 보조 사이트에 복제되는지 확인하세요.
  6. 복제가 자동으로 작동하지 않는 경우 리포지터리를 매뉴얼으로 동기화해 보세요.

Rails 콘솔 세션을 시작하여 다음 기본 문제 해결 단계를 수행하세요.

caution
데이터를 변경하는 명령은 올바르게 실행되지 않거나 적절한 조건에서 실행되지 않으면 손상을 일으킬 수 있습니다. 항상 먼저 테스트 환경에서 명령을 실행하고 복원할 수 있는 백업 인스턴스가 준비되어 있는지 확인하세요.

리포지터리 확인 실패한 리포지터리 수 얻기

Geo::ProjectRegistry.where(last_repository_check_failed: true).count

리포지터리 확인 실패한 리포지터리 찾기

Geo::ProjectRegistry.where(last_repository_check_failed: true)

리포지터리 확인 실패한 리포지터리 다시 확인

이 작업을 실행하면 각 실패한 리포지터리에 대해 fsck가 실행됩니다.

보조 사이트에서 fsck Rake 명령을 사용하여 왜 리포지터리 확인이 실패한지 이해할 수 있습니다.

Geo::ProjectRegistry.where(last_repository_check_failed: true).each do |pr|
    RepositoryCheck::SingleRepositoryWorker.new.perform(pr.project_id)
end