Gitalyクラスタの設定

Gitaly Clusterの設定を行います:

小規模なGitLabインストールでは、Gitaly自身だけが必要かもしれません。

note
Gitaly ClusterはKubernetesやAmazon ECSなどのコンテナ環境ではまだサポートされていません。詳しくはエピック6127をご覧ください。

要件

Gitalyクラスタの最小推奨設定は以下の通りです:

  • 1 ロードバランサー
  • 1台のPostgreSQLサーバ(PostgreSQL 11以降)
  • 3ノード
  • 3つのGitalyノード(1プライマリ、2セカンダリノード)
note
ディスク要件はGitalyノードに適用されます。

Gitalyノードのうち1つが変異RPC呼び出しで失敗した場合にトランザクションがタイブレーカーを持つように、奇数数のGitalyノードを設定する必要があります。

実装の詳細については、設計ドキュメントを参照してください。

note
GitLabで設定されていない場合、機能フラグはコンソールからfalseとして読み込まれ、Praefectはそのデフォルト値を使用します。デフォルト値はGitLabのバージョンによって異なります。

ネットワーク遅延と接続性

クラスターのネットワークレイテンシは、一桁ミリ秒単位で測定できることが理想的です。レイテンシは特に次のような場合に重要です:

  • Gitalyノードのヘルスチェック。ノードは1秒またはそれよりも速く応答できなければなりません。
  • 強力な一貫性を強制する参照トランザクション。より低いレイテンシは、Gitalyノードがより速く変更に同意できることを意味します。

Gitalyノード間で許容可能なレイテンシを実現します:

  • 物理的なネットワークでは、一般的に高帯域幅の単一ロケーション接続を意味します。
  • クラウド上では、一般的に同じリージョン内を意味し、アベイラビリティ・ゾーンを越えたレプリケーションも可能です。これらのリンクは、このタイプの同期用に設計されています。Gitalyクラスタでは2ミリ秒以下のレイテンシで十分です。

レプリケーションのために低いネットワークレイテンシを提供できない場合(例えば、離れた場所間)、Geoを検討してください。詳しくは、Geoとの比較をご覧ください。

Gitaly Clusterのコンポーネントは、多くの経路で相互に通信します。Gitaly Clusterが正しく機能するためには、ファイアウォールのルールが以下を許可している必要があります:

よりデフォルトポートTLSポート
GitLabPraefect ロードバランサー23053305
Praefect ロードバランサーPraefect23053305
PraefectGitaly80759999
PraefectGitLab (内部API)80443
GitalyGitLab (内部API)80443
GitalyPraefect ロードバランサー23053305
GitalyPraefect23053305
GitalyGitaly80759999
note
GitalyはPraefectに直接接続しません。しかし、GitalyからPraefectロードバランサーへのリクエストは、PraefectノードのファイアウォールがGitalyノードからのトラフィックを許可しない限り、ブロックされる可能性があります。

Praefect データベースストレージ

データベースに格納されているのはメタデータだけなので、必要条件は比較的低い:

  • リポジトリがある場所。
  • いくつかのキューに入れられた作業。

リポジトリの数にもよりますが、GitLabアプリケーションのメインデータベースと同様、最低でも5~10GBが良いでしょう。

セットアップ手順

Linuxパッケージを使ってGitLabをインストールした場合(強く推奨します)は、以下の手順に従ってください:

  1. 準備
  2. Praefect データベースの設定
  3. Praefect プロキシ/ルーターの設定
  4. 各Gitalyノードの設定(各Gitalyノードに対して1回)
  5. ロードバランサーの設定
  6. GitLabサーバの設定更新
  7. Grafanaの設定

準備

始める前に、すでにGitLabインスタンスが動作している必要があります。GitLabのインストール方法を学びましょう。

PostgreSQLサーバーを準備します。Linuxパッケージに同梱されているPostgreSQLを使い、それを使ってPostgreSQLデータベースを設定する必要があります。外部のPostgreSQLサーバー(バージョン11以降)を使うこともできますが、手動で設定する必要があります。

GitLabをインストールして新しいノードを準備します。必要なのは

  • 1 PostgreSQLノード
  • 1つのPgBouncerノード(オプション)
  • 最低1台のPraefectノード(必要最小限のストレージ)
  • Gitalyノード3台(高CPU、高メモリ、高速ストレージ)
  • 1台のGitLabサーバー

各ノードのIP/ホストアドレスも必要です:

  1. PRAEFECT_LOADBALANCER_HOSTロードバランサーのIP/ホストアドレス
  2. POSTGRESQL_HOST: PostgreSQLサーバのIP/ホストアドレス
  3. PGBOUNCER_HOST: PostgreSQLサーバのIP/ホストアドレス
  4. PRAEFECT_HOST: PraefectサーバーのIP/ホストアドレス
  5. GITALY_HOST_*各GitalyサーバーのIPまたはホストアドレス
  6. GITLAB_HOST: GitLabサーバーのIP/ホストアドレス

Google Cloud PlatformやSoftLayerなど、仮想プライベートクラウドを提供しているベンダーを利用している場合(VPC) PRAEFECT_HOST ,GITALY_HOST_*,GITLAB_HOST には、各クラウドインスタンスの非公開アドレス(Google Cloud Platformの場合は「内部アドレス」に相当)を使うことができます。

シークレット

コンポーネント間の通信は、以下に説明する様々なシークレットによってセキュリティが確保されます。始める前に、それぞれにユニークなシークレットを生成し、メモしておいてください。これにより、セットアッププロセスを完了する際に、これらのプレースホルダートークンを安全なトークンに置き換えることができます。

  1. GITLAB_SHELL_SECRET_TOKENこれは、Gitプッシュを受け入れる際にGitLabにコールバックHTTP APIリクエストを行うGitフックによって使用されます。このシークレットはレガシーな理由からGitLab Shellと共有されます。
  2. PRAEFECT_EXTERNAL_TOKENクラスターでホストされているリポジトリは、このトークンを持つGitalyクライアントからのみアクセスできます。
  3. PRAEFECT_INTERNAL_TOKENこのトークンは、Praefectクラスター内のレプリケーション・トラフィックに使用されます。Gitalyクライアントは、Praefectクラスタの内部ノードに直接アクセスすることはできませんので、このトークンはPRAEFECT_EXTERNAL_TOKEN
  4. PRAEFECT_SQL_PASSWORDこのパスワードは、PostgreSQLへの接続に使用されます。
  5. PRAEFECT_SQL_PASSWORD_HASH: Praefectユーザーのパスワードのハッシュです。ハッシュの生成にはgitlab-ctl pg-password-md5 praefect を使用します。コマンドはpraefect ユーザーのパスワードを要求します。PRAEFECT_SQL_PASSWORD の平文パスワードを入力します。デフォルトでは、Praefect はpraefect ユーザーを使用しますが、変更することもできます。
  6. PGBOUNCER_SQL_PASSWORD_HASHPgBouncerユーザーのパスワードのハッシュを入力します。PgBouncerはこのパスワードを使ってPostgreSQLに接続します。詳細は同梱のPgBouncerドキュメントを参照してください。

これらのシークレットが必要な箇所は以下の説明の通りです。

note
Linux パッケージのインストールでは、gitlab-secrets.json forGITLAB_SHELL_SECRET_TOKEN を使用できます。

タイムサーバー設定のカスタマイズ

デフォルトでは、Gitaly および Praefect ノードは、時刻同期チェックにpool.ntp.org のタイムサーバーを使用します。各ノードのgitlab.rb に以下を追加することで、この設定をカスタマイズすることができます:

  • gitaly['env'] = { "NTP_HOST" => "ntp.example.com" }Gitaly ノードの場合。
  • praefect['env'] = { "NTP_HOST" => "ntp.example.com" }Praefectノード用。

