리포지토리 미러링 문제 해결

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

미러링이 실패하면 프로젝트 유지자는 프로젝트 세부 정보 페이지에서 Pull 미러링 실패 1시간 전과 유사한 링크를 볼 수 있습니다. 이 링크를 선택하여 미러링 설정으로 바로 이동하여, GitLab이 미러링된 리포지토리에 대한 에러 뱃지를 표시합니다. 마우스 커서를 뱃지 위에 올려놓으면 에러 텍스트가 표시됩니다:

호버 시 표시되는 에러 메시지

Received RST_STREAM with error code 2 with GitHub

GitHub 리포지토리로 미러링하는 도중에 이 메시지를 받는 경우:

13:Received RST_STREAM with error code 2

다음 중 하나가 발생했을 수 있습니다:

  1. GitHub 설정에서 커밋에 사용된 이메일 주소를 노출하는 푸시를 차단하도록 설정되어 있을 수 있습니다. 이 문제를 해결하려면:
  2. 리포지토리가 GitHub의 100MB 파일 크기 제한을 초과했을 수 있습니다. 이 문제를 해결하려면, GitHub에서 구성된 파일 크기 제한을 확인하고, 큰 파일을 관리하는 데 Git Large File Storage를 사용하는 것을 고려합니다.

Deadline Exceeded

GitLab을 업그레이드하면 사용자 이름이 표시되는 방식에 변경이 있어 미러링 사용자 이름과 암호를 변경하여 %40 문자가 @로 대체되도록 해야 합니다.

Connection blocked: server only allows public key authentication

GitLab과 원격 리포지토리 간의 연결이 차단되었습니다. TCP 확인이 성공하더라도, GitLab에서 원격 서버로의 경로에 있는 네트워킹 구성 요소를 확인해야 합니다.

이 에러는 방화벽이 나가는 패킷에 대해 Deep SSH Inspection을 수행할 때 발생할 수 있습니다.

Could not read username: terminal prompts disabled

외부 리포지토리용 GitLab CI/CD를 사용하여 새 프로젝트를 만든 후 이 에러를 받는 경우:

  • Bitbucket Cloud의 경우:

    "2:fetch remote: "fatal: could not read Username for 'https://bitbucket.org':
    terminal prompts disabled\n": exit status 128."
    
  • Bitbucket Server (Self-managed)의 경우:

    "2:fetch remote: "fatal: could not read Username for 'https://lab.example.com':
    terminal prompts disabled\n": exit status 128.
    

미러링된 리포지토리의 URL에 리포지토리 소유자가 지정되어 있는지 확인합니다:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > 리포지토리를 선택합니다.
  3. 리포지토리 미러링을 확장합니다.
  4. 리포지토리 소유자가 지정되지 않은 경우, 다음 형식으로 URL을 다시 삭제하고 추가합니다. 여기서 OWNER, ACCOUNTNAME, PATH_TO_REPO, REPONAME을 각각의 값으로 변경합니다:

    • Bitbucket Cloud의 경우:

      https://OWNER@bitbucket.org/ACCOUNTNAME/REPONAME.git
      
    • Bitbucket Server(Self-managed)의 경우:

      https://OWNER@lab.example.com/PATH_TO_REPO/REPONAME.git
      

GitLab을 Cloud 또는 Self-managed Bitbucket 리포지토리에 미러링하는 경우, 리포지토리 소유자가 문자열에 필요합니다.

Pull mirror is missing LFS files

경우에 따라 pull 미러링이 LFS 파일을 전송하지 않을 수 있습니다. 이 문제는 다음 경우에 발생합니다:

  • SSH 리포지토리 URL을 사용하는 경우입니다. 대신 HTTPS 리포지토리 URL을 사용하면 문제를 해결할 수 있습니다. SSH URL에 대한 이 문제를 해결하기 위해 이슈가 존재합니다.
  • 개체 저장소를 사용하여 외부 리포지토리를 미러링하는 경우입니다. 이 문제에 대한 이슈가 존재합니다.

Pull 미러링이 파이프라인을 트리거하지 않음

여러 이유로 파이프라인이 실행되지 않을 수 있습니다:

  • 미러 업데이트를 위해 파이프라인을 트리거하는 것이 비활성화될 수 있습니다. 이 설정은 미러링을 초기 설정할 때만 활성화할 수 있습니다. 프로젝트를 확인한 후에 상태가 표시되지 않을 수 있습니다.

    외부 리포지토리용 CI/CD를 사용하여 미러링을 수동으로 다시 구성하면, 파이프라인을 트리거하는 것이 기본적으로 비활성화되므로 이것이 파이프라인 실행이 중지되는 이유일 수 있습니다.

  • rules 구성이 파이프라인에 작업을 추가하는 것을 방지할 수 있습니다.
  • 파이프라인이 pull 미러링을 설정한 계정을 사용하여 트리거됩니다. 계정이 더 이상 유효하지 않으면 파이프라인이 실행되지 않습니다.
  • 브랜치 보호가 미러링을 설정한 계정이 파이프라인을 실행하는 것을 방지할 수 있습니다.

