Gitalyクラスター

Gitリポジトリのストレージを提供するサービスであるGitalyは、耐障害性を高めるためにクラスター構成で実行することができます。 この構成では、すべてのGitリポジトリはクラスター内のすべてのGitalyノードに保存されます。 複数のクラスター(またはシャード)を構成することができます。

注:GitalyクラスターはGitLab Coreとそれ以上のティアを使用して作成することができます。 しかし、テクニカルサポートはGitLab PremiumとUltimateのお客様のみに限定されます。 GitLab.comではご利用いただけません。

PraefectはGitaly用のルータとトランザクションマネージャで、Gitalyクラスタを実行するために必要なコンポーネントです。

Architecture diagram

Gitalyクラスターを使用することで、耐障害性が向上します:

  • 書き込みオペレーションをウォームスタンバイGitalyノードにレプリケートします。
  • Gitalyノードの障害を検出します。
  • Gitリクエストを利用可能なGitalyノードに自動的にルーティングします。

Gitalyクラスターの可用性の目標は次のとおりです:

  • リカバリーポイント目標(RPO): 1分以内。

    書き込みは非同期にレプリケートされ、新しく昇格したプライマリにレプリケートされていない書き込みは失われます。

    強力なコンシステンシーを使えば、これを「ロスなし」に改善することができます。

  • 回復時間(RTO): 10秒未満。

    機能停止は、各Praefectノードで1秒ごとに実行されるヘルスチェックによって検出されます。 フェイルオーバーには、各Praefectノードのヘルスチェックが10回連続して失敗する必要があります。

    停電検出の高速化により、これを1秒未満に改善する予定です。

現在のバージョンでは

  • セカンダリレプリカの最終的な一貫性。
  • プライマリからセカンダリへの自動フェイルオーバー。
  • レプリケーションキューが空でない場合、データ損失の可能性をレポーター。
  • データ損失の可能性が検出された場合、新しく昇格したプライマリに読み取り専用マークを付けます。

HAGitalyのエピックに従い、リードの水平ディストリビューションなどの改善を行いました。

Gitalyクラスタを構成するための要件

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

  • ロードバランサー 1台
  • 1台のPostgreSQLサーバ(PostgreSQL 11以降)
  • 3プレフェクト・ノード
  • 3つのGitalyノード(プライマリ1、セカンダリ2)

実装の詳細については、設計書を参照してください。

セットアップ方法

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

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

準備

作業を始める前に、GitLabインスタンスが動作している必要があります。GitLabのインストール方法についてはこちらをご覧ください。

PostgreSQLサーバー(PostgreSQL 11以降)をプロビジョニングしてください。 Omnibus GitLabディストリビューションによる設定はまだサポートされていません。 アップデートについては、このイシューに従ってください。

GitLabをインストールして新しいノードを準備します。

  • 1プレフェクトノード(必要最小限のストレージ)
  • 3 Gitalyノード(ハイCPU、ハイメモリ、高速ストレージ)
  • 1 GitLabサーバー

各ノードのIP/ホスト・アドレスが必要です。

  1. LOAD_BALANCER_SERVER_ADDRESSロードバランサーの IP/ ホストアドレス
  2. POSTGRESQL_SERVER_ADDRESSPostgreSQLサーバのIP/ホストアドレス
  3. PRAEFECT_HOSTPraefectサーバーのIP/ホストアドレス
  4. GITALY_HOST各GitalyサーバーのIP/ホストアドレス
  5. GITLAB_HOSTGitLabサーバーのIP/ホストアドレス

クラウドプロバイダーを使用している場合は、クラウドプロバイダーの管理コンソールから各サーバーのアドレスを調べることができます。

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

秘密

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

  1. GITLAB_SHELL_SECRET_TOKENこのシークレットはレガシーな理由から GitLab Shell と共有されます。
  2. PRAEFECT_EXTERNAL_TOKENクラスター上のリポジトリは、このトークンを持つGitalyクライアントからのみアクセスできます。
  3. PRAEFECT_INTERNAL_TOKENこのトークンは、クラスター内部のレプリケーショントラフィックに使用されます。Gitalyクライアントがクラスター内部ノードに直接アクセストークンできないようにする必要があるため、PRAEFECT_EXTERNAL_TOKENとは異なります。
  4. PRAEFECT_SQL_PASSWORDこのパスワードはPostgreSQLに接続する際に使用されます。

これらの秘密が必要な箇所は、以下の説明書に記載されています。

PostgreSQL

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

