무결성 검사 Rake 작업


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

GitLab은 다양한 구성 요소의 무결성을 확인하는 레이크 작업을 제공합니다. 또한 GitLab 구성 레이크 작업 확인도 참조하세요.

저장소 무결성

Git은 매우 탄탄하고 데이터 무결성 문제를 방지하려고 노력하지만 때로는 문제가 발생합니다. 아래의 Rake 작업은 문제가 있는 저장소를 진단하여 수정할 수 있도록 돕기 위한 것입니다.

이러한 Rake 작업은 Git 저장소의 무결성을 결정하기 위해 세 가지 다른 방법을 사용합니다.

  1. Git 저장소 파일 시스템 확인 (git fsck). 이 단계는 저장소의 객체의 연결성과 유효성을 확인합니다.
  2. 저장소 디렉토리에 config.lock 확인
  3. refs/heads에 있는 브랜치/참조 잠금 파일 확인

config.lock 또는 참조 잠금이 존재한다고 해서 반드시 문제가 있는 것은 아닙니다. 잠금 파일은 Git 및 GitLab이 저장소에 대한 작업을 수행하는 동안 정기적으로 생성되고 삭제됩니다. 이들은 데이터 무결성 문제를 방지하는 데 사용됩니다. 그러나 Git 작업이 중단되면 이러한 잠금이 올바르게 정리되지 않을 수 있습니다.

다음 증상은 저장소 무결성에 문제가 있다는 것을 나타낼 수 있습니다. 사용자가 이러한 증상을 겪으면 아래에서 설명하는 Rake 작업을 사용하여 정확히 어떤 저장소에서 문제가 발생하고 있는지 확인할 수 있습니다.

  • 코드를 푸시하려고 할 때 오류가 발생함 - remote: error: cannot lock ref
  • GitLab 대시보드를 볼 때 또는 특정 프로젝트에 액세스할 때 500 오류가 발생함.

프로젝트 코드 저장소 확인

이 작업은 프로젝트 코드 저장소를 순환하며 이전에 설명한 무결성 확인을 실행합니다. 프로젝트가 풀 저장소를 사용하는 경우에도 확인됩니다. 다른 유형의 Git 저장소는 확인되지 않습니다.

  • Linux 패키지 설치:

    sudo gitlab-rake gitlab:git:fsck
    
  • 사용자 컴파일된 설치:

    sudo -u git -H bundle exec rake gitlab:git:fsck RAILS_ENV=production
    

저장소 refs의 체크섬

한 Git 저장소는 다른 Git 저장소와 비교할 수 있습니다. 각 저장소의 모든 refs를 체크섬하여 두 저장소가 동일한 refs를 가지고 있고 둘 다 무결성 검사를 통과하면 두 저장소가 동일함을 확신할 수 있습니다.

예를 들어, 이는 저장소의 백업을 원본 저장소와 비교하는 데 사용될 수 있습니다.

모든 GitLab 저장소 확인

이 작업은 GitLab 서버의 모든 저장소를 순환하고 형식은 <프로젝트 ID>,<체크섬>으로 체크섬을 출력합니다.

  • 저장소가 존재하지 않는 경우, 프로젝트 ID는 공백 체크섬입니다.
  • 저장소가 존재하지만 비어 있는 경우, 출력 체크섬은 0000000000000000000000000000000000000000입니다.
  • 존재하지 않는 프로젝트는 건너뜁니다.

  • Linux 패키지 설치:

    sudo gitlab-rake gitlab:git:checksum_projects
    
  • 사용자 컴파일된 설치:

    sudo -u git -H bundle exec rake gitlab:git:checksum_projects RAILS_ENV=production
    

예를 들어:

  • ID가 2인 프로젝트가 존재하지 않으면 건너뜁니다.
  • ID가 4인 프로젝트에 저장소가 없으면, 그 체크섬은 공란입니다.
  • ID가 5인 프로젝트가 비어 있는 저장소를 가지고 있으면, 체크섬은 0000000000000000000000000000000000000000입니다.

