インテグリティ・チェック レーキ・タスク

GitLabは様々なコンポーネントの整合性をチェックするRakeタスクを提供しています。checkGitLab設定Rakeタスクも参照してください。

リポジトリの整合性

Gitはとても回復力があり、データの整合性の問題を防ごうとしていますが、うまくいかないこともあります。以下のRakeタスクは、GitLab管理者が問題のあるリポジトリを診断して修正できるようにするためのものです。

これらのRakeタスクは、Gitリポジトリの整合性を判断するために3つの異なる方法を使います。

  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
    

リポジトリ参照チェックサム

Git リポジトリを別のリポジトリと比較するには、それぞれのリポジトリのすべての refsum をチェックします。両方のリポジトリが同じ refs を持ち、両方のリポジトリがインテグレーションチェックをパスすれば、どちらのリポジトリも同じものであると確信できます。

例えば、これはリポジトリのバックアップとソースリポジトリを比較するために使用できます。

すべてのGitLabリポジトリをチェック

このタスクはGitLabサーバー上のすべてのリポジトリをループし、チェックサムを<PROJECT ID>,<CHECKSUM>.

  • リポジトリが存在しない場合は、プロジェクト 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 リポジトリをチェックします。

オプションで、特定のプロジェクト ID をチェックサムすることもできます。環境変数CHECKSUM_PROJECT_IDS にカンマで区切った整数のリストを指定します:

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

アップロードされたファイルの整合性

GitLabインストールには、ユーザーによって様々な種類のファイルがアップロードされます。これらの整合性チェックはファイルが見つからないことを検出します。さらに、ローカルに保存されたファイルについては、アップロード時にチェックサムが生成されてデータベースに保存され、これらのチェックによって現在のファイルと照合されます。

