GitalyとGitalyクラスタのトラブルシューティング

GitalyおよびGitaly Clusterのトラブルシューティングについては、以下の情報をご参照ください。

Gitalyのトラブルシューティング

以下のセクションでは、Gitalyエラーの可能な解決策を提供します。

Gitaly のタイムアウト設定、およびgitaly/current ファイル](../logs/log_parsing.md#parsing-gitalycurrent)の[解析に関するアドバイスもご覧ください。

スタンドアロンのGitalyサーバーを使用する際のバージョンの確認

スタンドアロンのGitalyサーバーを使用する場合、完全な互換性を確保するためにGitLabと同じバージョンであることを確認する必要があります:

  1. 左のサイドバーで、Search を選択するか、次のページに進んでください。
  2. Admin Areaを選択します。
  3. 左サイドバーの「概要」>「Gitalyサーバー」を選択します。
  4. 全てのGitalyサーバーが最新であることを確認してください。

ストレージリソースの詳細を確認

Railsコンソールで以下のコマンドを実行することで、Gitalyストレージの使用可能領域と使用済み領域を調べることができます:

Gitlab::GitalyClient::ServerService.new("default").storage_disk_statistics
# For Gitaly Cluster
Gitlab::GitalyClient::ServerService.new("<storage name>").disk_statistics

使用方法gitaly-debug

gitaly-debug コマンドは、GitalyとGitのパフォーマンスに関する “プロダクション・デバッグ “ツールを提供します。これは、プロダクションエンジニアとサポートエンジニアがGitalyのパフォーマンスの問題を調査するのを助けることを目的としています。

サポートされているサブコマンドのリストについては、gitaly-debug のヘルプページを参照してください:

gitaly-debug -h

コミット、プッシュ、クローンは401を返します。

remote: GitLab: 401 Unauthorized

gitlab-secrets.json ファイルを GitLab アプリケーションノードと同期する必要があります。

リポジトリページで 500 とfetching folder content エラーが発生します。

Fetching folder contentや、場合によっては500 のエラーは、GitLab と Gitaly 間の接続性の問題を示しています。詳細はクライアント側のgRPCログを参照してください。

クライアント側のgRPCログ

GitalyはgRPCRPCフレームワークを使用しています。RubyのgRPCクライアントには独自のログファイルがあり、Gitalyのエラーが表示されたときに役立つ情報を含んでいるかもしれません。gRPC クライアントのログ・レベルはGRPC_LOG_LEVEL 環境変数で制御できます。デフォルトのレベルはWARN です。

gRPC トレースを実行するには、次のようにします:

sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check

このコマンドがfailed to connect to all addresses エラーで失敗する場合は、SSL または TLS に問題がないか確認してください:

/opt/gitlab/embedded/bin/openssl s_client -connect <gitaly-ipaddress>:<port> -verify_return_error

Verify return code フィールドが既知の Linux パッケージのインストール設定の問題を示しているかどうかを確認します。

openssl は成功するがgitlab-rake gitlab:gitaly:check は失敗する場合、Gitaly の証明書要件を確認してください。

サーバー側のgRPCログ

gRPCトレースは、Gitaly自身でも環境変数GODEBUG=http2debug を使って有効にすることができます。Linuxパッケージのインストールでこれを設定するには:

  1. gitlab.rb ファイルに以下を追加します:

    gitaly['env'] = {
      "GODEBUG=http2debug" => "2"
    }
    
  2. GitLab を再設定します。

GitプロセスとRPCの関連付け

時には、どのGitaly RPCが特定のGitプロセスを作成したのかを調べる必要があります。

そのための一つの方法は、DEBUG のロギングを使うことです。しかし、これは前もって有効にしておく必要があり、生成されるログはかなり冗長です。

この相関を行うための軽量な方法は、Gitプロセスの環境を検査し(そのPID )、CORRELATION_ID 変数を見ることです:

PID=<Git process ID>
sudo cat /proc/$PID/environ | tr '\0' '\n' | grep ^CORRELATION_ID=

Gitalyは内部的にRPCをプールして再利用しているので、この方法はgit cat-file

リポジトリの変更は401 Unauthorized エラーで失敗します。

Gitalyを自サーバで動作させていて、このような状態に気づいた場合:

  • ユーザーは、SSHとHTTPSの両方を使用して、リポジトリのクローンと取得に成功することができます。
  • ユーザーはリポジトリにプッシュできません。また、ウェブ UI でリポジトリに変更を加えようとすると401 Unauthorized メッセージが表示されます。

Gitalyクライアントのシークレットファイルが間違っているため、Gitalyの認証に失敗している可能性があります。

以下がすべて正しいことを確認してください:

  • 任意のユーザーがこのGitalyサーバー上の任意のリポジトリに対してgit push を実行すると、401 Unauthorized エラーで失敗します:

     remote: GitLab: 401 Unauthorized
     To <REMOTE_URL>
     ! [remote rejected] branch-name -> branch-name (pre-receive hook declined)
     error: failed to push some refs to '<REMOTE_URL>'
    
  • GitLab UI を使ってリポジトリからファイルを追加したり変更したりすると、401 Unauthorized の赤いバナーで即座に失敗します。
  • 新しいプロジェクトを作成してREADME で初期化すると、プロジェクトの作成には成功しますが、README は作成されません。
  • Gitalyクライアントでログを追跡し、エラーを再現すると、/api/v4/internal/allowed エンドポイントに到達する際に、401 エラーが発生します:

     # api_json.log
     {
       "time": "2019-07-18T00:30:14.967Z",
       "severity": "INFO",
       "duration": 0.57,
       "db": 0,
       "view": 0.57,
       "status": 401,
       "method": "POST",
       "path": "\/api\/v4\/internal\/allowed",
       "params": [
         {
           "key": "action",
           "value": "git-receive-pack"
         },
         {
           "key": "changes",
           "value": "REDACTED"
         },
         {
           "key": "gl_repository",
           "value": "REDACTED"
         },
         {
           "key": "project",
           "value": "\/path\/to\/project.git"
         },
         {
           "key": "protocol",
           "value": "web"
         },
         {
           "key": "env",
           "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}"
         },
         {
           "key": "user_id",
           "value": "2"
         },
         {
           "key": "secret_token",
           "value": "[FILTERED]"
         }
       ],
       "host": "gitlab.example.com",
       "ip": "REDACTED",
       "ua": "Ruby",
       "route": "\/api\/:version\/internal\/allowed",
       "queue_duration": 4.24,
       "gitaly_calls": 0,
       "gitaly_duration": 0,
       "correlation_id": "XPUZqTukaP3"
     }
       
     # nginx_access.log
     [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby"
    

この問題を解決するには、Gitalyサーバー上のgitlab-secrets.json ファイル が、Gitalyクライアント上のものと一致していることを確認してください。一致しない場合は、Gitalyサーバー上のシークレットファイルをGitalyクライアントと一致するように更新し、再設定してください。

gitlab-secrets.json ファイルがすべての Gitaly サーバーとクライアントで同じであることを確認した場合、アプリケーションはこのシークレットを別のファイルから取得している可能性があります。Gitalyサーバーのconfig.toml file 、使用中のシークレットファイルを示します。この設定がない場合、GitLabはデフォルトで/opt/gitlab/embedded/service/gitlab-rails/.gitlab_shell_secretの下にある.gitlab_shell_secret を使用します。

リポジトリのプッシュに失敗します。

git push を試すと、次のようになります:

  • 401 Unauthorized エラー。
  • サーバーのログに以下のようなものがあります:

     {
       ...
       "exception.class":"JWT::VerificationError",
       "exception.message":"Signature verification raised",
       ...
     }
    

このエラーは、GitLabサーバーがGitLab 15.5以降にアップグレードされているが、Gitalyがまだアップグレードされていない場合に発生します。

GitLab 15.5以降、GitLabは共有シークレットの代わりにJWTトークンを使ってGitLab Shellと認証します。外部Gitalyのアップグレードに関する推奨事項に従い、GitLabサーバの前にGitalyをアップグレードする必要があります。

リポジトリのプッシュがdeny updating a hidden ref エラーで失敗します。

GitLab 13.12で導入された変更により、Gitalyには読み取り専用のGitLab内部参照があり、ユーザーは更新することができません。git push --mirror で内部参照を更新しようとすると、Git は拒否エラーdeny updating a hidden refを返します。

以下の参照は読み取り専用です:

  • refs/environments/を参照してください。
  • refs/キープアラウンド
  • マージリクエスト
  • パイプライン

ブランチとタグだけをミラープッシュし、保護されたrefをミラープッシュしようとしないようにするには、以下を実行してください:

git push origin +refs/heads/*:refs/heads/* +refs/tags/*:refs/tags/*

管理者がプッシュしたい他の名前空間も、追加のパターンを使って含めることができます。

コマンドラインツールはGitalyに接続できません。

以下の場合、gRPCはGitalyサーバに接続できません:

  • コマンドラインツールでGitalyサーバーに接続できない場合。
  • 特定のアクションでは、14: Connect Failed のエラーメッセージが表示されます。

TCPでGitalyにアクセスできることを確認してください:

sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT]

TCP接続の場合:

  • ネットワーク設定とファイアウォールルールを確認してください。
  • 成功しました。ネットワークとファイアウォールのルールが正しく設定されています。

Bashなどのコマンドライン環境でプロキシサーバを使用している場合、gRPCトラフィックを妨害する可能性があります。

Bashまたは互換性のあるコマンドライン環境を使用している場合は、以下のコマンドを実行してプロキシサーバが設定されているかどうかを確認してください:

echo $http_proxy
echo $https_proxy

これらの変数のいずれかに値がある場合、Gitaly CLI接続はGitalyに接続できないプロキシを経由している可能性があります。

プロキシ設定を削除するには、以下のコマンドを実行してください(どの変数に値があるかによって異なります):

unset http_proxy
unset https_proxy

リポジトリにアクセスすると、GitalyまたはPraefectのログに権限拒否のエラーが表示されます。

GitalyやPraefectのログに以下のような記載がある場合があります:

{
  ...
  "error":"rpc error: code = PermissionDenied desc = permission denied",
  "grpc.code":"PermissionDenied",
  "grpc.meta.client_name":"gitlab-web",
  "grpc.request.fullMethod":"/gitaly.ServerService/ServerInfo",
  "level":"warning",
  "msg":"finished unary call with code PermissionDenied",
  ...
}

ログのこの情報は、gRPCコールのエラーレスポンスコードです。

Gitalyの認証トークンが正しく設定されているにもかかわらず、このエラーが発生する場合は、Gitalyサーバーでクロックドリフトが発生している可能性があります。

Gitalyクライアントとサーバーが同期していることを確認し、同期を保つためにNTPタイムサーバーを使用してください。

再設定後、Gitalyが新しいアドレスをリッスンしません。

gitaly['configuration'][:listen_addr] またはgitaly['configuration'][:prometheus_listen_addr] の値を更新すると、Gitaly はsudo gitlab-ctl reconfigureの後も古いアドレスでリッスンし続けることがあります。

このような場合は、sudo gitlab-ctl restart を実行してイシューを解決してください。このイシューは解決されたので、もう必要ありません。

スタンドアロンのGitalyノードからリポジトリにアクセスすると、Gitalyログに権限拒否のエラーが表示されます。

ファイルの権限が正しいにもかかわらずこのエラーが発生する場合、Gitalyノードでクロック・ドリフトが発生している可能性があります。

GitLabノードとGitalyノードが同期していることを確認し、可能であればNTPタイムサーバーを使って同期させてください。

ヘルスチェックの警告

/var/log/gitlab/praefect/current の以下の警告は無視してかまいません。

"error":"full method name not found: /grpc.health.v1.Health/Check",
"msg":"error when looking up method info"

ファイルが見つからないエラー

/var/log/gitlab/gitaly/current の以下のエラーは無視してかまいません。これらのエラーは、GitLab Rails アプリケーションがリポジトリに存在しない特定のファイルをチェックするために発生します。

"error":"not found: .gitlab/route-map.yml"
"error":"not found: Dockerfile"
"error":"not found: .gitlab-ci.yml"

Dynatrace を有効にすると Git のプッシュが遅くなります。

Dynatrace が有効になっていると、/opt/gitlab/embedded/bin/gitaly-hooks 参照トランザクションフックの起動と終了に数秒かかることがあります。gitaly-hooks はユーザーがプッシュするときに二度実行されるため、大幅な遅延が発生します。

Dynatraceが有効になっているときにGitのプッシュが遅すぎる場合は、Dynatraceを無効にしてください。

gitaly check 401 というステータスコードで失敗します。

gitaly check Gitalyが内部GitLab APIにアクセスできない場合、401 ステータスコードで失敗することがあります。

これを解決する一つの方法は、gitlab.rb で設定した GitLab 内部 API URL のエントリが正しいことをgitlab_rails['internal_api_url'] で確認することです。

Gitaly がnoexec ファイルシステムに保存されたプロセスのフォークに失敗します。

GitLab 14.10で導入された変更のため、noexec オプションをマウントポイントに適用すると(例えば、/var)、Gitalyはプロセスのフォークに関連するpermission denied エラーを投げます。例えば

fork/exec /var/opt/gitlab/gitaly/run/gitaly-2057/gitaly-git2go: permission denied

これを解決するには、ファイルシステムのマウントからnoexec オプションを削除します。別の方法としては、Gitalyのランタイム・ディレクトリを変更することです:

  1. /etc/gitlab/gitlab.rbgitaly['runtime_dir'] = '<PATH_WITH_EXEC_PERM>' を追加し、noexec を設定しない場所を指定します。
  2. sudo gitlab-ctl reconfigure を実行してください。

コミット署名がinvalid argument: signing key is encrypted またはinvalid data: tag byte does not have MSB set.

Gitaly のコミット署名はヘッドレスで、特定のユーザーに関連付けられていないため、GPG 署名鍵はパスフレーズなしで作成するか、エクスポート前にパスフレーズを削除する必要があります。

Praefect(クラスター)のトラブルシューティング

以下のセクションでは、Gitaly Clusterのエラーに対する可能な解決策を提供します。

クラスターの健全性の確認

GitLab 14.5 で導入されました

check Praefectサブコマンドは、Gitalyクラスタの健全性を判断するために一連のチェックを実行します。

gitlab-ctl praefect check

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

マイグレーション

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. Prafectデータベースの負荷が高いかどうかを確認します。Praefectデータベースの応答が遅い場合、ヘルスチェックがデータベースに反映されず、Praefectがノードを不健全であると判断する可能性があります。

クロック同期のチェック

GitLab 14.8で導入されました

PraefectとGitalyサーバー間の認証では、トークンのチェックが成功するようにサーバーの時間が同期している必要があります。

このチェックは、Praefectによって記録されるpermission denied エラーの根本原因を特定するのに役立ちます。

公開pool.ntp.org サーバーにアクセスできないオフライン環境では、Praefectcheck サブコマンドはこのチェックに失敗し、次のようなエラーメッセージが表示されます:

checking with NTP service at  and allowed clock drift 60000ms [correlation_id: <XXX>]
Failed (fatal) error: gitaly node at tcp://[gitlab.example-instance.com]:8075: rpc error: code = DeadlineExceeded desc = context deadline exceeded

このイシューを解決するには、すべての Praefect サーバーで、アクセス可能な内部 NTP サーバーを指すように環境変数を設定します。たとえば、次のようになります:

export NTP_HOST=ntp.example.com

ログのPraefectエラー

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

よくあるエラーとその原因について説明します:

  • 500レスポンスコード
    • ActionView::Template::Error (7:permission denied)
      • praefect['configuration'][:auth][:token]gitlab_rails['gitaly_token'] が GitLab サーバー上で一致しません。
    • 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接続チェッカーを実行して診断してみてください。

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

PraefectデータベースのCPU使用率が高くなる一般的な原因には、次のようなものがあります:

  • Prometheus メトリクスで高価なクエリが実行されている場合。GitLab 14.2 以上の場合は、gitlab.rbpraefect['configuration'][:prometheus_exclude_database_from_default_metrics] = true を設定してください。
  • リード・ディストリビューション・キャッシングが無効になっているため、ユーザーのトラフィックが多いときにデータベースへのクエリ数が増えます。読み取りディストリビューション・キャッシングが有効になっていることを確認してください。

プライマリ・ノードの決定

リポジトリのプライマリノードを決定します:

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

GitLab 14.6で導入されました

Gitaly Clusterはクラスターに保存されたリポジトリに関するメタデータデータベースを維持します。トラブルシューティングのためにメタデータを調べるにはpraefect metadata サブコマンドを使います。

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

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

物理ストレージ上の物理パスが@cluster で始まる場合、物理パスでリポジトリ ID を見つけることができます。

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

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

使用例

リポジトリ ID が 1 のリポジトリのメタデータを取得します:

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

仮想ストレージdefault および相対パス@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git を持つリポジトリのメタデータを取得するには、次の手順に従います:

sudo /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リポジトリの現在のプライマリ。
Generationリポジトリの変更を追跡するために Praefect が使用します。リポジトリに書き込まれるたびに、リポジトリの世代がインクリメントされます。
Replicas存在する、または存在すると予想されるレプリカのリスト。

各レプリカについて、以下のメタデータが利用可能です:

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

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

- 健全な Gitaly ノードに保存されている。
- 完全に最新である。
- レプリケーション要因の減少による保留中の削除ジョブの対象になっていない。
- 割り当てられている。
Verified At 検証ワーカーがレプリカの検証に最後に成功した時刻を示します。レプリカがまだ検証されていない場合、最後に検証に成功した時刻の代わりにunverified が表示されます。GitLab 15.0 で導入されました。

リポジトリが見つかりません’でコマンドが失敗します。

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

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

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

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

場合によっては、PraefectデータベースとGitalyノードの同期がずれることがあります。指定したリポジトリがすべてのノードで完全に同期されていることを確認するには、gitlab:praefect:replicas Rake タスク を実行して、すべての Gitaly ノードでリポジトリのチェックサムを行います。

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

関係が存在しないエラー

デフォルトでは、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 /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
praefect sql-migrate: OK (applied 21 migrations)

repository scoped: invalid Repository」エラーでリクエストが失敗します。

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

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

クラウドプラットフォーム上でのGitalyクラスターのパフォーマンスのイシュー

Praefectは多くのCPUやメモリを必要としないため、小規模な仮想マシン上で実行できます。クラウドサービスでは、ディスクIOやネットワークトラフィックなど、小規模なVMが使用できるリソースに制限が設けられている場合があります。

Praefectノードは多くのネットワークトラフィックを生成します。クラウドサービスによってネットワーク帯域幅が制限されている場合、次のような症状が見られます:

  • Gitオペレーションのパフォーマンスの低下。
  • ネットワーク遅延が大きい
  • Praefectによるメモリ使用量の多さ。

解決策

  • より大きなVMをプロビジョニングして、より大きなネットワーク・トラフィック許容値を利用できるようにします。
  • クラウドサービスの監視とロギングを使用して、Praefectノードがトラフィック許容量を使い果たしていないことを確認します。

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'] が整数ではなく文字列として設定されている場合に発生します。

Gitalyのプロファイリング

Gitalyは、PrometheusがリッスンしているポートのGoビルトイン・パフォーマンス・プロファイリング・ツールのいくつかを公開します。例えば、PrometheusがGitLabサーバーのポート9236

  • 実行中のgoroutines とそのバックトレースのリストを取得します:

     curl --output goroutines.txt "http://<gitaly_server>:9236/debug/pprof/goroutine?debug=2"
    
  • CPUプロファイルを30秒間実行します:

     curl --output cpu.bin "http://<gitaly_server>:9236/debug/pprof/profile"
    
  • プロファイルのヒープメモリ使用量:

     curl --output heap.bin "http://<gitaly_server>:9236/debug/pprof/heap"
    
  • 5秒間の実行トレースを記録します。これは実行中のGitalyパフォーマンスに影響します:

     curl --output trace.bin "http://<gitaly_server>:9236/debug/pprof/trace?seconds=5"
    

go がインストールされているホストでは、CPUプロファイルとヒーププロファイルをブラウザで見ることができます:

go tool pprof -http=:8001 cpu.bin
go tool pprof -http=:8001 heap.bin

実行トレースは、実行することで見ることができます:

go tool trace heap.bin