The repository is being updated, but neither fails nor succeeds visibly

드문 경우에, Redis의 미러링 슬롯이 고갈될 수 있으며, 이는 메모리 부족(OoM)으로 인해 Sidekiq 워커가 종료되었을 수 있습니다. 이 경우, 미러링 작업이 빠르게 시작하고 완료되지만 실패하거나 성공하지 않습니다. 또한 명확한 로그가 남지 않습니다. 이 문제를 확인하려면:

  1. Rails 콘솔로 들어가 Redis의 미러링 용량을 확인합니다:

    current = Gitlab::Redis::SharedState.with { |redis| redis.scard('MIRROR_PULL_CAPACITY') }.to_i
    maximum = Gitlab::CurrentSettings.mirror_max_capacity
    available = maximum - current
    
  2. 미러링 용량이 0 또는 매우 낮은 경우 다음 명령을 사용하여 모든 막힌 작업을 처리할 수 있습니다:

    Gitlab::Redis::SharedState.with { |redis| redis.smembers('MIRROR_PULL_CAPACITY') }.each do |pid|
      Gitlab::Redis::SharedState.with { |redis| redis.srem('MIRROR_PULL_CAPACITY', pid) }
    end
    
  3. 명령을 실행한 후 백그라운드 작업 페이지에서 새로운 미러링 작업이 예약되는 것을 확인할 수 있어야 합니다. 특히 수동으로 트리거될 때 표시됩니다.

잘못된 URL

SSH를 통해 미러링 설정 중이며 이 오류를 받은 경우 URL이 올바른 형식인지 확인하세요.

Mirroring에는 호스트와 프로젝트 경로가 :로 구분된 SCP 스타일의 클론 URL 형식인 git@gitlab.com:gitlab-org/gitlab.git과 같은 형식을 지원하지 않습니다. ssh://git@gitlab.com/gitlab-org/gitlab.git와 같이 ssh:// 프로토콜을 포함한 표준 URL이 필요합니다.

호스트 키 확인 실패

이 오류는 대상 호스트의 공개 SSH 키가 변경된 경우에 반환됩니다. 대개 호스트 공개 SSH 키는 변경되지 않습니다. 호스트 키 확인이 실패하지만 여전히 유효하다고 의심되는 경우 키 정보를 새로 고칠 수 있습니다.

전제 조건:

  • 프로젝트에 적어도 Maintainer 역할이 있어야 합니다.

이 문제를 해결하려면:

  1. 호스트 키를 확인하세요.
  2. 왼쪽 사이드 바에서 검색 또는 이동을 선택하여 프로젝트를 찾으세요.
  3. 설정 > 저장소를 선택하세요.
  4. 저장소 미러링을 확장하세요.
  5. 키를 새로 고치려면 아래 중 하나를 선택하세요:

    • 서버로부터 호스트 키를 가져와 지문을 표시하려면 호스트 키 검색을 선택하세요.
    • 수동으로 호스트 키를 입력하려면 호스트 키 수동 입력을 선택하고 SSH 호스트 키 필드에 호스트 키를 입력하세요.
  • 저장소 미러링을 선택하세요.

미러 사용자 및 토큰을 단일 서비스 계정으로 이전

이는 GitLab Rails console에 액세스해야 합니다.

사용 사례: 여러 사용자가 자체 GitHub 자격 증명을 사용하여 레포지토리 미러링을 설정한 경우, 회사를 떠나는 경우 미러링이 중단됩니다. 이 스크립트를 사용하여 분산된 미러링 사용자와 토큰을 단일 서비스 계정으로 이동합니다:

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

svc_user = User.find_by(username: 'ourServiceUser')
token = 'githubAccessToken'

Project.where(mirror: true).each do |project|
  import_url = project.import_url

  # 원하는 URL은 https://token@project/path.git과 같습니다
  repo_url = if import_url.include?('@')
               # 경우 1: URL이 https://23423432@project/path.git과 비슷한 경우
               import_url.split('@').last
             elsif import_url.include?('//')
               # 경우 2: URL이 https://project/path.git과 비슷한 경우
               import_url.split('//').last
             end

  repo_url 없으면 건너뜁니다.

  final_url = "https://#{token}@#{repo_url}"

  project.mirror_user = svc_user
  project.import_url = final_url
  project.username_only_import_url = final_url
  project.save