完全性チェックは以下のタイプのファイルでサポートされています:

  • CIアーティファクト(GitLab 10.7.0で導入)
  • LFS オブジェクト (GitLab 10.6.0 で導入)
  • プロジェクトレベルのセキュアファイル (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 値を指定します。
VERBOSEboolean失敗をまとめるのではなく、個別にリストアップします。
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
Checking integrity of Uploads
- 1..1350: Failures: 0
- 1351..2743: Failures: 0
- 2745..4349: Failures: 2
- 4357..5762: Failures: 1
- 5764..7140: Failures: 2
- 7142..8651: Failures: 0
- 8653..10134: Failures: 0
- 10135..11773: Failures: 0
- 11777..13315: Failures: 0
Done!

冗長出力の例:

$ sudo gitlab-rake gitlab:uploads:check VERBOSE=1
Checking integrity of Uploads
- 1..1350: Failures: 0
- 1351..2743: Failures: 0
- 2745..4349: Failures: 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: Failures: 1
  - Upload: 4636: #<Google::Apis::ServerError: Server error>
- 5764..7140: Failures: 2
  - Upload: 5812: #<NoMethodError: undefined method `hashed_storage?' for nil:NilClass>
  - Upload: 5837: #<NoMethodError: undefined method `hashed_storage?' for nil:NilClass>
- 7142..8651: Failures: 0
- 8653..10134: Failures: 0
- 10135..11773: Failures: 0
- 11777..13315: Failures: 0
Done!

LDAPチェック

LDAP check Rake タスクは、(設定されていれば) バインド DN とパスワード認証情報をテストし、LDAP ユーザーのサンプルをリストアップします。このタスクはgitlab:check タスクの一部としても実行されますが、独立して実行することもできます。詳細はLDAP Rake Tasks - LDAP Checkを参照してください。

現在のシークレットを使用してデータベースの値を復号化できることを確認します。

GitLab 13.1で導入されました。

このタスクはデータベース内のすべての暗号化された値を実行し、現在のシークレットファイル(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
[...] other models possibly containing encrypted data
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 -- : Total: 1 row(s) affected
I, [2020-06-11T17:18:15.575711 #27148]  INFO -- : Done!

詳細モード

どの行や列が復号化できないかについて、より詳細な情報を得るには、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
[...] other models possibly containing encrypted data
D, [2020-06-11T17:19:53.224344 #27351] DEBUG -- : > Something went wrong for Group[10].runners_token: Validation failed: 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 -- : Total: 1 row(s) affected
I, [2020-06-11T17:18:15.575711 #27148]  INFO -- : Done!

トラブルシューティング

上記で説明した Rake タスクを使用して発見した問題の解決方法を以下に示します。

ぶら下がるオブジェクト

gitlab-rake gitlab:git:fsck タスクは、次のようなぶら下がりオブジェクトを見つけることができます:

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

これらを削除するには、ハウスキーピングを実行してください。

それでもイシューが消えない場合は、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
Checking integrity of Uploads
- 100..434: Failures: 2
- Upload: 100: Remote object does not exist
- Upload: 101: Remote object does not exist
Done!

外部で削除されたリモートアップロードへの参照を削除するには、GitLab Rails コンソールを開いて実行します:

uploads_deleted=0
Upload.find_each do |upload|
  next if upload.retrieve_uploader.file.exists?
  uploads_deleted=uploads_deleted + 1
  p upload                            ### allow verification before destroy
  # p upload.destroy!                 ### uncomment to actually destroy
end
p "#{uploads_deleted} remote objects were destroyed."

見つからないアーティファクトへの参照を削除します。

gitlab-rake gitlab:artifacts:check VERBOSE=1 アーティファクト (またはjob.log ファイル) を検出します:

  • GitLabの外部で削除された場合。
  • GitLabデータベースに参照が残っている場合。

このシナリオが検出されると、Rakeタスクはエラーメッセージを表示します。例えば

Checking integrity of Job artifacts
- 1..15: Failures: 2
  - Job artifact: 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>
  - Job artifact: 15: Remote object does not exist
Done!

ローカルおよび/またはリモートに存在しないアーティファクト (job.log ファイル) への参照を削除します:

  1. GitLab Rails Consoleを開きます。
  2. 以下のRubyコードを実行します:

    artifacts_deleted = 0
    ::Ci::JobArtifact.find_each do |artifact|                      ### Iterate artifacts
    #  next if artifact.file.filename != "job.log"                 ### Uncomment if only `job.log` files' references are to be processed
      next if artifact.file.file.exists?                           ### Skip if the file reference is valid
      artifacts_deleted += 1
      puts "#{artifact.id}  #{artifact.file.path} is missing."     ### Allow verification before destroy
    #  artifact.destroy!                                           ### Uncomment to actually destroy
    end
    puts "Count of identified/destroyed invalid references: #{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 Consoleを開きます。
  2. 以下のRubyコードを実行します:

    artifacts_updated = 0
    ::Ci::JobArtifact.find_each do |artifact|                    ### Iterate artifacts
      next if artifact.file_store != 2                           ### Skip if file_store already points to local storage
      artifacts_updated += 1
      # artifact.update(file_store: 1)                           ### Uncomment to actually update
    end
    puts "Updated file_store count: #{artifacts_updated}"
    

不足しているアーティファクトへの参照を削除するスクリプトが正しく機能するようになり、データベースがクリーンアップされました。

見つからないセキュリティファイルへの参照の削除

VERBOSE=1 gitlab-rake gitlab:ci_secure_files:check セキュリティで保護されたファイルを検出します:

  • GitLabの外部で削除された場合。
  • GitLabデータベースに参照が残っている場合。

このシナリオが検出されると、Rakeタスクはエラーメッセージを表示します。例えば

Checking integrity of CI Secure Files
- 1..15: Failures: 2
  - Job SecureFile: 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>
  - Job SecureFile: 15: Remote object does not exist
Done!

紛失したローカルまたはリモートのセキュリティファイルへの参照を削除するには、以下の手順に従います:

  1. GitLab Rails Consoleを開きます。
  2. 以下のRubyコードを実行します:

    secure_files_deleted = 0
    ::Ci::SecureFile.find_each do |secure_file|                    ### Iterate secure files
      next if secure_file.file.file.exists?                        ### Skip if the file reference is valid
      secure_files_deleted += 1
      puts "#{secure_file.id}  #{secure_file.file.path} is missing."     ### Allow verification before destroy
    #  secure_file.destroy!                                           ### Uncomment to actually destroy
    end
    puts "Count of identified/destroyed invalid references: #{secure_files_deleted}"