正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

Gitaly Cluster (Praefect)のトラブルシューティング

  • プラン: Free、Premium、Ultimate
  • 提供形態: GitLab Self-Managed

Gitaly Cluster (Praefect)のトラブルシューティングを行う際は、以下の情報を参照してください。Gitalyのトラブルシューティングについては、Gitalyのトラブルシューティングを参照してください。

クラスターのヘルスチェック

check Praefectサブコマンドは、一連のチェックを実行して、Gitaly Cluster (Praefect)のヘルスチェックの状態を判断します。

gitlab-ctl praefect check

Praefectチャートを使用してPraefectをデプロイする場合は、バイナリを直接実行してください。

/usr/local/bin/praefect check

以下のセクションでは、実行されるチェックについて説明します。

Praefectの移行

データベースの移行がPraefectの正常な動作のために最新である必要があるため、Praefectの移行が最新であるかどうかをチェックします。

このチェックに失敗した場合:

  1. データベースのschema_migrationsテーブルを参照して、どの移行が実行されたかを確認します。
  2. praefect sql-migrateを実行して、移行を最新の状態にします。

ノードの接続性とディスクアクセス

PraefectがすべてのGitalyノードに到達できるかどうか、および各Gitalyノードがすべてのストレージへの読み取りおよび書き込みアクセス権を持っているかどうかをチェックします。

このチェックに失敗した場合:

  1. ネットワークアドレスとトークンが正しく設定されていることを確認します:
    • Praefect設定内。
    • 各Gitalyノードの設定内。
  2. Gitalyノードで、gitalyプロセスがgitとして実行されていることを確認します。Gitalyがストレージディレクトリにアクセスできないようにするアクセス許可の問題が発生している可能性があります。
  3. PraefectをGitalyノードに接続するネットワークに問題がないことを確認します。

データベースの読み取りと書き込みのアクセス

Praefectがデータベースから読み取り、データベースに書き込みできるかどうかをチェックします。

このチェックに失敗した場合:

  1. Praefectデータベースがリカバリーモードになっているかどうかを確認します。リカバリーモードでは、テーブルは読み取り専用になる場合があります。確認するには、以下を実行します:

    select pg_is_in_recovery()
  2. PraefectがPostgreSQLへの接続に使用するユーザーに、データベースへの読み取りおよび書き込みアクセス権があることを確認します。

  3. データベースが読み取り専用モードになっているかどうかを確認します。確認するには、以下を実行します:

    show default_transaction_read_only

アクセスできないリポジトリ

プライマリー割り当てがないか、プライマリーが利用できないために、アクセスできないリポジトリの数を確認します。

このチェックに失敗した場合:

  1. Gitalyノードがダウンしているかどうかを確認します。praefect ping-nodesを実行して確認します。
  2. Praefectデータベースに高い負荷がかかっているかどうかを確認します。Praefectデータベースの応答が遅い場合、ヘルスチェックがデータベースに永続化できなくなり、Praefectはノードが異常であると認識する可能性があります。

ログ内のPraefectエラー

エラーが発生した場合は、/var/log/gitlab/gitlab-rails/production.logを確認してください。

一般的なエラーと潜在的な原因を以下に示します:

  • 500レスポンスコード
    • ActionView::Template::Error (7:permission denied)
      • praefect['configuration'][:auth][:token]gitlab_rails['gitaly_token']がGitLabサーバーで一致しません。
      • gitlab_rails['repositories_storages']ストレージ設定がSidekiqサーバーにありません。
    • Unable to save project. Error: 7:permission denied
      • GitLabサーバーのpraefect['configuration'][:virtual_storage]のシークレットトークンが、1つ以上のGitalyサーバーのgitaly['auth_token']の値と一致しません。
  • 503レスポンスコード
    • GRPC::Unavailable (14:failed to connect to all addresses)
      • GitLabがPraefectに到達できませんでした。
    • GRPC::Unavailable (14:all SubCons are in TransientFailure...)
      • Praefectが1つ以上の子Gitalyノードに到達できません。Praefect接続チェッカーを実行して診断してみてください。

CPU負荷が高いPraefectデータベース