PostgreSQL

note
Geoを使用する場合は、GitLabアプリケーションデータベースとPraefectデータベースを同じPostgreSQLサーバーに保存しないでください。レプリケーションの状態はGitLabの各インスタンス内部であり、レプリケートされるべきではありません。

これらの手順は、単一のPostgreSQLデータベースをセットアップするのに役立ちますが、これは単一障害点を作成します。これを避けるには、独自のクラスター化されたPostgreSQLを設定することができます。Linuxパッケージを使用したPostgreSQLのレプリケーションとフェイルオーバーのサポートはエピック7814で提案されています。他のデータベース(例えば、PraefectやGeoデータベース)に対するクラスター化データベースのサポートはイシュー7292で提案されています。

以下のオプションが利用できます:

  • Geo 以外のインストールには、以下のいずれかを選択します:
    • ドキュメントに記載されているPostgreSQL セットアップのいずれかを使用します。
    • 独自のサードパーティデータベースのセットアップを使用してください。手動で設定する必要があります。
  • Geoインスタンスでは、以下のいずれかを行います:

PostgreSQLを設定すると、空のPraefectテーブルが作成されます。詳細については、関連するトラブルシューティングのセクションを参照してください。

同じサーバー上でGitLabとPraefectデータベースを実行する場合

GitLabアプリケーションデータベースとPraefectデータベースは、同じサーバー上で実行することができます。ただし、LinuxパッケージのPostgreSQLを使用する場合、Praefectは独自のデータベースサーバーを持つ必要があります。フェイルオーバーが発生した場合、Praefectはそれに気づかず、使用しようとしているデータベースがフェイルオーバーすることになります:

  • 使用できません。
  • 読み取り専用モード。

手動データベース設定

このセクションを完了するには

  • 1つのPraefectノード
  • PostgreSQLノード1台(バージョン11以降)
    • データベースサーバを管理する権限を持つPostgreSQLユーザー

このセクションでは、PostgreSQLデータベースの設定を行います。これは外部PostgreSQLサーバでもLinuxパッケージ提供のPostgreSQLサーバでも使用できます。

以下の手順を実行するには、Linux パッケージ (/opt/gitlab/embedded/bin/psql) によってpsql がインストールされている Praefect ノードを使用できます。Linuxパッケージ提供のPostgreSQLを使用している場合は、代わりにPostgreSQLノードでgitlab-psql

  1. Praefect で使用する新しいユーザーpraefect を作成します:

    CREATE ROLE praefect WITH LOGIN PASSWORD 'PRAEFECT_SQL_PASSWORD';
    

    PRAEFECT_SQL_PASSWORD を準備のステップで作成した強力なパスワードに置き換えます。

  2. praefect ユーザーが所有する新しいデータベースpraefect_production を作成します。

    CREATE DATABASE praefect_production WITH OWNER praefect ENCODING UTF8;
    

Linuxパッケージが提供するPgBouncerを使用する場合、以下の追加手順が必要です。Linuxパッケージに同梱されているPostgreSQLをバックエンドとして使用することを強く推奨します。以下の手順はLinuxパッケージ付属のPostgreSQLでのみ動作します:

  1. Linuxパッケージ提供のPgBouncerの場合、実際のパスワードの代わりにpraefect パスワードのハッシュ値を使用する必要があります:

    ALTER ROLE praefect WITH PASSWORD 'md5<PRAEFECT_SQL_PASSWORD_HASH>';
    

    <PRAEFECT_SQL_PASSWORD_HASH> を準備ステップで生成したパスワードのハッシュに置き換えてください。md5 リテラルが先頭に付きます。

  2. Linuxパッケージに同梱されているPgBouncerはauth_querypg_shadow_lookup 関数を使用するように設定されています。この関数をpraefect_production データベースに作成する必要があります:

    CREATE OR REPLACE FUNCTION public.pg_shadow_lookup(in i_username text, out username text, out password text) RETURNS record AS $$
    BEGIN
        SELECT usename, passwd FROM pg_catalog.pg_shadow
        WHERE usename = i_username INTO username, password;
        RETURN;
    END;
    $$ LANGUAGE plpgsql SECURITY DEFINER;
       
    REVOKE ALL ON FUNCTION public.pg_shadow_lookup(text) FROM public, pgbouncer;
    GRANT EXECUTE ON FUNCTION public.pg_shadow_lookup(text) TO pgbouncer;
    

これでPraefectが使用するデータベースの設定は完了です。

これで、Praefectがデータベースを使用するように設定できます:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      host: POSTGRESQL_HOST,
      port: 5432,
      password: PRAEFECT_SQL_PASSWORD,
      dbname: 'praefect_production',
   }
}

PostgreSQLの設定後にPraefectデータベースエラーが表示された場合は、トラブルシューティング手順を参照してください。

ディストリビューションキャッシュの読み込み

Praefectのパフォーマンスは、database_direct の設定を追加することで向上します:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      session_pooled: {
         # ...
         host: POSTGRESQL_HOST,
         port: 5432

         # Use the following to override parameters of direct database connection.
         # Comment out where the parameters are the same for both connections.
         user: 'praefect',
         password: PRAEFECT_SQL_PASSWORD,
         dbname: 'praefect_production',
         # sslmode: '...',
         # sslcert: '...',
         # sslkey: '...',
         # sslrootcert: '...',
      }
   }
}

設定すると、この接続はSQL LISTEN機能に自動的に使用され、PostgreSQLからキャッシュ無効化の通知をPraefectが受信できるようになります。

この機能が動作しているかどうかは、Praefectのログで次のログエントリを確認してください:

reads distribution caching is enabled by configuration

PgBouncerを使用

PostgreSQLリソースの消費を抑えるには、PostgreSQLインスタンスの前にPgBouncerを設定する必要があります。しかし、Pregrefectは接続数が少ないため、PgBouncerは必要ありません。PgBouncerを使用する場合は、GitLabアプリケーションデータベースとPraefectデータベースの両方に同じPgBouncerインスタンスを使用できます。

PostgreSQLインスタンスの前にPgBouncerを設定するには、Praefectの設定でデータベースパラメータを設定してPgBouncerにPraefectを向ける必要があります:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      host: PGBOUNCER_HOST,
      port: 6432,
      user: 'praefect',
      password: PRAEFECT_SQL_PASSWORD,
      dbname: 'praefect_production',
      # sslmode: '...',
      # sslcert: '...',
      # sslkey: '...',
      # sslrootcert: '...',
   }
}

Playfectは、LISTEN機能をサポートするPostgreSQLへの追加接続を必要とします。PgBouncerでは、この機能はsession プールモード(pool_mode = session )でのみ使用できます。transaction プールモード (pool_mode = transaction) ではサポートされていません。

追加接続を設定するには、以下のどちらかを行う必要があります:

  • 同じPostgreSQLデータベースのエンドポイントを使用する新しいPgBouncerデータベースを設定しますが、プールモードは異なります(pool_mode = session)。
  • Playfectを直接PostgreSQLに接続し、PgBouncerをバイパスします。

新しいPgBouncerデータベースを次のように設定します。pool_mode = session

session プールモードでPgBouncerを使用する必要があります。同梱のPgBouncerを使用するか、外部のPgBouncerを使用して手動で設定します。

以下の例では、同梱のPgBouncerを使用し、PostgreSQLホスト上で2つの別々の接続プールを設定します(1つはsession プールモードで、もう1つはtransaction プールモードです)。この例を動作させるためには、PostgreSQLサーバを準備する必要があります