그러면 출력은 다음과 같이 보일 것입니다:

1,cfa3f06ba235c13df0bb28e079bcea62c5848af2
3,3f3fb58a8106230e3a6c6b48adc2712fb3b6ef87
4,
5,0000000000000000000000000000000000000000
6,6c6b48adc2712fb3b6ef87cfa3f06ba235c13df0

특정 GitLab 저장소 확인

선택적으로, 환경 변수 CHECKSUM_PROJECT_IDS를 설정하여 쉼표로 구분된 정수 목록으로 특정 프로젝트 ID의 체크섬을 생성할 수 있습니다.

sudo CHECKSUM_PROJECT_IDS="1,3" gitlab-rake gitlab:git:checksum_projects

업로드된 파일 무결성

사용자가 GitLab 설치에 다양한 유형의 파일을 업로드할 수 있습니다. 이 무결성 검사는 누락된 파일을 감지할 수 있습니다. 또한 로컬로 저장된 파일의 경우 업로드시 체크섬이 생성되어 데이터베이스에 저장되며, 이러한 검사는 현재 파일과의 일치 여부를 확인합니다.

다음 유형의 파일에 대한 무결성 검사가 지원됩니다:

  • CI 아티팩트
  • LFS 오브젝트
  • 프로젝트 수준 Secure 파일 (GitLab 16.1.0에서 도입됨)
  • 사용자 업로드

  • Linux 패키지 설치:

    sudo gitlab-rake gitlab:artifacts:check
    sudo gitlab-rake gitlab:ci_secure_files:check
    sudo gitlab-rake gitlab:lfs:check
    sudo gitlab-rake gitlab:uploads:check
    
  • 사용자 컴파일된 설치:

    sudo -u git -H bundle exec rake gitlab:artifacts:check RAILS_ENV=production
    sudo -u git -H bundle exec rake gitlab:ci_secure_files:check RAILS_ENV=production
    sudo -u git -H bundle exec rake gitlab:lfs:check RAILS_ENV=production
    sudo -u git -H bundle exec rake gitlab:uploads:check RAILS_ENV=production
    

이러한 작업은 일부 환경 변수도 허용하며 특정 값들을 재정의할 수 있습니다:

변수 타입 설명
BATCH 정수 배치의 크기를 지정합니다. 기본값은 200입니다.
ID_FROM 정수 시작하는 ID를 지정합니다. 값은 포함됩니다.
ID_TO 정수 끝날 ID 값을 지정합니다. 값은 포함됩니다.
VERBOSE 부울 실패 사항을 요약하는 대신 개별적으로 나열하도록 합니다.
sudo gitlab-rake gitlab:artifacts:check BATCH=100 ID_FROM=50 ID_TO=250
sudo gitlab-rake gitlab:ci_secure_files:check BATCH=100 ID_FROM=50 ID_TO=250
sudo gitlab-rake gitlab:lfs:check BATCH=100 ID_FROM=50 ID_TO=250
sudo gitlab-rake gitlab:uploads:check BATCH=100 ID_FROM=50 ID_TO=250

예시 출력:

$ sudo gitlab-rake gitlab:uploads:check
업로드의 무결성을 확인 중
- 1..1350: 실패 사항: 0
- 1351..2743: 실패 사항: 0
- 2745..4349: 실패 사항: 2
- 4357..5762: 실패 사항: 1
- 5764..7140: 실패 사항: 2
- 7142..8651: 실패 사항: 0
- 8653..10134: 실패 사항: 0
- 10135..11773: 실패 사항: 0
- 11777..13315: 실패 사항: 0
완료!

예시 상세 출력:

$ sudo gitlab-rake gitlab:uploads:check VERBOSE=1
업로드의 무결성을 확인 중
- 1..1350: 실패 사항: 0
- 1351..2743: 실패 사항: 0
- 2745..4349: 실패 사항: 2
  - Upload: 3573: #<Errno::ENOENT: No such file or directory @ rb_sysopen - /opt/gitlab/embedded/service/gitlab-rails/public/uploads/user-foo/project-bar/7a77cc52947bfe188adeff42f890bb77/image.png>
  - Upload: 3580: #<Errno::ENOENT: No such file or directory @ rb_sysopen - /opt/gitlab/embedded/service/gitlab-rails/public/uploads/user-foo/project-bar/2840ba1ba3b2ecfa3478a7b161375f8a/pug.png>