end

The requested URL returned error: 301

http:// 또는 https:// 프로토콜을 사용하여 미러링할 때 레포지토리의 정확한 URL을 지정하는지 확인하세요: https://gitlab.example.com/group/project.git

HTTP 리디렉션이 따르지 않으며 .git을 생략하면 301 오류가 발생할 수 있습니다:

13:fetch remote: "fatal: unable to access 'https://gitlab.com/group/project': The requested URL returned error: 301\n": exit status 128.

GitLab 인스턴스에서 Geo 보조 노드로 미러 푸시 실패

HTTP 또는 HTTPS 프로토콜을 사용하여 GitLab 레포지토리의 미러링 푸시가 대상이 Geo 보조 노드인 경우, 푸시 요청을 Geo 기본 노드로 프록시하는 과정에서 실패하고 다음과 같은 오류가 표시됩니다:

13:get remote references: create git ls-remote: exit status 128, stderr: "fatal: unable to access 'https://gitlab.example.com/group/destination.git/': The requested URL returned error: 302".

이 오류는 Geo 통합 URL이 구성되었고 대상 호스트 이름이 보조 노드의 IP 주소로 해석되는 경우 발생합니다.

오류를 피하려면 다음 중 하나를 수행하세요:

  • 푸시 미러를 SSH 프로토콜을 사용하도록 구성합니다. 그러나 레포지토리에는 항상 HTTP 또는 HTTPS를 통해 전송되는 LFS 객체가 포함되어서는 안 됩니다.
  • 소스 인스턴스에서 모든 요청을 기본 Geo 노드로 리디렉션하기 위해 역방향 프록시를 사용합니다.
  • 대상에서 타깃 호스트 이름을 Geo 기본 노드의 IP 주소로 해석하도록 소스의 로컬 hosts 파일 항목을 추가합니다.
  • 타깃에서 풀 미러를 구성합니다.

풀 또는 푸시 미러 업데이트 실패: The project is not mirrored

GitLab Silent Mode가 활성화된 경우 풀 또는 푸시 미러가 업데이트에 실패합니다. 이런 경우 UI에서 미러링을 허용하는 옵션이 비활성화됩니다.

관리자는 GitLab Silent Mode가 비활성화되었는지 확인할 수 있습니다.

Silent Mode로 인해 미러링이 실패한 경우 다음과 같은 디버그 단계가 있습니다:

예를 들어 Silent Mode가 가져오는 경우 출력은 다음과 비슷할 것입니다:

"id": 1,
"update_status": "finished",
"url": "https://test.git"
"last_error": null,
"last_update_at": null,
"last_update_started_at": "2023-12-12T00:01:02.222Z",
"last_successful_update_at": null

초기 미러링 실패: Unable to pull mirror repo: Unable to get pack index

다음과 비슷한 오류를 받을 수 있습니다:

13:fetch remote: "error: Unable to open local file /var/opt/gitlab/git-data/repositories/+gitaly/tmp/quarantine-[OMITTED].idx.temp.temp\nerror: Unable to get pack index https://git.example.org/ebtables/objects/pack/pack-[OMITTED].idx\nerror: Unable to find fcde2b2edba56bf408601fb721fe9b5c338d10ee under https://git.example.org/ebtables
Cannot obtain needed object fcde2b2edba56bf408601fb721fe9b5c338d10ee
while processing commit 2c26b46b68ffc68ff99b453c1d30413413422d70.
error: fetch failed.\n": exit status 128.

이 문제는 Gitaly가 “덤” HTTP 프로토콜을 통해 레포지토리를 미러링하거나 가져오는 것을 지원하지 않기 때문에 발생합니다.

서버가 “스마트”인지 “덤”인지 확인하려면 cURL을 사용하여 git-upload-pack 서비스의 참조 검색을 시작하고 Git “스마트” 클라이언트를 흉내내거나 사용합니다:

$GIT_URL="https://git.example.org/project"
curl --silent --dump-header - "$GIT_URL/info/refs?service=git-upload-pack"\
  -o /dev/null | grep -Ei "$content-type:"
  • “스마트” 서버Content-Type 응답 헤더에서 application/x-git-upload-pack-advertisement를 보고합니다.
  • “덤” 서버는 Content-Type 응답 헤더에서 text/plain을 보고합니다.

자세한 내용은 참조 검색에 대한 Git 문서를 참조하세요.

이를 해결하려면 다음 중 하나를 수행하세요:

  • 소스 레포지토리를 “스마트” 서버로 마이그레이션합니다.
  • SSH 프로토콜을 사용하여 레포지토리를 미러링합니다(인증이 필요함).