pgbouncer['databases'] = {
  # Other database configuration including gitlabhq_production
  ...

  praefect_production: {
    host: POSTGRESQL_HOST,
    # Use `pgbouncer` user to connect to database backend.
    user: 'pgbouncer',
    password: PGBOUNCER_SQL_PASSWORD_HASH,
    pool_mode: 'transaction'
  },
  praefect_production_direct: {
    host: POSTGRESQL_HOST,
    # Use `pgbouncer` user to connect to database backend.
    user: 'pgbouncer',
    password: PGBOUNCER_SQL_PASSWORD_HASH,
    dbname: 'praefect_production',
    pool_mode: 'session'
  },

  ...
}

# Allow the praefect user to connect to PgBouncer
pgbouncer['users'] = {
  'praefect': {
    'password': PRAEFECT_SQL_PASSWORD_HASH,
  }
}

praefect_productionpraefect_production_direct は同じデータベースエンドポイント (praefect_production) を使用しますが、プールモードは異なります。これは、PgBouncerの以下のdatabases セクションに変換されます:

[databases]
praefect_production = host=POSTGRESQL_HOST auth_user=pgbouncer pool_mode=transaction
praefect_production_direct = host=POSTGRESQL_HOST auth_user=pgbouncer dbname=praefect_production pool_mode=session

これで、両方の接続でPgBouncerを使用するようにPraefectを設定できます:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      host: PGBOUNCER_HOST,
      port: 6432,
      user: 'praefect',
      # `PRAEFECT_SQL_PASSWORD` is the plain-text password of
      # Praefect user. Not to be confused with `PRAEFECT_SQL_PASSWORD_HASH`.
      password: PRAEFECT_SQL_PASSWORD,
      dbname: 'praefect_production',
      session_pooled: {
         # ...
         dbname: 'praefect_production_direct',
         # There is no need to repeat the following. Parameters of direct
         # database connection will fall back to the values above.
         #
         # host: PGBOUNCER_HOST,
         # port: 6432,
         # user: 'praefect',
         # password: PRAEFECT_SQL_PASSWORD,
      },
   },
}

この設定により、Praefectは両方の接続タイプでPgBouncerを使用します。

note
Linux パッケージインストールは認証要件を処理します(auth_query を使用)が、手動でデータベースを準備し、外部の PgBouncer を設定する場合は、PgBouncer が使用するファイルにpraefect ユーザーとそのパスワードを含める必要があります。例えば、userlist.txtauth_file設定オプションが設定されています。詳細はPgBouncerのドキュメントを参照してください。

PostgreSQLに直接接続するようにPraefectを設定します。

session プールモードでPgBouncerを設定する代わりに、PostgreSQLに直接アクセスするために異なる接続パラメータを使用するようにPraefectを設定することができます。この接続は、LISTEN 機能をサポートしています。

PgBouncerをバイパスしてPostgreSQLに直接接続するPraefectの設定例:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      session_pooled: {
         # ...
         host: POSTGRESQL_HOST,
         port: 5432,

         # Use the following to override parameters of direct database connection.
         # Comment out where the parameters are the same for both connections.
         #
         user: 'praefect',
         password: PRAEFECT_SQL_PASSWORD,
         dbname: 'praefect_production',
         # sslmode: '...',
         # sslcert: '...',
         # sslkey: '...',
         # sslrootcert: '...',
      },
   },
}

Praefect

GitLab 13.4で導入されたPraefectノードは、primary として指定することができなくなりました。

複数のPraefectノードがある場合:

  1. 1つのノードをデプロイノードとして指定し、次の手順で設定します。
  2. 追加の各ノードについて、以下の手順を実行します。

このセクションを完了するには、以下を含むPostgreSQLサーバの設定が必要です:

caution
Playfectは専用ノードで実行してください。アプリケーションサーバーやGitalyノードでPraefectを実行しないでください。

Praefectノード上:

  1. /etc/gitlab/gitlab.rb を編集して、他のすべてのサービスを無効にします:
# Avoid running unnecessary services on the Praefect server
gitaly['enable'] = false
postgresql['enable'] = false
redis['enable'] = false
nginx['enable'] = false
puma['enable'] = false
sidekiq['enable'] = false
gitlab_workhorse['enable'] = false
prometheus['enable'] = false
alertmanager['enable'] = false
grafana['enable'] = false
gitlab_exporter['enable'] = false
gitlab_kas['enable'] = false

# Enable only the Praefect service
praefect['enable'] = true

# Prevent database migrations from running on upgrade automatically
praefect['auto_migrate'] = false
gitlab_rails['auto_migrate'] = false
  1. /etc/gitlab/gitlab.rbを編集して、Praefectがネットワークインターフェイスをリッスンするように設定します:

    praefect['configuration'] = {
       # ...
       listen_addr: '0.0.0.0:2305',
    }
    
  2. /etc/gitlab/gitlab.rb を編集して Prometheus のメトリクスを設定します:

    praefect['configuration'] = {
       # ...
       #
       # Enable Prometheus metrics access to Praefect. You must use firewalls
       # to restrict access to this address/port.
       # The default metrics endpoint is /metrics
       prometheus_listen_addr: '0.0.0.0:9652',
       # Some metrics run queries against the database. Enabling separate database metrics allows
       # these metrics to be collected when the metrics are
       # scraped on a separate /db_metrics endpoint.
       prometheus_exclude_database_from_default_metrics: true,
    }
    
  3. /etc/gitlab/gitlab.rbクラスタ外部のクライアント(GitLab Shellなど)がPraefectクラスタと通信するために必要です:

    praefect['configuration'] = {
       # ...
       auth: {
          # ...
          token: 'PRAEFECT_EXTERNAL_TOKEN',
       },
    }
    
  4. PostgreSQLデータベースに接続するようにPraefectを設定します。PgBouncer の使用も強くお勧めします。

    TLSクライアント証明書を使用する場合は、以下のオプションを使用できます:

    praefect['configuration'] = {
       # ...
       database: {
          # ...
          #
          # Connect to PostgreSQL using a TLS client certificate
          # sslcert: '/path/to/client-cert',
          # sslkey: '/path/to/client-key',
          #
          # Trust a custom certificate authority
          # sslrootcert: '/path/to/rootcert',
       },
    }
    

    デフォルトでは、Playfectは暗号化されていないPostgreSQLへの接続を拒否します。以下の行のコメントを解除すると、これをオーバーライドできます:

    praefect['configuration'] = {
       # ...
       database: {
          # ...
          # sslmode: 'disable',
       },
    }
    
  5. /etc/gitlab/gitlab.rb を編集して、クラスター内の各Gitalyノードに接続するようにPraefectクラスターを設定します。

    仮想ストレージの名前は、GitLab設定で設定したストレージ名と一致している必要があります。後のステップで、ストレージ名を設定default しますので、 defaultここでもdefault 同様に使用 defaultします。このクラスターには3つのGitalyノードgitaly-1,gitaly-2,gitaly-3 があり、これらは互いのレプリカとなることを想定しています。

    caution
    default という既に存在するストレージにデータがある場合は、別の名前で仮想ストレージを設定し、その後Gitalyクラスタストレージにデータをマイグレーションする必要があります。

    PRAEFECT_INTERNAL_TOKEN を、クラスター内の Gitaly ノードと通信する際に Praefect が使用する強力なシークレットに置き換えます。このトークンは、PRAEFECT_EXTERNAL_TOKEN とは異なります。

    GITALY_HOST_* を各 Gitaly ノードの IP アドレスまたはホストアドレスに置き換えます。

    クラスターにGitalyノードを追加してレプリカの数を増やすことができます。また、非常に大規模なGitLabインスタンスのためにクラスターを追加することもできます。

    note
    仮想ストレージにGitalyノードを追加する場合、その仮想ストレージ内のすべてのストレージ名は一意でなければなりません。さらに、Praefect設定で参照するGitalyノードのアドレスはすべて一意である必要があります。
    # Name of storage hash must match storage name in git_data_dirs on GitLab
    # server ('default') and in gitaly['configuration'][:storage][INDEX][:name] on Gitaly nodes ('gitaly-1')
    praefect['configuration'] = {
       # ...
       virtual_storage: [
          {
             # ...
             name: 'default',
             node: [
                {
                   storage: 'gitaly-1',
                   address: 'tcp://GITALY_HOST_1:8075',
                   token: 'PRAEFECT_INTERNAL_TOKEN'
                },
                {
                   storage: 'gitaly-2',
                   address: 'tcp://GITALY_HOST_2:8075',
                   token: 'PRAEFECT_INTERNAL_TOKEN'
                },
                {
                   storage: 'gitaly-3',
                   address: 'tcp://GITALY_HOST_3:8075',
                   token: 'PRAEFECT_INTERNAL_TOKEN'
                },
             ],
          },
       ],
    }
    
  6. /etc/gitlab/gitlab.rb に変更を保存し、Prafect を再設定します:

    gitlab-ctl reconfigure
    
  7. 使用例:

    • デプロイ・ノード」:
      1. /etc/gitlab/gitlab.rbpraefect['auto_migrate'] = true を設定して、Praefect データベースの自動マイグレーションを再度有効にします。
      2. データベースのマイグレーションがアップグレード時に自動的に実行されず、再設定時にのみ実行されるようにするには、以下を実行します:

        sudo touch /etc/gitlab/skip-auto-reconfigure
        
    • 他のノードの設定はそのままで大丈夫です。/etc/gitlab/skip-auto-reconfigure は必須ではありませんが、apt-get update のようなコマンドを実行するときに GitLab が自動的に reconfigure を実行しないように設定しておくとよいでしょう。こうすることで、追加の設定変更を行ってから手動で reconfigure を実行することができます。
  8. /etc/gitlab/gitlab.rb に変更を保存し、Prafect を再設定します:

    gitlab-ctl reconfigure
    
  9. Promefectのリスンアドレスが更新されたことを確認するために、Promefectを再起動します:

    gitlab-ctl restart praefect
    
  10. PraefectがPostgreSQLにアクセスできることを確認します:

    sudo -u git /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-ping
    

    チェックに失敗した場合は、手順が正しいことを確認してください。/etc/gitlab/gitlab.rbを編集した場合は、sql-ping コマンドを試す前に、sudo gitlab-ctl reconfigure を再度実行することを忘れないでください。