- 4357..5762: 실패 사항: 1
  - Upload: 4636: #<Google::Apis::ServerError: Server error>
- 5764..7140: 실패 사항: 2
  - Upload: 5812: #<NoMethodError: undefined method `hashed_storage?' for nil:NilClass>
  - Upload: 5837: #<NoMethodError: undefined method `hashed_storage?' for nil:NilClass>
- 7142..8651: 실패 사항: 0
- 8653..10134: 실패 사항: 0
- 10135..11773: 실패 사항: 0
- 11777..13315: 실패 사항: 0
완료!

LDAP 체크

LDAP 체크 Rake 작업은 바인드 DN 및 비밀번호 자격 증명(구성된 경우)을 테스트하고 LDAP 사용자의 샘플을 나열합니다. 이 작업은 또한 gitlab:check 작업의 일부로 실행되지만 독립적으로 실행할 수도 있습니다. 자세한 내용은 LDAP Rake Tasks - LDAP Check를 참조하십시오.

현재 비밀로 값이 암호화된 데이터베이스 값 확인

이 작업은 데이터베이스의 모든 가능한 암호화된 값을 확인하여 현재 secrets 파일(gitlab-secrets.json)을 사용하여 복호화할 수 있는지 확인합니다.

자동 해결책은 아직 구현되지 않았습니다. 복호화할 수 없는 값이 있는 경우 복구하는 단계를 따를 수 있으며, 자세한 내용은 비밀 파일이 분실된 경우를 참조하십시오.

데이터베이스의 크기에 따라 이 작업에는 매우 오랜 시간이 걸릴 수 있습니다. 모든 테이블의 모든 행을 확인하기 때문입니다.

  • 리눅스 패키지 설치:

    sudo gitlab-rake gitlab:doctor:secrets
    
  • 자체 컴파일된 설치:

    bundle exec rake gitlab:doctor:secrets RAILS_ENV=production
    

예시 출력

