Gitalyクラスタの復旧オプションとツール

Gitaly Clusterはプライマリノードの障害や利用できないリポジトリから復旧することができます。Gitaly Clusterはデータ復旧を行うことができ、Praefect追跡データベースツールを備えています。

Gitalyクラスタ上のGitalyノードの管理

Gitalyクラスタ上のGitalyノードの追加や入れ替えができます。

新しいGitalyノードの追加

レプリケーション要素を持つGitalyクラスターに、新しいGitalyノードを追加します:

  • set-replication-factor Praefect コマンドを使用して、各リポジトリのレプリケーション係数を設定します。新しいリポジトリは、レプリケーション係数に基づいてレプリケートされます。Praefectは、既存のリポジトリを新しいGitalyノードに自動的にレプリケートしません。
  • 設定されていない場合は、Praefectの設定でpraefect['virtual_storages'] の下に新しいノードを追加します。Praefectは、設定に追加された新しいGitalyノードにすべてのデータを自動的にレプリケートします。

既存のGitalyノードの置き換え

既存のGitalyノードを、同じ名前または異なる名前の新しいノードに置き換えることができます。

同じ名前のノード

置き換えノードに同じ名前を使用するには、リポジトリ検証ツールを使用してストレージをスキャンし、ぶら下がったメタデータレコードを削除します。置換後のストレージの検証を手動で優先して、処理を高速化します。

異なる名前のノードで

レプリケーション要素を持つGitalyクラスタの代替ノードに別の名前を使用するには:

  • 新しいストレージを割り当てるために、praefect set-replication-factor を使用して、リポジトリごとのレプリケーション係数を再度設定します。例えば

     $ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage default -relative-path @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git -replication-factor 2
       
     current assignments: gitaly-1, gitaly-2
    

    新しいGitalyノードを設定した後、すべてのリポジトリを古いストレージから新しいストレージに再割り当てする場合:

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

      /opt/gitlab/embedded/bin/psql -h <psql host> -U <user> -d <database name>
      
    2. repository_assignments テーブルを更新して、古い Gitaly ノード名(例:old-gitaly )を新しい Gitaly ノード名(例:new-gitaly)に置き換えます:

      UPDATE repository_assignments SET storage='new-gitaly' WHERE storage='old-gitaly';
      
  • 設定されていない場合は、設定内のノードを置き換えます。古いノードの状態は Praefect データベースに残りますが、無視されます。

プライマリノードの障害

  • GitLab 13.0から導入されたGitalyクラスタは、プライマリからの未複製の書き込みが最も少ないセカンダリを新しいプライマリとして選択します。まだ複製されていない書き込みがある可能性があり、データ損失が発生する可能性があります。
  • GitLab 14.1でプライマリノードの障害復旧サポートが追加されました。

Gitaly Clusterは、プライマリGitalyノードの障害から、健全なセカンダリノードを新しいプライマリとして昇格させることで回復します。Gitaly Cluster:

  • リポジトリの完全な最新コピーを持つ健全なセカンダリを新しいプライマリとして選択します。
  • 健全なセカンダリにリポジトリの完全な最新コピーがない場合、リポジトリは利用できなくなります。

利用できないリポジトリ

  • GitLab 13.0から14.0までは、プライマリでは古くても健全なセカンダリでは完全に最新であればリポジトリは読み込み専用になりました。dataloss サブコマンドはこれらのバージョンまでデフォルトで読み込み専用のリポジトリを表示します。
  • GitLab 14.1以降、Praefectはより応答性の高いフェイルオーバーロジックを含んでおり、リポジトリを読み取り専用モードにするのではなく、完全に最新化されたセカンダリの1つに即座にフェイルオーバーします。GitLab 14.1より、dataloss サブコマンドは、健康なGitalyノード上に完全に最新のコピーがないために利用できないリポジトリを表示します。

リポジトリが利用できないのは、最新のレプリカがすべて利用できない場合です。利用できないリポジトリは、自動化ツールを破損する可能性のある古いデータを提供することを防ぐため、Praefectからアクセスできません。

データ損失のチェック

Praefectdataloss サブコマンドで確認します:

  • GitLab 13.0からGitLab 14.0へのリポジトリのコピー。これは、フェイルオーバー後の潜在的なデータ損失を特定するのに役立ちます。
  • 利用できないGitLab 14.1以降のリポジトリ。これは、潜在的なデータ損失や、最新のレプリカコピーがすべて利用できないためにアクセスできなくなったリポジトリを特定するのに役立ちます。