TLSサポートを有効にします

PraefectはTLS暗号化をサポートしています。セキュアな接続をリッスンするPraefectインスタンスと通信するには、以下が必要です:

  • GitalyがTLS用に設定されていることを確認し、GitLab設定の対応するストレージエントリのgitaly_addresstls:// URLスキームを使用します。
  • 証明書は自動的には提供されないため、各自でご用意ください。各 Praefect サーバーに対応する証明書をインストールする必要があります。

さらに、証明書、またはその作成者は、GitLabカスタム証明書設定で説明されている手順に従って、すべてのGitalyサーバーとそれと通信するすべてのPraefectクライアントにインストールする必要があります(以下も同様)。

以下に注意してください。

  • 証明書には、Praefect サーバーへのアクセスに使用するアドレスを指定する必要があります。ホスト名または IP アドレスを証明書のサブジェクト代替名として追加する必要があります。
  • Gitaly TLS を有効にした状態で、コマンドラインからdial-nodeslist-untracked-repositories などの Praefect サブコマンドを実行する場合は、Gitaly 証明書が信頼されるようにSSL_CERT_DIR またはSSL_CERT_FILE 環境変数を設定する必要があります。たとえば、次のようになります:

     sudo SSL_CERT_DIR=/etc/gitlab/trusted-certs /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
    
  • 暗号化されていないリスニングアドレスlisten_addr と暗号化されたリスニングアドレスtls_listen_addr の両方を持つ Praefect サーバーを同時に設定できます。これにより、必要に応じて、暗号化されていないトラフィックから暗号化されたトラフィックに徐々に移行することができます。

    暗号化されていないリスナーを無効にするには、次のように設定します:

     praefect['configuration'] = {
       # ...
       listen_addr: nil,
     }
    

TLSでPraefectを設定します。