PraefectデータベースでCPU使用率が上昇する一般的な理由には、次のものがあります:

  • Prometheusメトリクスがコストのかかるクエリを実行してスクレイプするpraefect['configuration'][:prometheus_exclude_database_from_default_metrics] = truegitlab.rbに設定します。
  • 読み取り分散キャッシュが無効になっているため、ユーザートラフィックが多い場合にデータベースに対して行われるクエリの数が増加します。読み取り分散キャッシュが有効になっていることを確認してください。

プライマリGitalyノードを特定する

リポジトリのプライマリノードを特定するには、praefect metadataサブコマンドを使用します。

リポジトリのメタデータを表示

Gitaly Cluster (Praefect)は、クラスターに格納されているリポジトリに関するメタデータデータベースを保持します。praefect metadataサブコマンドを使用して、トラブルシューティングのメタデータを検査します。

リポジトリのメタデータは、Praefectによって割り当てられたリポジトリIDで取得できます:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id <repository-id>

物理ストレージ上の物理パスが@clusterで始まる場合、リポジトリIDを物理パスで確認できます

リポジトリのメタデータは、仮想ストレージと相対パスで取得することもできます:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage <virtual-storage> -relative-path <relative-path>

Praefectによって割り当てられたリポジトリIDが1のリポジトリのメタデータを取得するには:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id 1

仮想ストレージがdefault、相対パスが@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.gitのリポジトリのメタデータを取得するには:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage default -relative-path @hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git

これらの例のいずれかを実行すると、リポジトリのメタデータ例が取得されます:

Repository ID: 54771
Virtual Storage: "default"
Relative Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
Replica Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
Primary: "gitaly-1"
Generation: 1
Replicas:
- Storage: "gitaly-1"
  Assigned: true
  Generation: 1, fully up to date
  Healthy: true
  Valid Primary: true
  Verified At: 2021-04-01 10:04:20 +0000 UTC
- Storage: "gitaly-2"
  Assigned: true
  Generation: 0, behind by 1 changes
  Healthy: true
  Valid Primary: false
  Verified At: unverified
- Storage: "gitaly-3"
  Assigned: true
  Generation: replica not yet created
  Healthy: false
  Valid Primary: false
  Verified At: unverified

利用可能なメタデータ

praefect metadataによって取得されたメタデータには、次のテーブルのフィールドが含まれています。

フィールド説明
Repository IDPraefectによってリポジトリに割り当てられた永続的な一意のID。GitLabがリポジトリに使用するIDとは異なります。
Virtual Storageリポジトリが格納されている仮想ストレージの名前。
Relative Path仮想ストレージ内のリポジトリのパス。
Replica PathGitalyノードのディスク上のリポジトリのレプリカが格納されている場所。
Primaryリポジトリの現在のプライマリ。
GenerationPraefectがリポジトリの変更を追跡するために使用します。リポジトリへの書き込みごとに、リポジトリの世代が増加します。
Replicas存在するか、または存在することが予想されるレプリカのリスト。

各レプリカについて、次のメタデータを使用できます:

Replicasフィールド説明
Storageレプリカを含むGitalyストレージの名前。
Assignedレプリカがストレージに存在することが予想されるかどうかを示します。Gitalyノードがクラスターから削除された場合、またはリポジトリのレプリケーションファクターが減少した後でストレージに余分なコピーが含まれている場合は、falseになる可能性があります。
Generationレプリカの最新の確認済みの世代。それは以下を示します:

- 世代がリポジトリの世代と一致する場合、レプリカは完全に最新の状態です。
- レプリカの世代がリポジトリの世代よりも低い場合、レプリカは古くなっています。
- ストレージにレプリカがまだ存在しない場合は、replica not yet created
HealthyこのレプリカをホストしているGitalyノードが、Praefectノードのコンセンサスによって正常と見なされているかどうかを示します。
Valid Primaryレプリカがプライマリノードとして機能するのに適しているかどうかを示します。リポジトリのプライマリが有効なプライマリでない場合、別のレプリカが有効なプライマリである場合、リポジトリへの次の書き込みでフェイルオーバーが発生します。レプリカが有効なプライマリである条件:

- 正常なGitalyノードに格納されている。
- 完全に最新の状態である。
- レプリケーションファクターの減少による保留中の削除ジョブの対象になっていない。
- 割り当てられている。
Verified At検証ワーカーによるレプリカの最後の検証成功を示します。レプリカがまだ検証されていない場合は、最後の検証成功時刻の代わりにunverifiedが表示されます。

「リポジトリが見つかりません」というコマンドが失敗する

-virtual-storageに指定された値が正しくない場合、コマンドは次のエラーを返します:

get metadata: rpc error: code = NotFound desc = repository not found

ドキュメント化された例では、-virtual-storage defaultを指定します。/etc/gitlab/gitlab.rbのPraefectサーバーの設定praefect['configuration'][:virtual_storage]を確認してください。

リポジトリが同期していることを確認します

一部のケースでは、Praefectデータベースが基盤となるGitalyノードと同期しなくなる可能性があります。特定のリポジトリがすべてのノードで完全に同期されていることを確認するには、Railsノードでgitlab:praefect:replicas Rakeタスクを実行します。このRakeタスクは、すべてのGitalyノードのリポジトリをチェックサムします。

Praefect datalossコマンドは、Praefectデータベース内のリポジトリの状態のみをチェックし、このシナリオでは同期の問題を検出するために信頼することはできません。

datalossコマンドは、@failed-geo-syncリポジトリを同期していない状態で表示します

@failed-geo-syncは、プロジェクトの同期に失敗した場合にGeoがGitLab 16.1以前で使用していたレガシーパスであり、非推奨になりました。

GitLab 16.2以降では、このパスを安全に削除できます。@failed-geo-syncディレクトリは、Gitalyノードのリポジトリパスの下にあります。

リレーションが存在しないエラー

デフォルトでは、Praefectデータベーステーブルはgitlab-ctl reconfigureタスクによって自動的に作成されます。

ただし、Praefectデータベーステーブルは最初の再設定では作成されず、次のいずれかの場合はリレーションが存在しないというエラーが発生する可能性があります:

  • gitlab-ctl reconfigureコマンドが実行されていません。
  • 実行中にエラーが発生します。

例:

  • ERROR: relation "node_status" does not exist at character 13

  • ERROR: relation "replication_queue_lock" does not exist at character 40

  • このエラー:

    {"level":"error","msg":"Error updating node: pq: relation \"node_status\" does not exist","pid":210882,"praefectName":"gitlab1x4m:0.0.0.0:2305","time":"2021-04-01T19:26:19.473Z","virtual_storage":"praefect-cluster-1"}

これを解決するには、praefectコマンドのsql-migrateサブコマンドを使用して、データベーススキーマの移行を実行できます:

$ sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
praefect sql-migrate: OK (applied 21 migrations)

「リポジトリのスコープ: 無効なリポジトリ」エラーでリクエストが失敗する

これは、Praefect設定で使用されている仮想ストレージ名が、GitLabのgitaly['configuration'][:storage][<index>][:name]設定で使用されているストレージ名と一致しないことを示します。

PraefectとGitLab設定で使用されている仮想ストレージ名を一致させることで、これを解決します。

クラウドプラットフォームでのGitaly Cluster (Praefect)のパフォーマンスの問題

Praefectは多くのCPUやメモリを必要とせず、小さな仮想マシン上で実行できます。クラウドサービスでは、ディスクIOやネットワーク帯域幅など、小さなVMで使用できるリソースに他の制限が課せられる場合があります。

Praefectノードは大量のネットワーキングトラフィックを生成します。クラウドサービスによってネットワーク帯域幅が制限されている場合、次の症状が見られることがあります:

  • Git操作のパフォーマンスが低い。
  • 高いネットワークレイテンシー。
  • Praefectによる高いメモリ使用量。

考えられる解決策:

  • より大きなネットワーキングトラフィック許容量にアクセスするために、より大きなVMをプロビジョニングします。
  • クラウドサービスのモニタリングとログを使用して、Praefectノードがトラフィック許容量を使い果たしていないことを確認します。

Praefect設定エラーでgitlab-ctl reconfigureが失敗する

gitlab-ctl reconfigureが失敗した場合、次のエラーが表示されることがあります:

STDOUT: praefect: configuration error: error reading config file: toml: cannot store TOML string into a Go int

このエラーは、praefect['database_port']またはpraefect['database_direct_port']が整数ではなく文字列として設定されている場合に発生します。