I, [2020-06-11T17:17:54.951815 #27148]  INFO -- : 데이터베이스의 암호화된 값 확인 중
I, [2020-06-11T17:18:12.677708 #27148]  INFO -- : - ApplicationSetting 실패: 0
I, [2020-06-11T17:18:12.823692 #27148]  INFO -- : - User 실패: 0
[...] 가능한 기타 모델이 암호화된 데이터를 포함하고 있을 수 있음
I, [2020-06-11T17:18:14.938335 #27148]  INFO -- : - Group 실패: 1
I, [2020-06-11T17:18:15.559162 #27148]  INFO -- : - Operations::FeatureFlagsClient 실패: 0
I, [2020-06-11T17:18:15.575533 #27148]  INFO -- : - ScimOauthAccessToken 실패: 0
I, [2020-06-11T17:18:15.575678 #27148]  INFO -- : 총: 1개의 행이 영향을 받았음
I, [2020-06-11T17:18:15.575711 #27148]  INFO -- : 완료!

자세한 모드

변경되거나 암호 해독할 수 없는 행 및 열에 대한 자세한 정보를 얻으려면 VERBOSE 환경 변수를 전달할 수 있습니다:

  • 리눅스 패키지 설치:

    sudo gitlab-rake gitlab:doctor:secrets VERBOSE=1
    
  • 자체 컴파일된 설치:

    bundle exec rake gitlab:doctor:secrets RAILS_ENV=production VERBOSE=1
    

자세한 예시 출력

I, [2020-06-11T17:17:54.951815 #27148]  INFO -- : 데이터베이스의 암호화된 값 확인 중
I, [2020-06-11T17:18:12.677708 #27148]  INFO -- : - ApplicationSetting 실패: 0
I, [2020-06-11T17:18:12.823692 #27148]  INFO -- : - User 실패: 0
[...] 가능한 기타 모델이 암호화된 데이터를 포함하고 있을 수 있음
D, [2020-06-11T17:19:53.224344 #27351] DEBUG -- : > Group[10].runners_token에 대해 오류가 발생했습니다.: Validation failed: Route can't be blank
I, [2020-06-11T17:19:53.225178 #27351]  INFO -- : - Group 실패: 1
D, [2020-06-11T17:19:53.225267 #27351] DEBUG -- :   - Group[10]: runners_token
I, [2020-06-11T17:18:15.559162 #27148]  INFO -- : - Operations::FeatureFlagsClient 실패: 0
I, [2020-06-11T17:18:15.575533 #27148]  INFO -- : - ScimOauthAccessToken 실패: 0
I, [2020-06-11T17:18:15.575678 #27148]  INFO -- : 총: 1개의 행이 영향을 받았음
I, [2020-06-11T17:18:15.575711 #27148]  INFO -- : 완료!

암호화된 토큰이 복구되지 못할 때 암호화된 토큰 재설정

경고: 이 작업은 위험할 수 있으며 데이터 손실을 야기할 수 있습니다. 매우 신중히 진행하시기 바랍니다. 이 작업을 수행하기 전에 GitLab 내부에 대한 지식을 갖고 있어야 합니다.

어떤 경우에는 암호화된 토큰을 더 이상 회복할 수 없고 문제를 일으킬 수 있습니다. 가장 흔히, 대규모의 인스턴스에서는 그룹 및 프로젝트의 러너 등록 토큰이 손상될 수 있습니다.

손상된 토큰을 재설정하려면:

  1. 손상된 암호화된 토큰을 가진 데이터베이스 모델을 식별하십시오. 예를 들어 GroupProject일 수 있습니다.
  2. 손상된 토큰을 식별하십시오. 예를 들어, runners_token입니다.
  3. 손상된 토큰을 재설정하려면 VERBOSE=true MODEL_NAMES=Model1,Model2 TOKEN_NAMES=broken_token1,broken_token2와 함께 gitlab:doctor:reset_encrypted_tokens을 실행하십시오. 예를 들어:

    VERBOSE=true MODEL_NAMES=Project,Group TOKEN_NAMES=runners_token bundle exec rake gitlab:doctor:reset_encrypted_tokens
    

    이 작업이 시도하려는 모든 작업을 확인할 수 있습니다:

    I, [2023-09-26T16:20:23.230942 #88920]  INFO -- : Project, Group에서 실행 중인 runners_token 재설정
    I, [2023-09-26T16:20:23.230975 #88920]  INFO -- : DRY RUN 모드에서 실행 중이므로 레코드가 실제로 업데이트되지는 않습니다
    D, [2023-09-26T16:20:30.151585 #88920] DEBUG -- : > Project[1].runners_token 수정
    I, [2023-09-26T16:20:30.151617 #88920]  INFO -- : 1/9 프로젝트 확인됨
    D, [2023-09-26T16:20:30.151873 #88920] DEBUG -- : > Project[3].runners_token 수정
    D, [2023-09-26T16:20:30.152975 #88920] DEBUG -- : > Project[10].runners_token 수정
    I, [2023-09-26T16:20:30.152992 #88920]  INFO -- : 11/29 프로젝트 확인됨
    I, [2023-09-26T16:20:30.153230 #88920]  INFO -- : 21/29 프로젝트 확인됨
    I, [2023-09-26T16:20:30.153882 #88920]  INFO -- : 29/29 프로젝트 확인됨
    D, [2023-09-26T16:20:30.195929 #88920] DEBUG -- : > Group[22].runners_token 수정
    I, [2023-09-26T16:20:30.196125 #88920]  INFO -- : 1/19 그룹 확인됨
    D, [2023-09-26T16:20:30.196192 #88920] DEBUG -- : > Group[25].runners_token 수정
    D, [2023-09-26T16:20:30.197557 #88920] DEBUG -- : > Group[82].runners_token 수정
    I, [2023-09-26T16:20:30.197581 #88920]  INFO -- : 11/19 그룹 확인됨
    I, [2023-09-26T16:20:30.198455 #88920]  INFO -- : 19/19 그룹 확인됨
    I, [2023-09-26T16:20:30.198462 #88920]  INFO -- : 완료!
  4. 이 작업이 올바른 토큰을 재설정하는지 확신하면, dry-run 모드를 비활성화하고 작업을 다시 실행하십시오:

    DRY_RUN=false VERBOSE=true MODEL_NAMES=Project,Group TOKEN_NAMES=runners_token bundle exec rake gitlab:doctor:reset_encrypted_tokens
    

문제 해결

다음은 상기 문서화된 Rake 작업을 사용하다가 발견할 수 있는 문제에 대한 해결책입니다.

매달린 객체

gitlab-rake gitlab:git:fsck 작업은 다음과 같은 매달린 객체를 찾을 수 있습니다.

dangling blob a12...
dangling commit b34...
dangling tag c56...
dangling tree d78...

이러한 객체를 삭제하려면 housekeeping을 실행해 보세요.

문제가 지속되면 Rails 콘솔을 통해 가비지 컬렉션을 트리거 해보세요:

p = Project.find_by_path("project-name")
Repositories::HousekeepingService.new(p, :gc).execute

매달린 객체가 기본 2주의 유효 기간보다 젊은 경우이고 자동으로 만료될 때까지 기다리고 싶지 않다면 다음을 실행하세요:

Repositories::HousekeepingService.new(p, :prune).execute

누락된 원격 업로드에 대한 참조 삭제

gitlab-rake gitlab:uploads:check VERBOSE=1는 외부에서 삭제되었지만 여전히 GitLab 데이터베이스에 참조가 있는 원격 객체를 감지합니다.

오류 메시지가 포함된 예제 출력:

$ sudo gitlab-rake gitlab:uploads:check VERBOSE=1
Uploads의 무결성 확인 중
- 100..434: 오류 발생: 2
- Upload: 100: 원격 객체가 존재하지 않음
- Upload: 101: 원격 객체가 존재하지 않음
완료!

이러한 누락된 원격 업로드에 대한 참조를 삭제하려면 GitLab Rails 콘솔을 열고 다음을 실행하세요:

uploads_deleted=0
Upload.find_each do |upload|
  next if upload.retrieve_uploader.file.exists?
  uploads_deleted=uploads_deleted + 1
  p upload                            ### 삭제 전 확인
  # p upload.destroy!                 ### 실제 삭제를 위해 주석 해제
end
p "#{uploads_deleted}개의 원격 객체가 삭제되었습니다."

누락된 아티팩트에 대한 참조 삭제

gitlab-rake gitlab:artifacts:check VERBOSE=1는 GitLab 외부에서 삭제되거나 여전히 데이터베이스에 참조가 있는 아티팩트(또는 job.log 파일)를 감지합니다.

이러한 시나리오가 감지되면 Rake 작업은 오류 메시지를 표시합니다. 예:

작업 아티팩트 무결성 확인 중
- 1..15: 오류 발생: 2
  - 작업 아티팩트: 9: #<Errno::ENOENT: No such file or directory @ rb_sysopen - /var/opt/gitlab/gitlab-rails/shared/artifacts/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a/2022_06_30/8/9/job.log>
  - 작업 아티팩트: 15: 원격 객체가 존재하지 않음
완료!

이러한 누락된 로컬 또는 원격 아티팩트 (job.log 파일)에 대한 참조를 삭제하려면 다음을 실행하세요:

  1. GitLab Rails 콘솔을 엽니다.
  2. 다음 Ruby 코드를 실행하세요:

    artifacts_deleted = 0
    ::Ci::JobArtifact.find_each do |artifact|                      ### 아티팩트 반복
    #  아래 줄 주석 처리를 해제하여 `job.log` 파일의 참조만 처리하는 경우에 사용하세요
    #  next if artifact.file.filename != "job.log"
      next if artifact.file.file.exists?                           ### 파일 참조가 유효한 경우 건너뜁니다
      artifacts_deleted += 1
      puts "#{artifact.id}  #{artifact.file.path}이(가) 누락되었습니다."     ### 삭제 전 확인
    #  artifact.destroy!                                           ### 실제 삭제를 위해 주석 해제
    end
    puts "식별/삭제된 유효하지 않은 참조 수: #{artifacts_deleted}"
    

누락된 LFS 객체에 대한 참조 삭제

gitlab-rake gitlab:lfs:check VERBOSE=1가 데이터베이스에 존재하지만 디스크에 없는 LFS 객체를 감지하면, 다음 LFS 문서의 절차를 따라 데이터베이스 항목을 제거하세요.

매달린 객체 저장소 참조 업데이트

객체 저장소에서 로컬 저장소로 마이그레이션를 수행하고 파일이 누락된 경우, 매달린 데이터베이스 참조가 남아 있습니다.

이는 다음과 같은 오류가 포함된 마이그레이션 로그에서 확인할 수 있습니다:

W, [2022-11-28T13:14:09.283833 #10025]  WARN -- : Failed to transfer Ci::JobArtifact ID 11 with error: undefined method `body' for nil:NilClass
W, [2022-11-28T13:14:09.296911 #10025]  WARN -- : Failed to transfer Ci::JobArtifact ID 12 with error: undefined method `body' for nil:NilClass

목록에서 객체 저장소를 비활성화한 후 누락된 아티팩트에 대한 참조를 삭제를 시도하면 다음과 같은 오류가 발생합니다:

RuntimeError (Object Storage is not enabled for JobArtifactUploader)

이러한 참조를 로컬 저장소를 가리키도록 업데이트하려면 다음을 실행하세요:

  1. GitLab Rails 콘솔을 엽니다.
  2. 다음 Ruby 코드를 실행하세요:

    artifacts_updated = 0
    ::Ci::JobArtifact.find_each do |artifact|                    ### 아티팩트 반복
      next if artifact.file_store != 2                           ### 파일 저장소가 이미 로컬 저장소를 가리키고 있는 경우 건너뜁니다
      artifacts_updated += 1
      # artifact.update(file_store: 1)                           ### 실제 업데이트를 위해 주석 해제
    end
    puts "업데이트된 파일 저장소 수: #{artifacts_updated}"
    

이제 누락된 아티팩트에 대한 참조를 삭제하는 스크립트가 올바르게 작동하여 데이터베이스를 정리합니다.

누락된 보안 파일에 대한 참조 삭제

VERBOSE=1 gitlab-rake gitlab:ci_secure_files:check는 누락된 로컬 또는 원격 보안 파일에 대한 참조를 감지합니다.

이러한 시나리오가 감지되면 Rake 작업은 오류 메시지를 표시합니다. 예:

CI 보안 파일의 무결성 확인 중
- 1..15: 오류 발생: 2
  - 작업 보안 파일: 9: #<Errno::ENOENT: No such file or directory @ rb_sysopen - /var/opt/gitlab/gitlab-rails/shared/ci_secure_files/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a/2022_06_30/8/9/distribution.cer>
  - 작업 보안 파일: 15: 원격 객체가 존재하지 않음
완료!

이러한 누락된 로컬 또는 원격 보안 파일에 대한 참조를 삭제하려면 다음을 실행하세요:

  1. GitLab Rails 콘솔을 엽니다.
  2. 다음 Ruby 코드를 실행하세요:

    secure_files_deleted = 0
    ::Ci::SecureFile.find_each do |secure_file|                    ### 보안 파일 반복
      next if secure_file.file.file.exists?                        ### 파일 참조가 유효한 경우 건너뜁니다
      secure_files_deleted += 1
      puts "#{secure_file.id}  #{secure_file.file.path}이(가) 누락되었습니다."     ### 삭제 전 확인
    #  secure_file.destroy!                                           ### 실제 삭제를 위해 주석 해제
    end
    puts "식별/삭제된 유효하지 않은 참조 수: #{secure_files_deleted}"