Linuxパッケージ・インストールの場合:

  1. Praefectサーバー用の証明書を作成します。

  2. Praefect サーバーで、/etc/gitlab/ssl ディレクトリを作成し、そこに鍵と証明書をコピーします:

    sudo mkdir -p /etc/gitlab/ssl
    sudo chmod 755 /etc/gitlab/ssl
    sudo cp key.pem cert.pem /etc/gitlab/ssl/
    sudo chmod 644 key.pem cert.pem
    
  3. /etc/gitlab/gitlab.rb を編集し、追加してください:

    praefect['configuration'] = {
       # ...
       tls_listen_addr: '0.0.0.0:3305',
       tls: {
          # ...
          certificate_path: '/etc/gitlab/ssl/cert.pem',
          key_path: '/etc/gitlab/ssl/key.pem',
       },
    }
    
  4. ファイルを保存して再設定してください。

  5. Praefectクライアント(各Gitalyサーバーを含む)で、証明書またはその作成者を/etc/gitlab/trusted-certs にコピーします:

    sudo cp cert.pem /etc/gitlab/trusted-certs/
    
  6. Praefectクライアント(Gitalyサーバーを除く)で、/etc/gitlab/gitlab.rbgit_data_dirs を以下のように編集します:

    git_data_dirs({
      "default" => {
        "gitaly_address" => 'tls://PRAEFECT_LOADBALANCER_HOST:3305',
        "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    })
    
  7. ファイルを保存し、GitLabを再設定してください。

セルフコンパイルによるインストールの場合:

  1. Praefectサーバー用の証明書を作成します。
  2. Praefect サーバーで、/etc/gitlab/ssl ディレクトリを作成し、そこに鍵と証明書をコピーします:

    sudo mkdir -p /etc/gitlab/ssl
    sudo chmod 755 /etc/gitlab/ssl
    sudo cp key.pem cert.pem /etc/gitlab/ssl/
    sudo chmod 644 key.pem cert.pem
    
  3. Praefectクライアント(各Gitalyサーバーを含む)上で、証明書またはその作成者をシステムの信頼済み証明書にコピーします:

    sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt
    sudo update-ca-certificates
    
  4. Praefectクライアント(Gitalyサーバーを除く)で、/home/git/gitlab/config/gitlab.ymlstorages を以下のように編集します:

    gitlab:
      repositories:
        storages:
          default:
            gitaly_address: tls://PRAEFECT_LOADBALANCER_HOST:3305
            path: /some/local/path
    
    note
    /some/local/path は、存在するローカルフォルダに設定する必要がありますが、このフォルダにはデータは保存されません。この要件は、このイシューが解決された時点で削除される予定です。
  5. ファイルを保存し、GitLabを再起動します。
  6. すべてのPraefectサーバー証明書、またはその作成者を、各Gitalyサーバーのシステム信頼済み証明書にコピーし、Gitalyサーバーから呼び出されたときにPraefectサーバーが証明書を信頼するようにします:

    sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt
    sudo update-ca-certificates
    
  7. /home/git/praefect/config.toml を編集し、追加してください:

    tls_listen_addr = '0.0.0.0:3305'
       
    [tls]
    certificate_path = '/etc/gitlab/ssl/cert.pem'
    key_path = '/etc/gitlab/ssl/key.pem'
    
  8. ファイルを保存し、GitLabを再起動します。

サービス発見

GitLab 15.10 で導入されました

前提条件:

  • DNSサーバー。

GitLabはサービス・ディスカバリーを使用してPraefectホストのリストを取得します。サービス・ディスカバリーでは、DNS AレコードまたはAAAAレコードを定期的にチェックし、レコードから取得したIPを対象ノードのアドレスとして使用します。Praefectは、SRVレコードによるサービスディスカバリーをサポートしていません。

デフォルトでは、レコードのTTLに関係なく、チェック間の最短時間は5分です。Praefectでは、この間隔のカスタマイズには対応していません。クライアントが更新を受信すると

  • 新しいIPアドレスへの新しい接続を確立します。
  • 既存のIPアドレスへの接続はそのまま維持します。
  • 削除されたIPアドレスへの接続を削除します。

削除される予定のコネクションへのインフライトリクエストは、 終了するまで処理されます。Workhorse には 10 分のタイムアウトがありますが、 他のクライアントでは猶予のあるタイムアウトは指定されていません。

DNSサーバはそれ自身を負荷分散する代わりに、すべてのIPアドレスを返すべきです。クライアントはリクエストをラウンドロビン方式で IP アドレスにディストリビューションできます。

クライアント設定を更新する前に、DNSサービス検出が正しく機能していることを確認してください。IPアドレスのリストが正しく返されるはずです。dig を検証するのに使用するとよいツールです。

❯ dig A praefect.service.consul @127.0.0.1

; <<>> DiG 9.10.6 <<>> A praefect.service.consul @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29210
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;praefect.service.consul.                     IN      A

;; ANSWER SECTION:
praefect.service.consul.              0       IN      A       10.0.0.3
praefect.service.consul.              0       IN      A       10.0.0.2
praefect.service.consul.              0       IN      A       10.0.0.1

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Wed Dec 14 12:53:58 +07 2022
;; MSG SIZE  rcvd: 86
サービス発見の設定

デフォルトでは、PraefectはDNS解決をオペレーションシステムに委譲します。この場合、Gitalyアドレスは以下のいずれかの形式で設定できます:

  • dns:[host]:[port]
  • dns:///[host]:[port] (3つのスラッシュに注意してください)

この形式で設定することで、権威ネームサーバーを指定することもできます:

  • dns://[authority_host]:[authority_port]/[host]:[port]
Linux package (Omnibus)
  1. /etc/gitlab/gitlab.rb を編集し、追加してください:

    praefect['consul_service_name'] = 'praefect'
    
  2. ファイルを保存して再設定してください。
  3. Praefect クライアント(Gitaly サーバーを除く)で、/etc/gitlab/gitlab.rbgit_data_dirs を次のように編集します。PRAEFECT_SERVICE_DISCOVERY_ADDRESS を、praefect.service.consulのような Praefect サービス発見アドレスに置き換えます。

    git_data_dirs({
      "default" => {
        "gitaly_address" => 'dns:PRAEFECT_SERVICE_DISCOVERY_ADDRESS:2305',
        "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    })
    
  4. ファイルを保存し、GitLabを再設定してください。
Self-compiled (source)
  1. DNSサービス検出サービスをインストールします。すべてのPraefectノードをサービスに登録します。
  2. Praefectクライアント(Gitalyサーバーを除く)で、/home/git/gitlab/config/gitlab.ymlstorages を以下のように編集します:

    gitlab:
      repositories:
        storages:
          default:
            gitaly_address: dns:PRAEFECT_SERVICE_DISCOVERY_ADDRESS:2305
            path: /some/local/path
    
    note
    /some/local/path は存在するローカルフォルダーに設定されるべきですが、このフォルダーにはデータは保存されません。イシュー375254は、この要件を削除することを提案しています。
  3. ファイルを保存し、GitLabを再起動します。

Gitaly

note
各Gitalyノードについて、以下のステップを完了してください。

このセクションを完了するには

  • 設定済みのPraefectノード
  • GitLabがインストールされた、Gitalyノードとして設定する3台(またはそれ以上)のサーバー。これらのノードは専用ノードである必要があり、これらのノード上で他のサービスを実行しないでください。

クラスターに割り当てられたすべてのGitalyサーバーを設定する必要があります。設定は、標準的なスタンドアロンのGitalyサーバーと同じです:

  • ストレージ名はGitLabではなくPraefectに公開されます。
  • シークレットトークンはGitLabではなくPraefectと共有されます。

オペレーションを正しくルーティングするためにPraefectに依存しているため、Praefectクラスター内のすべてのGitalyノードの設定は同一にすることができます。

特に注意が必要なのは

  • このセクションで設定するgitaly['configuration'][:auth][:token] は、Praefect ノードのpraefect['configuration'][:virtual_storage][<index>][:node][<index>][:token] の下にあるtoken の値と一致している必要があります。この値は前のセクションで設定しました。このドキュメントでは、PRAEFECT_INTERNAL_TOKEN というプレースホルダを内部で使用します。
  • このセクションで設定するgitaly['configuration'][:storage] の物理ストレージ名は、Praefect ノードのpraefect['configuration'][:virtual_storage] の物理ストレージ名と一致する必要があります。これは前のセクションで設定しました。このドキュメントでは、物理ストレージ名としてgitaly-1gitaly-2gitaly-3 を使用します。

Gitaly サーバー設定の詳細については、Gitaly ドキュメントを参照してください。

  1. GitalyノードにSSH接続し、rootでログインします:

    sudo -i
    
  2. /etc/gitlab/gitlab.rb を編集して、他のすべてのサービスを無効にします:

    # Disable all other services on the Gitaly node
    postgresql['enable'] = false
    redis['enable'] = false
    nginx['enable'] = false
    grafana['enable'] = false
    puma['enable'] = false
    sidekiq['enable'] = false
    gitlab_workhorse['enable'] = false
    prometheus_monitoring['enable'] = false
    gitlab_kas['enable'] = false
       
    # Enable only the Gitaly service
    gitaly['enable'] = true
       
    # Enable Prometheus if needed
    prometheus['enable'] = true
       
    # Disable database migrations to prevent database connections during 'gitlab-ctl reconfigure'
    gitlab_rails['auto_migrate'] = false
    
  3. /etc/gitlab/gitlab.rbを編集して、Gitalyがネットワークインターフェイスをリッスンするように設定します:

    gitaly['configuration'] = {
       # ...
       #
       # Make Gitaly accept connections on all network interfaces.
       # Use firewalls to restrict access to this address/port.
       listen_addr: '0.0.0.0:8075',
       # Enable Prometheus metrics access to Gitaly. You must use firewalls
       # to restrict access to this address/port.
       prometheus_listen_addr: '0.0.0.0:9236',
    }
    
  4. /etc/gitlab/gitlab.rbクライアントがGitalyノードと通信するために必要な強力なauth_token を設定します。通常、このトークンはすべてのGitalyノードで同じです。

    gitaly['configuration'] = {
       # ...
       auth: {
          # ...
          token: 'PRAEFECT_INTERNAL_TOKEN',
       },
    }
    
  5. git push のオペレーションに必要な GitLab Shell シークレットトークンを設定します。どちらかです:

    • 方法 1:

      1. /etc/gitlab/gitlab-secrets.json をGitalyクライアントからGitalyサーバーと他のGitalyクライアントの同じパスにコピーします。
      2. Gitalyサーバー上でGitLabを再設定します。
    • 方法2:

      1. /etc/gitlab/gitlab.rbを編集します。
      2. GITLAB_SHELL_SECRET_TOKEN を本当のシークレットに置き換えてください。

        gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
        
  6. git push のオペレーションにも必要なinternal_api_url を設定します:

    # Configure the gitlab-shell API callback URL. Without this, `git push` will
    # fail. This can be your front door GitLab URL or an internal load balancer.
    # Examples: 'https://gitlab.example.com', 'http://10.0.2.2'
    gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
    
  7. /etc/gitlab/gitlab.rbgitaly['configuration'][:storage] を設定して、Gitデータの保存場所を設定します。各Gitalyノードは、ユニークなストレージ名(gitaly-1 など)を持つ必要があります。

    各 Gitaly ノードに対してgitaly['configuration'][:storage] を一意に設定する代わりに、すべての Gitaly ノードに対する設定をすべての Gitaly ノードに含める方が簡単な場合があります。なぜなら、Praefectvirtual_storage 設定は、各ストレージ名(gitaly-1 など)を特定のノードにマッピングし、リクエストはそれに応じてルーティングされるからです。これは、フリート内のすべてのGitalyノードが同じ設定を共有できることを意味します。

    # You can include the data dirs for all nodes in the same config, because
    # Praefect will only route requests according to the addresses provided in the
    # prior step.
    gitaly['configuration'] = {
       # ...
       storage: [
         {
           name: 'gitaly-1',
           path: '/var/opt/gitlab/git-data',
         },
         {
           name: 'gitaly-2',
           path: '/var/opt/gitlab/git-data',
         },
         {
           name: 'gitaly-3',
           path: '/var/opt/gitlab/git-data',
         },
       ],
    }
    
  8. /etc/gitlab/gitlab.rb に変更を保存し、Gitaly を再設定します:

    gitlab-ctl reconfigure
    
  9. GitalyがPrometheusのリスンアドレスを更新したことを確認するために、Gitalyを再起動します:

    gitlab-ctl restart gitaly
    

上記の手順は、各Gitalyノードで完了する必要があります!

すべてのGitalyノードの設定が完了したら、Praefect接続チェッカーを実行し、Praefect設定内のすべてのGitalyサーバーにPraefectが接続できることを確認します。

  1. 各PraefectノードにSSH接続し、Praefect接続チェッカーを実行します:

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

ロードバランサ

フォールト・トレラントなGitaly設定では、GitLabアプリケーションからPraefectノードへの内部トラフィックをルーティングするためにロード・バランサーが必要です。どのロードバランサーを使用するか、または正確な設定についての詳細は、GitLabドキュメントの範囲を超えています。

note
ロードバランサーは、GitLabノードに加えてGitalyノードからのトラフィックを受け入れるように設定する必要があります。

GitLabのようなフォールト・トレラントなシステムを管理しているのであれば、すでにロード・バランサーを選択していることを望みます。例えば、HAProxy(オープンソース)、Google Internal Load BalancerAWS Elastic Load Balancer、F5 Big-IP LTM、Citrix Net Scalerなどがあります。この設定資料では、設定する必要があるポートとプロトコルの概要を説明しています。

note
HAProxyleastconn に相当するロードバランシング戦略を使用する必要があります。
LBポートバックエンドポートプロトコル
23052305TCP

GitLab

このセクションを完了するには

PraefectクラスターをGitLabアプリケーションのストレージとして公開する必要があります。これはgit_data_dirs.

特に注意が必要なのは

  • このセクションでgit_data_dirs に追加されたストレージ名は、Praefect ノードのpraefect['configuration'][:virtual_storage] のストレージ名と一致している必要があります。これは、このガイドのPraefectセクションで設定されています。本書では、default を Praefect ストレージ名として使用します。
  1. GitLabノードにSSHし、rootでログインします:

    sudo -i
    
  2. /etc/gitlab/gitlab.rb を編集して、適切なエンドポイントアクセスによってファイルがGitLabから提供されるようにexternal_url を設定します:

    GITLAB_SERVER_URL 、現在のGitLabインスタンスがサービスを提供している実際の外部向けURLに置き換える必要があります:

    external_url 'GITLAB_SERVER_URL'
    
  3. GitLabホスト上で稼働しているデフォルトのGitalyサービスを無効にします。GitLabは設定されたクラスターに接続するので、それは必要ありません。

    caution
    デフォルトのGitalyストレージに既存のデータが保存されている場合は、まずGitaly Clusterストレージにデータをマイグレーションしてください。
    gitaly['enable'] = false
    
  4. /etc/gitlab/gitlab.rb を編集して、Praefect クラスターをストレージの場所として追加します。

    置き換える必要があります:

    • PRAEFECT_LOADBALANCER_HOST をロードバランサの IP アドレスかホスト名に置き換える必要があります。
    • PRAEFECT_EXTERNAL_TOKEN を本当のシークレットで指定します。

    TLSを使用している場合:

    • gitaly_address の代わりにtls:// で始める必要があります。
    • ポートは3305 に変更すべきです。
    git_data_dirs({
      "default" => {
        "gitaly_address" => "tcp://PRAEFECT_LOADBALANCER_HOST:2305",
        "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    })
    
  5. git push 中に Gitaly ノードからのコールバックが適切に認証されるように GitLab Shell シークレットトークンを設定します。どちらかです:

    • 方法 1:

      1. /etc/gitlab/gitlab-secrets.json をGitalyクライアントからGitalyサーバーと他のGitalyクライアントの同じパスにコピーします。
      2. Gitalyサーバー上でGitLabを再設定します。
    • 方法2:

      1. /etc/gitlab/gitlab.rbを編集します。
      2. GITLAB_SHELL_SECRET_TOKEN を本当のシークレットに置き換えてください。

        gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
        
  6. /etc/gitlab/gitlab.rb を編集して Prometheus モニタリング設定を追加します。Prometheusが別のノードで有効になっている場合は、代わりにそのノードで編集してください。

    置き換える必要があります:

    • PRAEFECT_HOST を Praefect ノードの IP アドレスまたはホスト名に置き換える必要があります。
    • GITALY_HOST_* 各GitalyノードのIPアドレスまたはホスト名を含む
    prometheus['scrape_configs'] = [
      {
        'job_name' => 'praefect',
        'static_configs' => [
          'targets' => [
            'PRAEFECT_HOST:9652', # praefect-1
            'PRAEFECT_HOST:9652', # praefect-2
            'PRAEFECT_HOST:9652', # praefect-3
          ]
        ]
      },
      {
        'job_name' => 'praefect-gitaly',
        'static_configs' => [
          'targets' => [
            'GITALY_HOST_1:9236', # gitaly-1
            'GITALY_HOST_2:9236', # gitaly-2
            'GITALY_HOST_3:9236', # gitaly-3
          ]
        ]
      }
    ]
    
  7. /etc/gitlab/gitlab.rb に変更を保存し、GitLabを再設定します:

    gitlab-ctl reconfigure
    
  8. 各GitalyノードでGit HooksがGitLabに到達できることを確認します。各Gitalyノードで実行してください:
    • GitLab 15.3以降では、sudo /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml.
    • GitLab 15.2 以前については、sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml を実行してください。
  9. GitLabがPraefectにアクセスできることを確認します:

    gitlab-rake gitlab:gitaly:check
    
  10. Praefectストレージが新しいリポジトリを保存するように設定されていることを確認します:

    1. 左のサイドバーで、Search を選択するか、次のページに進んでください。
    2. Admin Areaを選択します。
    3. 左側のサイドバーで、設定 > リポジトリ を選択します。
    4. リポジトリストレージセクションを展開します。

    このガイドに従って、default ストレージのウェイトを 100 にして、すべての新しいリポジトリを保存します。

  11. 新しいプロジェクトを作成して、すべてが機能していることを確認します。リポジトリをREADMEで初期化する」にチェックを入れて、リポジトリにコンテンツが表示されるようにします。プロジェクトが作成され、READMEファイルが表示されれば、動作しています!

既存のGitLabインスタンスにTCPを使う

既存のGitalyインスタンスにGitaly Clusterを追加する場合、既存のGitalyストレージがTCP/TLSでリッスンしている必要があります。gitaly_address が指定されていない場合、Unixソケットが使用され、クラスターとの通信が妨げられます。

使用例:

git_data_dirs({
  'default' => { 'gitaly_address' => 'tcp://old-gitaly.internal:8075' },
  'cluster' => {
    'gitaly_address' => 'tls://<PRAEFECT_LOADBALANCER_HOST>:3305',
    'gitaly_token' => '<praefect_external_token>'
  }
})

複数のGitalyストレージを実行するための詳細については、混合設定を参照してください。

Grafana

GrafanaはGitLabに含まれており、Praefectクラスターの監視に使用できます。詳細なドキュメントはGrafana Dashboard Serviceを参照してください。

すぐに始めるには

  1. GitLabノード(またはGrafanaが有効になっているノード)にSSHでログインし、rootとしてログインします:

    sudo -i
    
  2. /etc/gitlab/gitlab.rb を編集して Grafana ログインフォームを有効にします。

    grafana['disable_login_form'] = false
    
  3. /etc/gitlab/gitlab.rb に変更を保存し、GitLab を再設定します:

    gitlab-ctl reconfigure
    
  4. Grafana の管理者パスワードを設定します。このコマンドは、新しいパスワードを入力するよう促します:

    gitlab-ctl set-grafana-password
    
  5. Webブラウザで、GitLabサーバの/-/grafanahttps://gitlab.example.com/-/grafana など)を開きます。

    設定したパスワードとユーザー名admin を使ってログインします。

  6. エクスプローラにアクセスし、gitlab_build_info にクエリを実行して、すべてのマシンからメトリクスが取得されていることを確認します。

おめでとうございます!観測可能なフォールトトレラントPraefectクラスターが設定されました。

レプリケーション係数の設定

Praefectでは、リポジトリをホストする特定のストレージノードを割り当てることで、リポジトリごとにレプリケーション係数を設定できます。

caution
設定可能なレプリケーションファクターには、リポジトリ固有のプライマリノードが必要です。

Praefectは実際のレプリケーション係数を保存しませんが、希望するレプリケーション係数が満たされるように、リポジトリをホストするのに十分なストレージを割り当てます。ストレージノードが後で仮想ストレージから削除された場合、そのストレージに割り当てられたリポジトリのレプリケーション係数はそれに応じて減少します。

どちらかを設定できます:

  • 新しく作成されたリポジトリに適用される、各仮想ストレージのデフォルトのレプリケーション係数。
  • set-replication-factor サブコマンドを使用した既存のリポジトリに対するレプリケーション係数です。

デフォルトのレプリケーション係数の設定

default_replication_factor が設定されていない場合、リポジトリは常にvirtual_storages で定義されているすべてのストレージノードにレプリケートされます。新しいストレージノードが仮想ストレージに導入されると、新しいリポジトリと既存のリポジトリの両方が自動的にそのノードにレプリケートされます。

多くのストレージノードを持つ大規模なGitalyクラスタのデプロイでは、すべてのストレージノードにリポジトリをレプリケートすることは、多くの場合、賢明ではなく、問題を引き起こす可能性があります。通常、レプリケーション係数は3で十分です。これは、より多くのストレージが利用可能であっても、リポジトリを3つのストレージにレプリケートすることを意味します。レプリケーション係数を高くすると、プライマリストレージへの負荷が高くなります。

デフォルトのレプリケーション係数を設定するには、/etc/gitlab/gitlab.rb ファイルに設定を追加します:

praefect['configuration'] = {
   # ...
   virtual_storage: [
      {
         # ...
         name: 'default',
         default_replication_factor: 3,
      },
   ],
}

既存リポジトリのレプリケーション係数の設定

set-replication-factor サブコマンドは、希望するレプリケーション係数になるように、必要に応じてランダムなストレージノードを自動的に割り当てたり、割り当てなかったりします。リポジトリのプライマリノードは常に最初に割り当てられ、割り当てが解除されることはありません。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage <virtual-storage> -repository <relative-path> -replication-factor <replication-factor>
  • -virtual-storage はリポジトリが置かれている仮想ストレージです。
  • -repository はリポジトリの相対パスです。
  • -replication-factor はリポジトリのレプリケーション係数です。プライマリがリポジトリのコピーを必要とするため、最小値は1 です。レプリケーション係数の最大値は、仮想ストレージのストレージ数です。

成功すると、割り当てられたホストストレージが表示されます。例えば

$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage default -repository @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git -replication-factor 2

current assignments: gitaly-1, gitaly-2

リポジトリの推奨ストレージ

必要なストレージのサイズはインスタンスによって異なり、設定されたレプリケーション係数に依存します。リポジトリストレージの冗長性の実装を含めるとよいでしょう。

レプリケーション係数には

  • 1:Gitalyとクラスターのストレージ要件はほぼ同じです。
  • 1 以上 : 必要なストレージの量はused space * replication factor です。used space には、将来計画される増加分を含める必要があります。

リポジトリの検証

GitLab 15.0 で導入されました

Praefectはリポジトリに関するメタデータをデータベースに保存します。リポジトリがPraefectを介さずにディスク上で変更されると、メタデータが不正確になる可能性があります。メタデータはレプリケーションやルーティングの決定に使用されるため、不正確であると問題が発生する可能性があります。Praefectには、メタデータとディスク上の実際の状態を定期的に検証するバックグラウンドワーカーがあります。ワーカーは

  1. 健全なストレージ上で検証するレプリカのバッチをピックアップします。レプリカは未検証か、設定された検証間隔を超過しています。一度も検証されたことのないレプリカが優先され、最後に検証に成功してからの時間が長い順に他のレプリカが続きます。
  2. レプリカがそれぞれのストレージに存在するかどうかをチェックします。もし
    • レプリカが存在する場合は、最後に検証に成功した時刻を更新します。
    • レプリカが存在しない場合は、そのメタデータ・レコードを削除してください。
    • チェックに失敗した場合、次のワーカーが仕事をデキューするときに、レプリカは再度検証のためにピックアップされます。

ワーカーは、これから検証するレプリカのそれぞれについて、排他的な検証リースを取得します。これにより、複数のワーカーが同じレプリカを同時に検証することを防ぎます。ワーカーは、確認が完了するとリースをリリースします。Praefectには、ワーカーがリースをリリースせずに何らかの理由で終了した場合に、古いリースを10秒ごとにリリースするバックグラウンドゴルーチンがあります。

ワーカーは、メタデータの削除を実行する前にそれぞれログに記録します。perform_deletions キーは無効なメタデータレコードが実際に削除されたかどうかを示します。例えば

{
  "level": "info",
  "msg": "removing metadata records of non-existent replicas",
  "perform_deletions": false,
  "replicas": {
    "default": {
      "@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.git": [
        "praefect-internal-0"
      ]
    }
  }
}

検証ワーカーの設定

ワーカーはデフォルトで有効になっており、7 日ごとにメタデータレコードを検証します。検証間隔は任意の有効なGo 期間文字列で設定可能です。

メタデータを 3 日ごとに検証するには、次のようにします:

praefect['configuration'] = {
   # ...
   background_verification: {
      # ...
      verification_interval: '72h',
   },
}

0以下の値はバックグラウンド検証を無効にします。

praefect['configuration'] = {
   # ...
   background_verification: {
      # ...
      verification_interval: '0',
   },
}

削除の有効化

caution
GitLab 15.9より前のバージョンでは、リポジトリのリネーム時に競合状態が発生し、誤った削除が行われる可能性があるため、削除はデフォルトで無効になっていました。Geoインスタンスでは、Geoがないインスタンスよりも多くのリネームを行うため、特に顕著です。GitLab 15.0 から 15.5 では、gitaly_praefect_generated_replica_paths 機能フラグが有効な場合にのみ削除を有効にする必要があります。GitLab 15.6では機能フラグが削除され、削除は常に安全に有効にできるようになりました。

デフォルトでは、ワーカーは無効なメタデータレコードを削除します。また、削除されたレコードをログに記録し、Prometheusメトリクスを出力します。

で無効なメタデータレコードの削除を無効にできます:

praefect['configuration'] = {
   # ...
   background_verification: {
      # ...
      delete_invalid_records: false,
   },
}

検証の優先順位を手動で設定

次に予定されている検証時間よりも前に、一部のレプリカの検証を優先させることができます。これは、ディスク障害の発生後、ディスクの内容が変更された可能性があることを管理者が知っている場合などに必要です。Praefectは最終的にレプリカを再度検証しますが、その間にユーザーがエラーに遭遇する可能性があります。

一部のレプリカの再確認の優先順位を手動で設定するには、praefect verify サブコマンドを使用します。このサブコマンドは、レプリカを未検証としてマークします。未検証のレプリカはバックグラウンドの検証ワーカーによって優先されます。レプリカを検証するためには、検証ワーカーが有効になっている必要があります。

特定のリポジトリのレプリカの検証を優先します:

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

仮想ストレージに保存されているすべてのレプリカの検証を優先します:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml verify -virtual-storage=<virtual-storage>

ストレージに保存されているすべてのレプリカの検証を優先します:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml verify -virtual-storage=<virtual-storage> -storage=<storage>

出力には、未検証とマークされたレプリカの数が含まれます。

自動フェイルオーバーとプライマリ選出戦略

Praefectは、各Gitalyノードの健全性を定期的にチェックし、現在のプライマリノードが不健全であることが判明した場合、新たに選出されたプライマリノードに自動的にフェイルオーバーするために使用されます。

リポジトリ固有のプライマリ・ノードを使用する必要があります。これはGitLab 14.0から利用できる唯一の選出方法です。

リポジトリ固有のプライマリノード

  • GitLab 13.12で導入され、プライマリノードが起動した時やクラスターのコンセンサスが変化した時に実行されます。
  • GitLab 14.1で変更され、一次選挙は遅延的に実行されるようになりました。

Gitalyクラスタは、リポジトリごとにプライマリノードを選択します。設定可能なレプリケーション係数と組み合わせることで、ストレージ容量を水平方向に拡張し、Gitalyノード間で書き込み負荷を分散することができます。

プライマリ選出は遅延的に実行されます。Praefectは、現在のプライマリノードが不健全であっても、すぐに新しいプライマリノードを選出しません。現在のプライマリが利用できない間にリクエストを処理する必要がある場合、新しいプライマリが選出されます。

有効なプライマリノード候補とは、以下のようなGitalyノードです:

  • 健康であること。Gitalyノードは、>=50% Gitalyノードが過去10秒間にヘルスチェックに成功した場合、健康であるとみなされます。
  • リポジトリの完全な最新コピーを持っています。

プライマリノード候補が複数ある場合、Praefect:

  • ランダムに1つを選びます。
  • リポジトリのホストに割り当てられているGitalyノードを優先的に昇格させます。プライマリノードとして選択するGitalyノードが割り当てられていない場合、Praefectは一時的に未割り当てのノードを選択することができます。未割り当てのプライマリが利用可能になると、割り当てられたプライマリを優先して降格します。

リポジトリに有効なプライマリ候補がない場合:

  • 不健全なプライマリノードは降格され、リポジトリにはプライマリノードがない状態になります。
  • プライマリノードが必要なオペレーションは、プライマリノードが正常に選出されるまで失敗します。

リポジトリ固有のプライマリノードへのマイグレーション

新しいGitalyクラスターは、per_repository 選挙戦略をすぐに使い始めることができます。

既存のクラスターをマイグレーションするには:

  1. Praefectノードはこれまで、クラスターに保存されているすべてのリポジトリのデータベースレコードを保持していませんでした。per_repository 選挙戦略を設定すると、Praefect は各リポジトリのデータベースレコードがあることを期待します。バックグラウンドでデータベースをマイグレーションすると、リポジトリに不足しているデータベースレコードが作成されます。マイグレーションを実行する前に、Praefectのログを確認して、データベースマイグレーションが実行されたことを確認してください。

    Praefect のログでrepository importer finished メッセージを確認します。virtual_storages フィールドには、仮想ストレージの名前と、データベースレコードが作成されていないかどうかが表示されます。

    たとえば、default 仮想ストレージは正常にマイグレーションされました:

    {"level":"info","msg":"repository importer finished","pid":19752,"time":"2021-04-28T11:41:36.743Z","virtual_storages":{"default":true}}
    

    仮想ストレージが正常にマイグレーションされていない場合は、false が表示されます:

    {"level":"info","msg":"repository importer finished","pid":19752,"time":"2021-04-28T11:41:36.743Z","virtual_storages":{"default":false}}
    

    データベースのマイグレーションは Praefect の起動時に実行されます。データベースのマイグレーションが失敗した場合は、Praefect ノードを再起動してマイグレーションを再試行できます。

  2. 2つの異なる選挙戦略を並行して実行すると、異なるPraefectノードが異なるプライマリノードを持つリポジトリとみなすスプリットブレインが発生することがあります。これは次の方法で回避できます:

    • 短いダウンタイムを許容できる場合:

      1. 選挙戦略を変更する前に、すべての Praefect ノードをシャットダウンします。Praefect ノードでgitlab-ctl stop praefect を実行します。

      2. Praefect ノードで、praefect['failover_election_strategy'] = 'per_repository' を使用して、/etc/gitlab/gitlab.rb の選挙戦略を設定します。

      3. gitlab-ctl reconfigure && gitlab-ctl start を実行し、Praefect ノードを再設定して起動します。

    • ダウンタイムが許容できない場合

      1. どのGitalyノードが現在のプライマリノードであるかを決定します。

      2. すべてのPraefectノードの/etc/gitlab/gitlab.rb 、仮想ストレージの設定からセカンダリノードをコメントアウトします。こ れに よ り 、 Gitaly ノードが 1 つだけ設定 さ れ、 ど ち ら の選出ス ト ラ テジ も 同 じ Gitaly ノードをプ ラ イ マ リ ノ ー ド と し て選出す る よ う にな り ます。

      3. すべての Praefect ノードでgitlab-ctl reconfigure を実行します。すべての Praefect プロセスが再起動し、古いプロセスが終了するまで待ちます。最長1分かかります。

      4. すべての Praefect ノードで、praefect['failover_election_strategy'] = 'per_repository' を使用して、/etc/gitlab/gitlab.rb の選挙戦略を設定します。

      5. すべての Praefect ノードでgitlab-ctl reconfigure を実行します。すべての Praefect プロセスが再起動し、古いプロセスが終了するまで待ちます。最長1分かかります。

      6. すべてのPraefectノードで、先のステップでコメントアウトしたセカンダリノードの設定のコメントを解除します。

      7. すべての Praefect ノードでgitlab-ctl reconfigure を実行して、Praefect プロセスを再設定し、再起動します。