一般的なレプリケーションエラー

以下に、考えられる解決策を備えた一般的なレプリケーションエラーをいくつか示します。

ロックファイルが存在する

ロックファイルは、同じrefsへの複数の更新を防ぐために使用されます。ロックファイルが古くなり、レプリケーションがエラーerror: cannot lock refで失敗することがあります。

古い*.lockファイルをクリアするには、RailsコンソールOptimizeRepositoryRequestをトリガーできます:

p = Project.find <Project ID>
client = Gitlab::GitalyClient::RepositoryService.new(p.repository)
client.optimize_repository

OptimizeRepositoryRequestのトリガーが機能しない場合は、ファイルを手動で調べて作成日を確認し、*.lockファイルを手動で削除できるかどうかを判断します。24時間以上前に作成されたロックファイルは安全に削除できます。

Git fsckエラー

無効なオブジェクトを持つGitalyリポジトリは、次のようなGitalyログのエラーでレプリケーションの失敗につながる可能性があります:

  • exit status 128, stderr: "fatal: git upload-pack: not our ref"
  • "fatal: bad object 58....e0f... ssh://gitaly/internal.git did not send all necessary objects

いずれかのGitalyノードにリポジトリの正常なコピーがまだある限り、これらの問題を修正できます:

  1. Praefectデータベースからリポジトリを削除します。
  2. Praefect track-repositoryサブコマンドを使用して、再度追跡します。

これにより、権限のあるGitalyノードからのリポジトリのコピーを使用して、他のすべてのGitalyノードのコピーを上書きします。これらのコマンドを実行する前に、リポジトリの最新のバックアップが作成されていることを確認してください。

  1. 問題のあるリポジトリを移動します:

    run `mv <REPOSITORY_PATH> <REPOSITORY_PATH>.backup`

    例:

    mv /var/opt/gitlab/git-data/repositories/@cluster/repositories/de/74/2335 /var/opt/gitlab/git-data/repositories/@cluster/repositories/de/74/2335.backup
  2. Praefectコマンドを実行して、レプリケーションをトリガーします:

    # Validate you have the correct repository.
    sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage gitaly -relative-path '<relative_path>' -db-only
    
    # Run again with '--apply' flag to remove repository from the Praefect tracking database
    sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage gitaly -relative-path '<relative_path>' -db-only --apply
    
    # Re-track the repository, overwriting the secondary nodes
    sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage gitaly -authoritative-storage '<healthy_gitaly>' -relative-path '<relative_path>' -replica-path '<replica_path>'-replicate-immediately

レプリケーションがサイレントに失敗する

Praefect datalossリポジトリの一部が利用できないことを示し、accept-datalossコマンドがログにエラーが表示されずにリポジトリを同期できない場合は、storage_repositoriesテーブルのrepository_idフィールドのPraefectデータベースの不一致が原因である可能性があります。不一致を確認するには:

  1. Praefectデータベースに接続します。

  2. 次のクエリを実行します:

    select * from storage_repositories where relative_path = '<relative-path>';

    <relative-path>を、@hashedで始まるリポジトリパスに置き換えます。

代替ディレクトリが存在しません

GitLabでは、Gitの代替メカニズムを使用して重複排除を行っています。alternatesは、オブジェクトをフェッチするために、@poolリポジトリのobjectsディレクトリを指すテキストファイルです。このファイルが無効なパスを指している場合、レプリケーションは以下のいずれかのエラーで失敗する可能性があります:

  • "error":"no alternates directory exists", "warning","msg":"alternates file does not point to valid git repository"
  • "error":"unexpected alternates content:
  • remote: error: unable to normalize alternate object path

このエラーの原因を調査するには、以下を実行します:

  1. プロジェクトがプールの一部であるかどうかを、Railsコンソールを使用して確認します:

    project = Project.find_by_id(<project id>)
    project.pool_repository
  2. プールリポジトリのパスがディスクに存在し、alternatesファイルの内容と一致することを確認します。

  3. alternatesファイル内のパスが、プロジェクト内のobjectsディレクトリから到達可能であることを確認します。

これらのチェックを実行した後、収集した情報を添えてGitLabサポートにお問い合わせください。