このセクションを完了するには、以下のものが必要です:

  • 1 Praefectノード
  • 1台のPostgreSQLサーバ(PostgreSQL 11以降)
    • データベースを作成する権限を持つSQLユーザー

このセクションでは、Omnibus GitLabによってインストールされたpsql 、PlayfectノードからPostgreSQLサーバーを設定します。

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

    sudo -i
    
  2. 管理者権限でPostgreSQLサーバに接続してください。 これはおそらくpostgres ユーザです。 データベースtemplate1 はすべてのPostgreSQLサーバでデフォルトで作成されているため、これを使用しています。

    /opt/gitlab/embedded/bin/psql -U postgres -d template1 -h POSTGRESQL_SERVER_ADDRESS
    

    Praefectで使用する新しいユーザーpraefect を作成します。PRAEFECT_SQL_PASSWORD を、準備ステップで作成した強力なパスワードに置き換えます。

    CREATE ROLE praefect WITH LOGIN CREATEDB PASSWORD 'PRAEFECT_SQL_PASSWORD';
    
  3. PostgreSQLサーバに再接続し、今度はpraefect

    /opt/gitlab/embedded/bin/psql -U praefect -d template1 -h POSTGRESQL_SERVER_ADDRESS
    

    新しいデータベースpraefect_productionを作成します。praefect ユーザーとして接続中にデータベースを作成することで、彼らがアクセスできることを確信します。

    CREATE DATABASE praefect_production WITH ENCODING=UTF8;
    

Praefectが使用するデータベースが設定されました。

総評

このセクションを完了するには、以下のものが必要です:

  • PostgreSQLサーバーの設定
    • IP/ホストアドレス (POSTGRESQL_SERVER_ADDRESS)
    • パスワード (PRAEFECT_SQL_PASSWORD)

アプリケーションサーバーやGitalyノード上でPlayfectを実行しないでください。

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

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

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

    praefect['listen_addr'] = '0.0.0.0:2305'
    
    # Enable Prometheus metrics access to Praefect. You must use firewalls
    # to restrict access to this address/port.
    praefect['prometheus_listen_addr'] = '0.0.0.0:9652'
    
  4. /etc/gitlab/gitlab.rbを編集して、Praefect用の強力なauth_token を設定します。これは、クラスター外部のクライアント(GitLab Shell など)が Praefect クラスターと通信するために必要になります:

    praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN'
    
  5. /etc/gitlab/gitlab.rbを編集して、PostgreSQLデータベースに接続するようにPraefectを設定します。

    POSTGRESQL_SERVER_ADDRESS をデータベースのIP/ホストアドレスに、PRAEFECT_SQL_PASSWORD を上記で設定した強力なパスワードに置き換える必要があります。

    praefect['database_host'] = 'POSTGRESQL_SERVER_ADDRESS'
    praefect['database_port'] = 5432
    praefect['database_user'] = 'praefect'
    praefect['database_password'] = 'PRAEFECT_SQL_PASSWORD'
    praefect['database_dbname'] = 'praefect_production'
    

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

    # Connect to PostreSQL using a TLS client certificate
    # praefect['database_sslcert'] = '/path/to/client-cert'
    # praefect['database_sslkey'] = '/path/to/client-key'
    
    # Trust a custom certificate authority
    # praefect['database_sslrootcert'] = '/path/to/rootcert'
    

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

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

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

    注意:defaultという名前の既存のストレージにデータがある場合は、別の名前で仮想ス トレージを構成してから、Praefect ストレージにデータを移行してください。

    PRAEFECT_INTERNAL_TOKEN このトークンはPRAEFECT_EXTERNAL_TOKENとは異なります。

    GITALY_HOST を各 Gitaly ノードの IP/host アドレスに置き換えてください。

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

    注: gitaly-1 ノードは現在プライマリと表記されています。これは、あるノードから別のノードへ手動でフェイルさせるために使用できます。これは将来削除される予定です。
    # Name of storage hash must match storage name in git_data_dirs on GitLab
    # server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
    praefect['virtual_storages'] = {
      'default' => {
        'gitaly-1' => {
          'address' => 'tcp://GITALY_HOST:8075',
          'token'   => 'PRAEFECT_INTERNAL_TOKEN',
          'primary' => true
        },
        'gitaly-2' => {
          'address' => 'tcp://GITALY_HOST:8075',
          'token'   => 'PRAEFECT_INTERNAL_TOKEN'
        },
        'gitaly-3' => {
          'address' => 'tcp://GITALY_HOST:8075',
          'token'   => 'PRAEFECT_INTERNAL_TOKEN'
        }
      }
    }
    
  7. GitLab 13.1以降で導入されリードのディストリビューションを可能にします。

  8. /etc/gitlab/gitlab.rb に変更を保存し、Praefect を再設定します:

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

    gitlab-ctl restart praefect
    
  10. Playfectが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を再度実行することを忘れないでください。