以下のパラメータが利用可能です:

  • -virtual-storage どの仮想ストレージをチェックするかを指定します。管理者が介入する必要があるため、デフォルトの動作は表示されます:
    • GitLab 13.0から14.0では、読み取り専用リポジトリのコピー。
    • GitLab 14.1以降では、利用できないリポジトリ。
  • GitLab 14.1以降では、-partially-unavailable 。利用可能だが、利用不可能なコピーが割り当てられているリポジトリを出力に含めるかどうかを指定します。
note
dataloss はまだベータ版であり、出力形式は変更される可能性があります。

プライマリが古いリポジトリや利用できないリポジトリをチェックするには、以下を実行してください:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>]

何も指定されていない場合は、設定されているすべての仮想ストレージがチェックされます:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss

リポジトリは、次のいずれかを持つ出力にリストされます:

  • GitLab 13.0 から GitLab 14.0 で、プライマリ上のリポジトリの古いコピー。
  • GitLab 14.1 以降では、健全で完全に最新のコピーがありません。

リポジトリごとに以下の情報が出力されます:

  • リポジトリのストレージディレクトリへの相対パスは、各リポジトリを識別し、関連する情報をグループ化します。
  • リポジトリの現在の状態は、ディスクパスの横の括弧内に表示されます:
    • GitLab 13.0 から 14.0 では、リポジトリのプライマリノードが古くて書き込みを受け付けない場合は(read-only) のどちらかです。そうでない場合は、(writable)
    • GitLab 14.1以降では、リポジトリが利用できない場合、(unavailable) がディスクパスの横に表示されます。
  • プライマリフィールドには、リポジトリの現在のプライマリが表示されます。リポジトリにプライマリがない場合、No Primary と表示されます。
  • In-Sync Storages には、書き込みに成功した最新の書き込みと、それに先行するすべての書き込みをレプリケートしたレプリカが一覧表示されます。
  • Outdated Storages は、リポジトリの古いコピーを含むレプリカを一覧表示します。リポジトリのコピーを持っていないが、リポジトリのコピーを持っているはずのレプリカもここに表示されます。レプリカが欠落している変更の最大数は、レプリカの横に表示されます。古いレプリカは完全に最新であるか、またはそれ以降の変更が含まれている可能性がありますが、Praefectでは保証できないことに注意してください。

その他の情報は以下の通りです:

  • リポジトリのホストとしてノードが割り当てられているかどうかは、各ノードのステータスと一緒に表示されます。assigned host は、リポジトリの保存先として割り当てられているノードの横に表示されます。ノードの中にリポジトリのコピーがあるが、リポジトリの保存を割り当てられていない場合は、テキストは省略されます。このようなコピーは、Praefect によって同期されませんが、割り当てられたコピーを最新の状態にするためのレプリケーションソースとして機能することがあります。
  • GitLab 14.1以降では、不健康なGitalyノードにあるコピーの横にunhealthy

出力例です:

Virtual storage: default
  Outdated repositories:
    @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git (unavailable):
      Primary: gitaly-1
      In-Sync Storages:
        gitaly-2, assigned host, unhealthy
      Outdated Storages:
        gitaly-1 is behind by 3 changes or less, assigned host
        gitaly-3 is behind by 3 changes or less

すべてのリポジトリが利用可能になると確認が出力されます。例えば

Virtual storage: default
  All repositories are available!

利用可能なリポジトリの利用不可能なレプリカ

GitLab 14.0 で導入され、フラグは-partially-replicated から改名され、動作も変更されました。

利用可能だが割り当てられたノードから利用できないリポジトリの情報も一覧表示するには、-partially-unavailable フラグを使用します。

リポジトリが利用可能なのは、健全で最新のレプリカが利用可能な場合です。割り当てられたセカンダリレプリカの中には、最新の変更をレプリケートするのを待っている間、一時的にアクセスできないものがあるかもしれません。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>] [-partially-unavailable]

出力例です:

Virtual storage: default
  Outdated repositories:
    @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git:
      Primary: gitaly-1
      In-Sync Storages:
        gitaly-1, assigned host
      Outdated Storages:
        gitaly-2 is behind by 3 changes or less, assigned host
        gitaly-3 is behind by 3 changes or less

-partially-unavailable フラグが設定されている場合、割り当てられた全てのレプリカが最新で健全であるかの確認が出力されます。

