무결성 검사 Rake 작업

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

GitLab은 다양한 구성 요소의 무결성을 확인하기 위한 Rake 작업을 제공합니다. 또한 GitLab 구성 무결성 Rake 작업을 확인하세요.

저장소 무결성

Git이 매우 견고하고 데이터 무결성 문제를 방지하려고 노력하지만, 때로는 문제가 발생할 수 있습니다. 다음 Rake 작업은 문제가 있는 저장소를 진단하여 수정할 수 있도록 GitLab 관리자를 돕기 위한 것입니다.

이러한 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 저장소는 다른 저장소와 체크섬으로 비교할 수 있습니다. 두 저장소가 동일한 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 artifacts (GitLab 10.7.0에서 도입됨)
  • LFS objects (GitLab 10.6.0에서 도입됨)
  • 프로젝트 수준 Secure Files (GitLab 16.1.0에서 도입됨)
  • 사용자 업로드 (GitLab 10.6.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 확인 레이크 작업은 바인드 DN 및 암호 자격 증명(구성된 경우)을 테스트하고 LDAP 사용자의 샘플을 나열합니다. 이 작업은 gitlab:check 작업의 일부로 실행되지만 독립적으로 실행할 수도 있습니다. 자세한 내용은 LDAP Rake Tasks - LDAP Check를 참조하세요.

현재 암호를 사용하여 데이터베이스 값이 복호화될 수 있는지 확인

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

자동 해결은 아직 구현되지 않았습니다. 만약 복호화할 수 없는 값이 있다면, 비밀 파일이 분실된 경우해야 할 조치에 대해 문서를 참조하세요.

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

  • Linux 패키지 설치:

    sudo gitlab-rake gitlab:doctor:secrets
    
  • 직접 컴파일한 설치:

    bundle exec rake gitlab:doctor:secrets RAILS_ENV=production
    

예제 출력

I, [2020-06-11T17:17:54.951815 #27148]  INFO -- : Checking encrypted values in the database
I, [2020-06-11T17:18:12.677708 #27148]  INFO -- : - ApplicationSetting failures: 0
I, [2020-06-11T17:18:12.823692 #27148]  INFO -- : - User failures: 0
[...] 다른 암호화된 데이터가 있는 모델
I, [2020-06-11T17:18:14.938335 #27148]  INFO -- : - Group failures: 1
I, [2020-06-11T17:18:15.559162 #27148]  INFO -- : - Operations::FeatureFlagsClient failures: 0
I, [2020-06-11T17:18:15.575533 #27148]  INFO -- : - ScimOauthAccessToken failures: 0
I, [2020-06-11T17:18:15.575678 #27148]  INFO -- : 총: 1개의 행이 영향을 받음
I, [2020-06-11T17:18:15.575711 #27148]  INFO -- : 완료!

자세한 모드

복호화할 수 없는 행과 열에 대한 더 자세한 정보를 얻으려면 VERBOSE 환경 변수를 전달할 수 있습니다.

  • Linux 패키지 설치:

    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 -- : Checking encrypted values in the database
I, [2020-06-11T17:18:12.677708 #27148]  INFO -- : - ApplicationSetting failures: 0
I, [2020-06-11T17:18:12.823692 #27148]  INFO -- : - User failures: 0
[...] 다른 암호화된 데이터가 있는 모델
D, [2020-06-11T17:19:53.224344 #27351] DEBUG -- : > Group[10].runners_token에 문제가 발생했습니다: Route can't be blank 유효성 실패
I, [2020-06-11T17:19:53.225178 #27351]  INFO -- : - Group failures: 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 failures: 0
I, [2020-06-11T17:18:15.575533 #27148]  INFO -- : - ScimOauthAccessToken failures: 0
I, [2020-06-11T17:18:15.575678 #27148]  INFO -- : 총: 1개의 행이 영향을 받음
I, [2020-06-11T17:18:15.575711 #27148]  INFO -- : 완료!

복구할 수 없는 암호화된 토큰을 재설정합니다

경고: 이 작업은 위험하며 데이터 손실을 야기할 수 있습니다. 극도의 주의를 기울여 진행하십시오. 이 작업을 수행하기 전에 GitLab 내부에 대해 알아야 합니다.

일부 경우에는 복구할 수 없게 된 암호화된 토큰이 문제를 일으킬 수 있습니다. 매우 대규모의 인스턴스에서는 종종 그룹 및 프로젝트용 러너 등록 토큰이 손상될 수 있습니다.

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

  1. 손상된 암호화된 토큰이 있는 데이터베이스 모델을 확인합니다. 예를 들어, 그룹프로젝트일 수 있습니다.
  2. 손상된 토큰을 확인합니다. 예를 들어 runners_token입니다.
  3. 손상된 토큰을 재설정하려면 gitlab:doctor:reset_encrypted_tokens 명령을 다음과 같이 사용합니다: VERBOSE=true MODEL_NAMES=Model1,Model2 TOKEN_NAMES=broken_token1,broken_token2. 예를 들어:

     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 -- : Resetting runners_token on Project, Group if they can not be read
     I, [2023-09-26T16:20:23.230975 #88920]  INFO -- : Executing in DRY RUN mode, no records will actually be updated
     D, [2023-09-26T16:20:30.151585 #88920] DEBUG -- : > Fix Project[1].runners_token
     I, [2023-09-26T16:20:30.151617 #88920]  INFO -- : Checked 1/9 Projects
     D, [2023-09-26T16:20:30.151873 #88920] DEBUG -- : > Fix Project[3].runners_token
     D, [2023-09-26T16:20:30.152975 #88920] DEBUG -- : > Fix Project[10].runners_token
     I, [2023-09-26T16:20:30.152992 #88920]  INFO -- : Checked 11/29 Projects
     I, [2023-09-26T16:20:30.153230 #88920]  INFO -- : Checked 21/29 Projects
     I, [2023-09-26T16:20:30.153882 #88920]  INFO -- : Checked 29 Projects
     D, [2023-09-26T16:20:30.195929 #88920] DEBUG -- : > Fix Group[22].runners_token
     I, [2023-09-26T16:20:30.196125 #88920]  INFO -- : Checked 1/19 Groups
     D, [2023-09-26T16:20:30.196192 #88920] DEBUG -- : > Fix Group[25].runners_token
     D, [2023-09-26T16:20:30.197557 #88920] DEBUG -- : > Fix Group[82].runners_token
     I, [2023-09-26T16:20:30.197581 #88920]  INFO -- : Checked 11/19 Groups
     I, [2023-09-26T16:20:30.198455 #88920]  INFO -- : Checked 19 Groups
     I, [2023-09-26T16:20:30.198462 #88920]  INFO -- : Done!
  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 작업을 사용하면 다음과 같은 떨어진 객체를 찾을 수 있습니다:

떨어진 blob a12...
떨어진 commit b34...
떨어진 tag c56...
떨어진 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 데이터베이스에 여전히 참조가 있는 삭제된 아티팩트를 감지합니다.

여러분이 참조를 삭제하려면:

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

    artifacts_deleted = 0
    ::Ci::JobArtifact.find_each do |artifact|                      ### 아티팩트 반복
    #  next if artifact.file.filename != "job.log"                 ### '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                           ### file_store가 이미 로컬 저장소를 가리키는 경우 건너뜁니다
      artifacts_updated += 1
      # artifact.update(file_store: 1)                           ### 실제로 업데이트하려면 주석 해제
    end
    puts "업데이트된 file_store 카운트: #{artifacts_updated}"
    

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

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

VERBOSE=1 gitlab-rake gitlab:ci_secure_files:check은 다음과 같은 경우를 감지합니다.

  • GitLab 외부에서 삭제된 안전한 파일.
  • 여전히 GitLab 데이터베이스에 참조가 있는 파일.

이러한 시나리오가 감지되면 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} is missing."     ### 삭제 전 확인
    #  secure_file.destroy!                                           ### 실제로 삭제하려면 주석을 해제합니다
    end
    puts "식별된/삭제된 무효 참조 수: #{secure_files_deleted}"