上記の手順は、Praefect ノードごとに行う必要があります!

TLSサポートの有効化

GitLab 13.2 で導入されました

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

  • GitLab設定の対応するストレージエントリーのgitaly_addresstls:// URLスキームを使用してください。
  • 各Praefectサーバーに対応する証明書をインストールする必要があります。

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

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

  • 証明書には、Praefect サーバーへのアクセスに使用するアドレスを指定する必要があります。 Praefect サーバーのアドレスを指定する場合は、次のようにします:

    • ホスト名には、[共通名] フィールドを使用するか、サブジェクトの代替名として追加できます。
    • IPアドレスは、証明書のサブジェクト代替名として追加する必要があります。
  • 暗号化されていないリスニングアドレス(listen_addr )と暗号化されたリスニングアドレス(tls_listen_addr )の両方を持つPraefectサーバーを同時に設定できます。これにより、必要に応じて、暗号化されていないトラフィックから暗号化されたトラフィックへ徐々に移行することができます。

TLSを使用してPraefectを設定するには、次の手順に従います:

Omnibus 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. /etc/gitlab/gitlab.rb を編集して追加してください:

    praefect['tls_listen_addr'] = "0.0.0.0:3305"
    praefect['certificate_path'] = "/etc/gitlab/ssl/cert.pem"
    praefect['key_path'] = "/etc/gitlab/ssl/key.pem"
    
  4. ファイルを保存し、GitLabを再設定します。
  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://praefect1.internal:3305' },
      'storage1' => { 'gitaly_address' => 'tls://praefect2.internal:3305' },
    })
    
  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://praefect1.internal:3305
            path: /some/dummy/path
          storage1:
            gitaly_address: tls://praefect2.internal:3305
            path: /some/dummy/path
    
    注:/some/dummy/path は存在する内部フォルダに設定する必要がありますが、このフォルダにはデータは保存されません。このイシューが解決された後は、この設定は不要になります。
  5. ファイルを保存し、GitLabを再起動します。
  6. Gitalyサーバーから呼び出された際に、Praefectサーバーが証明書を信頼するように、すべてのPraefectサーバー証明書、またはその作成者を、各Gitalyサーバーのシステム信頼済み証明書にコピーします:

    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を再起動します。

Gitaly

注: 各Gitalyノードについて、これらの手順を完了してください。

このセクションを完了するには、以下のものが必要です:

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

Praefectクラスターに割り当てられたGitalyサーバーは、すべて設定が必要です。 設定は、通常のスタンドアロンのGitalyサーバーと同じですが、以下の点が異なります:

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

オペレーションを正しくルーティングするためにPraefectに依存しているため、クラスター内のすべてのGitalyノードのコンフィギュレーションは同一でかまいません。

特に注意すべきは

  • このセクションで設定したgitaly['auth_token'] は、Praefect ノードのpraefect['virtual_storages'] の下にあるtokenの値と一致する必要があります。これは前のセクションで設定したものです。このドキュメントでは、全体を通してプレースホルダPRAEFECT_INTERNAL_TOKEN を使用します。
  • このセクションで設定したgit_data_dirs のストレージ名は、Praefect ノードのpraefect['virtual_storages'] 以下のストレージ名と一致する必要があります。これは前のセクションで設定したものです。このドキュメントでは、gitaly-1gitaly-2gitaly-3 を Gitaly ストレージ名として使用します。