使用例:

Virtual storage: default
  All repositories are fully available on all assigned storages!

リポジトリのチェックサムチェック

プロジェクトのリポジトリのチェックサムをすべてのGitalyノードでチェックするには、メインのGitLabノードでreplicas Rakeタスクを実行します。

データロスを受け入れる

caution
accept-dataloss は、リポジトリの他のバージョンを上書きすることで、永続的なデータ損失を引き起こします。使用する前にデータ復旧作業を行う必要があります。

最新のレプリカのいずれかをオンラインに戻すことができない場合は、データ損失を受け入れる必要があります。データ損失を受け入れる場合、Praefectはリポジトリの選択したレプリカを最新バージョンとしてマークし、割り当てられた他のGitalyノードにレプリケートします。このプロセスは、リポジトリの他のバージョンを上書きするため、注意が必要です。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss
-virtual-storage <virtual-storage> -relative-path <relative-path> -authoritative-storage <storage-name>

書き込みを有効にするか、データ損失を受け入れるか

caution
accept-dataloss を使用すると、リポジトリの他のバージョンを上書きすることによって永久的なデータ損失を引き起こします。使用する前にデータaccept-dataloss復旧作業をaccept-dataloss行う必要があります。

Praefectには、書き込みを再有効化するか、データ損失を受け入れるための以下のサブコマンドがあります。最新ノードの1つをオンラインに戻すことができない場合は、データ損失を受け入れなければならない場合があります:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss -virtual-storage <virtual-storage> -relative-path <relative-path> -authoritative-storage <storage-name>

データ損失を受け入れる場合、Praefect:

  1. 選択したリポジトリのコピーを最新バージョンとしてマークします。
  2. 他のGitalyノードにコピーを複製します。

この処理は、リポジトリの他のコピーを上書きしますので、注意が必要です。

データ復旧

Gitalyノードが何らかの理由でレプリケーション・ジョブに失敗した場合、影響を受けたリポジトリの古いバージョンをホストすることになります。Praefectは以下のツールを提供します:

  • GitLab 13.4以降の自動リコンシリエーション。
  • 手動照合:
    • GitLab 13.3以前。
    • GitLab 13.4 以降にアップグレードされたリポジトリで、repositories テーブルにエントリがないもの。GitLab 13.6 以降では、マイグレーションはこれらのリポジトリに対して Praefect の起動時に実行されます。

これらのツールは、古くなったリポジトリを調整し、完全に最新の状態に戻します。

自動照合

GitLab 13.4 で導入されました

Praefectは、最新でないリポジトリを自動的に調整します。デフォルトでは、これは5分ごとに実行されます。健全なGitalyノード上のそれぞれの古いリポジトリに対して、Praefectは別の健全なGitalyノード上のリポジトリのランダムで完全に最新のレプリカを選んでレプリケートします。レプリケーションジョブは、ターゲットリポジトリに対して保留中の他のレプリケーションジョブがない場合にのみスケジュールされます。

照合頻度は設定で変更できます。この値は、有効なGo期間の値であれば何でもかまいません。0以下の値はこの機能を無効にします。

例:

praefect['configuration'] = {
   # ...
   reconciliation: {
      # ...
      scheduling_interval: '5m', # the default value
   },
}
praefect['configuration'] = {
   # ...
   reconciliation: {
      # ...
      scheduling_interval: '30s', # reconcile every 30 seconds
   },
}
praefect['configuration'] = {
   # ...
   reconciliation: {
      # ...
      scheduling_interval: '0', # disable the feature
   },
}

手動照合

caution
reconcile サブコマンドは GitLab 14.1 で削除されました。代わりに自動照合を使用してください。手動照合は過剰なレプリケーションジョブを生成する可能性があり、機能にも制限があります。リポジトリ固有のプライマリノードが有効になっている場合、手動照合は機能しません。

Praefectreconcile サブコマンドを使用すると、2 つの Gitaly ノード間の手動照合を行うことができます。このコマンドは、参照ストレージ上の後のバージョンのすべてのリポジトリをターゲットストレージにレプリケートします。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -reference <up-to-date-storage> -target <outdated-storage> -f
  • プレースホルダ<virtual-storage> を、確認する Gitaly ノード ストレージを含む仮想ストレージに置き換えます。
  • プレースホルダ<up-to-date-storage> を、最新のリポジトリを含む Gitaly ストレージ名に置き換えてください。
  • プレースホルダ<outdated-storage> を、古いリポジトリを含む Gitaly ストレージ名に置き換えてください。