Gitalyサーバーの設定については、Gitalyのドキュメントをご覧ください。

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

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

    # Disable all other services on the Praefect 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
    
    # Enable only the Gitaly service
    gitaly['enable'] = true
    
    # Enable Prometheus if needed
    prometheus['enable'] = true
    
    # Prevent database connections during 'gitlab-ctl reconfigure'
    gitlab_rails['rake_cache_clear'] = false
    gitlab_rails['auto_migrate'] = false
    
  3. /etc/gitlab/gitlab.rbを編集して、Gitalyがネットワーク・インタフェースをリッスンするように設定します:

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

    gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN'
    
  5. git push のオペレーションに必要な GitLab Shellsecret_tokeninternal_api_url を設定します。

    すでにGitalyを独自サーバーに設定している場合

    gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
    
    # 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://example.gitlab.com', 'http://1.2.3.4'
    gitlab_rails['internal_api_url'] = 'http://GITLAB_HOST'
    
  6. /etc/gitlab/gitlab.rbgit_data_dirs を設定し、Gitデータの保存場所を設定します。各Gitalyノードは、ユニークなストレージ名(gitaly-1)を持つ必要があります。

    各 Gitaly ノードに対してgit_data_dirs を一意に設定する代わりに、すべての Gitaly ノードに対する設定をすべての Gitaly ノードに含める方が簡単な場合があります。これは、Praefectvirtual_storages設定が各ストレージ名(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.
    git_data_dirs({
      "gitaly-1" => {
        "path" => "/var/opt/gitlab/git-data"
      },
      "gitaly-2" => {
        "path" => "/var/opt/gitlab/git-data"
      },
      "gitaly-3" => {
        "path" => "/var/opt/gitlab/git-data"
      }
    })
    
  7. /etc/gitlab/gitlab.rb に変更を保存し、Gitaly を再設定してください:

    gitlab-ctl reconfigure
    
  8. GitalyがPrometheusのリスンアドレスを更新したことを確認するには、Gitalyを再起動してください:

    gitlab-ctl restart gitaly
    

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

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

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

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

ロードバランサー

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

GitLabのようなHAシステムを管理されている方は、すでにロードバランサーを選択されているかと思います。HAProxy(オープンソース)、Google Internal Load BalancerAWS Elastic Load Balancer、F5 Big-IP LTM、Citrix Net Scalerなどがその例です。 このドキュメントでは、設定する必要があるポートとプロトコルの概要を説明します。

LBポート バックエンドポート プロトコル
2305 2305 伝送制御プロトコル

GitLab

このセクションを完了するには、以下のものが必要です:

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

特に注意すべきは

  • このセクションでgit_data_dirs に追加したストレージ名は、Praefect ノードのpraefect['virtual_storages'] のストレージ名と一致する必要があります。これは、このガイドのPraefectセクションで設定したものです。このドキュメントでは、Praefect ストレージ名としてstorage-1 を使用します。
  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は設定されたクラスターに接続するので、これは必要ありません。

    注意デフォルトのGitalyストレージに既存のデータが保存されている場合は、まずPraefectストレージにデータを移行する必要があります。
    gitaly['enable'] = false
    
  4. /etc/gitlab/gitlab.rbを編集して、Praefectクラスターをストレージの場所として追加します。

    交換が必要です:

    • LOAD_BALANCER_SERVER_ADDRESS にロードバランサの IP アドレスかホスト名を指定します。
    • PRAEFECT_EXTERNAL_TOKEN 本当の秘密と
    git_data_dirs({
      "default" => {
        "gitaly_address" => "tcp://LOAD_BALANCER_SERVER_ADDRESS:2305",
        "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    })
    
  5. git push 中の Gitaly ノードからのコールバックが適切に認証されるように、/etc/gitlab/gitlab.rbを編集してgitlab_shell['secret_token'] を設定します:

    GITLAB_SHELL_SECRET_TOKEN を本当の秘密と置き換える必要があります。

    gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
    
  6. /etc/gitlab/gitlab.rbを編集して 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:9236', # gitaly-1
            'GITALY_HOST:9236', # gitaly-2
            'GITALY_HOST:9236', # gitaly-3
          ]
        ]
      }
    ]
    
  7. /etc/gitlab/gitlab.rb に変更を保存し、GitLab を再設定します:

    gitlab-ctl reconfigure
    
  8. 各Gitalyインスタンスのgitlab-shell 、GitLabにアクセスできることを確認します。 各Gitalyインスタンスで実行します:

    /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml
    
  9. GitLabがPraefectにアクセスできることを確認します:

    gitlab-rake gitlab:gitaly:check
    
  10. 管理エリア > 設定 > リポジトリ > リポジトリストレージで、Praefect ストレージが新しいリポジトリを保存するように構成されていることを確認します。 このガイドに従って、default ストレージのウェイトを 100 にして、すべての新しいリポジトリを保存します。

  11. プロジェクトが作成され、READMEファイルが表示されれば、うまくいっています!

グラファナ

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

すぐに始めるには

  1. GitLabノードに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. ウェブブラウザで、GitLabサーバーの/-/grafana (例:https://gitlab.example.com/-/grafana)を開きます。

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

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

おめでとうございます!観測可能な高可用性Praefectクラスターが構成されました。

ディストリビューションリード

GitLab 13.1のベータ版で、機能フラグgitaly_distributed_reads がdisabledに設定された状態で導入されました。

プレフェクトは、仮想ノード用に設定されたGitalyノード間での読み取りオペレーションのディストリビューションをサポートしています。

パフォーマンステストのため、分散読み込みは現在ベータ版でデフォルトでは無効になっています。 分散読み込みを有効にするには、Rubyコンソールでgitaly_distributed_reads機能フラグを有効にする必要があります:

Feature.enable(:gitaly_distributed_reads)

有効にすると、GetBlobのようなACCESSOR オプションが付いたすべてのRPCは、最新の健全なGitalyノードにリダイレクトされます。

ここでいう_最新とは_、以下のような意味です:

  • このノードではレプリケーション・オペレーションがスケジュールされていません。
  • 最後のレプリケーション・オペレーションが_完了_した状態です。

そのようなノードがない場合、またはノード選択中に他のエラーが発生した場合は、プライマリノードがリクエストに応答するために選択されます。

読み取りオペレーションのディストリビューションを追跡するには、gitaly_praefect_read_distributionPrometheusカウンタ・メトリックを使用できます。これには2つのラベルがあります:

  • virtual_storage.
  • storage.

これらは、この Praefect のインスタンスで定義された設定を反映しています。

強い一貫性

GitLab13.1のアルファ版で導入されましたが、デフォルトでは無効になっています。

プレフェクトは、プライマリGitalyノードへの書き込みが発生した後に、セカンダリノードへのすべての書き込みをレプリケートすることにより、最終的な一貫性を保証します。

Praefectは、トランザクションを作成し、すべてのGitalyノードに変更を一度に書き込むことで、強力な一貫性を提供することができます。 強力な一貫性は現在アルファ版であり、デフォルトでは有効になっていません。 詳細については、強力な一貫性のエピックを参照してください。

強力な一貫性を可能にするため:

  • GitLab 13.2以降では、:gitaly_reference_transactions 機能フラグを有効にしてください。
  • GitLab 13.1 では、:gitaly_reference_transactions:gitaly_hooks_rpc機能フラグを有効にしてください。

機能フラグを有効にするには、Railsコンソールにアクセスする必要があります。 Railsコンソールで、必要に応じてフラグを有効または無効にします。 たとえば、次のようにします:

Feature.enable(:gitaly_reference_transactions)

強力な一貫性を監視するには、gitaly_praefect_transactions_total およびgitaly_praefect_transactions_delay_seconds Prometheus カウンター・メトリクスを使用します。

自動フェイルオーバーとリーダー選出

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

  • PostgreSQL(推奨):デフォルトで有効、praefect['failover_election_strategy'] = sqlと同じです。 この設定オプションを使用すると、複数の Praefect ノードが PostgreSQL データベースを介して連携し、プライマリ Gitaly ノードを選出します。この設定により、Praefect ノードが新しいプライマリを選出し、その健全性を監視し、現在のプライマリに 10 秒以内に過半数の Praefect ノードが到達できなかった場合に、新しいプライマリを選出します。
  • 手動:自動フェイルオーバーは無効です。 プライマリ・ノードは、Praefect ノードの/etc/gitlab/gitlab.rb で再設定できます。primary = true を移動してpraefect['virtual_storages'] フィールドを変更し、別の Gitaly ノードをプライマリに昇格させます。上記の手順では、gitaly-1 がプライマリに設定されています。設定にはpraefect['failover_enabled'] = false が必要です。
  • メモリ:Praefect ノードの/etc/gitlab/gitlab.rbpraefect['failover_election_strategy'] = 'local'を設定することで有効になります。現在のプライマリバックエンド Gitaly ノードで十分な数のヘルスチェックが失敗した場合、新しいプライマリが選出されます。複数の Praefect ノードで使用しないでください!複数の Praefect ノードで使用すると、脳が分裂する可能性が高くなります。

将来的にはConsulのサポートやクラウドネイティブ戦略を導入することになるでしょう。

一次ノードの故障

プライマリGitalyノードの障害が発生した場合、健全なセカンダリを新しいプライマリとして昇格させることで復旧します。 データ損失を最小限に抑えるため、プライマリからの未複製書き込みが最も少ないセカンダリを選択します。 それでも未複製書き込みが発生し、データ損失につながる可能性があります。

Praefectは、フェイルオーバーイベント後に仮想ストレージを読み取り専用モードに切り替えます。 これにより、新しくプライマリに選択されたストレージへの書き込みが競合する可能性があるため、書き込みを防止してデータ復旧作業を容易にします。 管理者は、新しい書き込みを許可する前に、失われたデータの復旧を試みることができます。

一貫性よりも書き込み可用性を重視する場合は、/etc/gitlab/gitlab.rbpraefect['failover_read_only_after_failover'] = false を設定し、Praefect を再設定することで、この動作をオフにできます。

データ損失のチェック

Praefectdataloss サブコマンドは、未完了のレプリケーションジョブをチェックすることで、失われた書き込みを特定するのに役立ちます。 これは、フェイルオーバー後に起こりうるデータ損失のケースを特定するのに便利です。 このコマンドは、Praefectノード上で実行する必要があります。

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
Virtual storage: default
  Current read-only primary: gitaly-2
  Previous write-enabled primary: gitaly-1
    Nodes with data loss from failing over from gitaly-1:
      @hashed/2c/62/2c624232cdd221771294dfbb310aca000a0df6ac8b66b696d90ef06fdefb64a3.git: gitaly-0
      @hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git: gitaly-0, gitaly-2

現在、dataloss は、書き込み可能なプライマリから直接レプリケートされた場合のみ、リポジトリを最新とみなします。 最新セカンダリからリコンサイルすることでデータを回復できますが、これはデータ損失レポートでは表示されません。 これはGitaly#2866によって改善される予定です。

dataloss はまだベータ版であり、出力形式は変更される可能性があります。

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

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

失われた書き込みの回復

Praefectreconcile サブコマンドを使用すると、以前のプライマリがオンラインに戻ったときに、失われた書き込みを回復できます。これは、仮想ストレージが読み取り専用モードの場合にのみ可能です。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -reference <previous-primary> -target <current-primary> -f

reconcile サブコマンドの詳細については、「Backend Node Recovery」のセクションを参照してください。

書き込みの有効化

書き込みが競合する可能性を排除するために、書き込みを有効にする前にデータ回復を試行する必要があります。仮想ストレージは、Praefectenable-writes サブコマンドを使用して書き込みを再度有効にできます。

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

バックエンド・ノードの復旧

Praefectのバックエンドノードに障害が発生し、変更をレプリケートできなくなると、バックエンドノードはプライマリからドリフトし始めます。 そのノードが最終的に回復した場合は、現在のプライマリと照合する必要があります。 プライマリノードは、シャードの状態の唯一の真実の情報源と見なされます。 Praefectのreconcile サブコマンドを使用すると、バックエンドノードと現在のプライマリとの間で手動による照合を行うことができます。

すべてのプレースホルダ(<virtual-storage><target-storage>)を置換した後、Praefect サーバーで次のコマンドを実行します:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -target <target-storage>
  • プレースホルダ<virtual-storage> を、チェックするバックエンド・ノード・ストレージを含む仮想ストレージに置き換えます。
  • プレースホルダ<target-storage> をバックエンドのストレージ名に置き換えます。

このコマンドは、現在のプライマリに対して不整合が見つかったリポジトリのリストを返します。 これらの不整合は、レプリケーション・ジョブIDとともにログに記録されます。

既存のリポジトリのPraefectへの移行

GitLab インスタンスにすでにリポジトリがある場合は、自動的に移行されません。

リポジトリは、リポジトリAPIを使用して、ある保管場所から移動することができます:

curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "repository_storage=praefect" https://example.gitlab.com/api/v4/projects/123

プレフェクトのデバッグ

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

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

  • 500 応答コード
    • ActionView::Template::Error (7:権限が拒否されました)
      • praefect['auth_token']gitlab_rails['gitaly_token'] が GitLab サーバー上で一致しません。
    • プロジェクトを保存できません。 エラー: 7:権限が拒否されました。
      • GitLabサーバーのpraefect['storage_nodes'] のシークレットトークンが、1つ以上のGitalyサーバーのgitaly['auth_token'] の値と一致しません。
  • 503 応答コード
    • GRPC::Unavailable (14:すべてのアドレスへの接続に失敗しました)
      • GitLabはPraefectと連絡が取れませんでした。
    • GRPC::Unavailable (14:all SubCons are in TransientFailure…)
      • Gitalyの子ノードに接続できません。 Praefect接続チェッカーを実行して診断してください。