リポジトリの手動削除

  • GitLab 14.3で導入されました
  • GitLab 14.6で導入された、ドライランモードのサポート。
  • GitLab 15.3 で導入れた、Praefect トラッキングデータベースからのリポジトリの削除のサポート。

remove-repository Praefect サブコマンドは、Gitaly クラスターからリポジトリを削除し、指定されたリポジトリを含むリポジトリに関連するすべての状態を削除します:

  • 関連するすべてのGitalyノード上のオンディスクリポジトリ。
  • Praefectによって追跡されるすべてのデータベース状態。

GitLab 14.6以降では、デフォルトでこのコマンドはドライランモードでオペレーションします。以前のバージョンでは、コマンドはドライランモードに対応していませんでした。例えば

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage <virtual-storage> -relative-path <repository>
  • <virtual-storage> をリポジトリが入っている仮想ストレージの名前に置き換えてください。
  • <repository> を削除するリポジトリの相対パスに置き換えます。
  • GitLab 15.3 以降では、-db-only を追加すると、ディスク上のリポジトリを削除せずに、Praefect トラッキングデータベースエントリーを削除できます。このオプションは、孤児となったデータベースエントリを削除したり、有効なリポジトリが誤って指定された場合にディスク上のリポジトリデータを削除から保護したりするために使用します。データベースエントリが誤って削除された場合は、track-repository コマンドを使用してリポジトリを再トラッキングします。
  • GitLab 14.6 以降では、-apply を追加して、ドライランモード以外でコマンドを実行し、リポジトリを削除します。例えば

     sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage <virtual-storage> -relative-path <repository> -apply
    
  • -virtual-storage はリポジトリが置かれている仮想ストレージです。仮想ストレージはpraefect['configuration']['virtual_storage] の下の/etc/gitlab/gitlab.rb に設定され、以下のようになります:

     praefect['configuration'] = {
       # ...
       virtual_storage: [
         {
           # ...
           name: 'default',
         },
         {
           # ...
           name: 'storage-1',
         },
       ],
     }
    

    この例では、指定する仮想ストレージはdefault またはstorage-1 です。

  • -repository@hashed](../repository_storage_types.md#hashed-storage)で始まるストレージ[内のリポジトリの相対パスです。例えば

     @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
    

remove-repository を実行しても、リポジトリの一部が存在し続けることがあります。これは次のような理由が考えられます:

  • 削除エラー。
  • リポジトリを対象としたインフライト RPC 呼び出し。

この場合は、remove-repository を再度実行してください。

Praefect トラッキングデータベースのメンテナンス

Praefect トラッキングデータベースの一般的なメンテナンスタスクについて説明します。

未追跡リポジトリの一覧表示

list-untracked-repositories Praefect サブコマンドは、Gitalyクラスターのリポジトリを一覧表示します:

  • 少なくとも1つのGitalyストレージに存在します。
  • Praefectのトラッキングデータベースにトラッキングされていないこと。

-older-than オプションを追加して、以下のリポジトリを表示しないようにします:

  • 以下のリポジトリは作成中です。
  • Praefect トラッキングデータベースにレコードがまだ存在しないもの。

<duration> を期間(5s10m1hなど)に置き換えます。デフォルトは6hです。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-untracked-repositories -older-than <duration>

指定した期間より前に作成されたリポジトリのみが考慮されます。

コマンドは出力します:

  • 結果はSTDOUT とコマンドのログに。
  • エラーはSTDERR へ。

各エントリは完全な JSON 文字列で、最後に改行が入ります (-delimiter フラグで設定可能)。例えば

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-untracked-repositories
{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567890.git"}
{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567891.git"}

手動でリポジトリをトラッキングデータベースに追加します。

caution
既知のイシューのため、Praefectが生成したレプリカパス(@cluster)を持つリポジトリをPraefectトラッキングデータベースに追加することができません。これらのリポジトリはGitLabが使用するリポジトリパスに関連付けられておらず、アクセスできません。

track-repository Praefect サブコマンドは、ディスク上のリポジトリを追跡データベースに追加します。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage <virtual-storage> -authoritative-storage <storage-name> -relative-path <repository> -replica-path <disk_path> -replicate-immediately
  • -virtual-storage はリポジトリが置かれている仮想ストレージです。仮想ストレージはpraefect['configuration'][:virtual_storage] の下の/etc/gitlab/gitlab.rb に設定され、以下のようになります:

     praefect['configuration'] = {
       # ...
       virtual_storage: [
         {
           # ...
           name: 'default',
         },
         {
           # ...
           name: 'storage-1',
         },
       ],
     }
    

    この例では、指定する仮想ストレージはdefault またはstorage-1 です。

  • -relative-path は仮想ストレージ内の相対パスです。通常は@hashed](../repository_storage_types.md#hashed-storage)で始まる[を指定します。例えば

     @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
    
  • -replica-path は物理ストレージ上の相対パスです。@cluster で始まるか、relative_pathと一致します。
  • -authoritative-storage は、Praefect でプライマリとして扱いたいストレージです。レプリケーション戦略としてリポジトリ単位のレプリケーションが設定されている場合は必須です。
  • -replicate-immediatelyGitLab 14.6以降で使用可能なコマンドは、リポジトリをセカンダリに直ちにレプリケートします。それ以外の場合、レプリケーションジョブはデータベースで実行するようにスケジュールされ、Praefectのバックグラウンドプロセスによってピックアップされます。

コマンドは出力します:

  • 結果はSTDOUT とコマンドのログに出力されます。
  • エラーはSTDERR へ。

以下の場合、このコマンドは失敗します:

  • リポジトリが既に Praefect トラッキングデータベースで追跡されている場合。
  • リポジトリがディスク上に存在しません。

手動で多くのリポジトリを追跡データベースに追加してください。

GitLab 15.4で導入されました

caution
既知のイシューのため、Praefectが生成したレプリカパス(@cluster)を持つリポジトリをPraefectトラッキングデータベースに追加することができません。これらのリポジトリはGitLabが使用するリポジトリパスに関連付けられておらず、アクセスできません。

API を使用したマイグレーションでは、Praefect トラッキングデータベースにリポジトリが自動的に追加されます。

既存のインフラストラクチャから手動でリポジトリをコピーする場合は、track-repositories Praefectサブコマンドを使用できます。このサブコマンドを使用すると、ディスク上の大規模なリポジトリがPraefect追跡データベースに追加されます。

# Omnibus GitLab install
sudo gitlab-ctl praefect track-repositories --input-path /path/to/input.json

# Source install
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repositories -input-path /path/to/input.json

このコマンドは、すべてのエントリを検証します:

  • すべてのエントリが正しくフォーマットされ、必須フィールドが含まれていることを確認します。
  • ディスク上の有効な Git リポジトリに対応していること。
  • Praefect トラッキングデータベースでは追跡されません。

これらのチェックに失敗したエントリがある場合、コマンドはリポジトリの追跡を試みる前に中断します。

  • input-path は改行区切りのJSONオブジェクトとしてフォーマットされたリポジトリのリストを含むファイルへのパスです。オブジェクトには以下のキーを含める必要があります:
    • relative_path: はtrack-repositoryrepository に対応します。
    • authoritative-storageストレージPraefectは、プライマリとして扱うことです。
    • virtual-storageリポジトリが置かれている仮想ストレージ。

      使用例:

       {"relative_path":"@hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git","replica_path":"@cluster/fe/d3/1","authoritative_storage":"gitaly-1","virtual_storage":"default"}
       {"relative_path":"@hashed/f8/9f/f89f8d0e735a91c5269ab08d72fa27670d000e7561698d6e664e7b603f5c4e40.git","replica_path":"@cluster/7b/28/2","authoritative_storage":"gitaly-2","virtual_storage":"default"}
      
  • -replicate-immediatelyを指定すると、リポジトリが直ちにセカンダリにレプリケートされます。それ以外の場合、レプリケーションジョブはデータベースで実行するようにスケジュールされ、Praefectのバックグラウンドプロセスによってピックアップされます。

仮想ストレージの詳細を表示

GitLab 15.1で導入されました

list-storages Praefect サブコマンドは、仮想ストレージと関連するストレージノードを一覧表示します。仮想ストレージが

  • -virtual-storage指定された仮想ストレージのストレージノードのみを一覧表示します。
  • 指定しない場合は、すべての仮想ストレージと関連するストレージノードが表形式で一覧表示されます。
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-storages -virtual-storage <virtual_storage_name>

コマンドは出力します:

  • 結果はSTDOUT とコマンドのログに。
  • エラーはSTDERR へ。