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

Gitalyを設定する

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

Gitalyを設定する方法は2つあります:

  1. /etc/gitlab/gitlab.rbを編集して、Gitalyの設定を追加または変更します。Gitaly設定ファイルの例を参照してください。サンプルファイルの設定は、Rubyに変換する必要があります。
  2. ファイルを保存してGitLabを再設定します。
  1. /home/git/gitaly/config.tomlを編集して、Gitalyの設定を追加または変更します。Gitaly設定ファイルの例を参照してください。
  2. ファイルを保存して、GitLabを再起動します。

次の設定オプションも使用できます:

Gitalyトークンについて

Gitalyドキュメント全体で参照されているトークンは、管理者が選択した任意のパスワードにすぎません。これは、GitLab APIまたは他の同様のAPI用に作成されたトークンとは関係ありません。

Gitalyを独自のサーバーで実行する

デフォルトでは、GitalyはGitalyクライアントと同じサーバー上で実行され、前述のように構成されます。シングルサーバーインストールは、以下で使用されるこのデフォルト構成で最適に提供されます:

ただし、Gitalyは独自のサーバーにデプロイでき、複数のマシンにまたがるGitLabインストールに役立ちます。

独自のサーバー上で実行するように構成されている場合、Gitalyサーバーは、クラスター内のGitalyクライアントより前にアップグレードする必要があります。

ディスク要件は、Gitalyノードに適用されます。

独自のサーバーにGitalyをセットアップする手順は次のとおりです:

  1. Gitalyをインストールします。
  2. 認証を構成します。
  3. Gitalyサーバーを構成します。
  4. Gitalyクライアントを設定します。
  5. 不要なGitalyを無効にする (オプション)。

ネットワークアーキテクチャ

次のリストは、Gitalyのネットワークアーキテクチャを示しています:

  • GitLab Railsは、リポジトリストレージにシャードを分割します。
  • /config/gitlab.ymlには、ストレージ名から(Gitaly address, Gitaly token)のペアへのマップが含まれています。
  • /config/gitlab.ymlstorage name -> (Gitaly address, Gitaly token)マップは、Gitalyネットワークトポロジの信頼できる唯一の情報源です。
  • (Gitaly address, Gitaly token)は、Gitalyサーバーに対応します。
  • Gitalyサーバーは、1つ以上のストレージをホストします。
  • Gitalyクライアントは、1つ以上のGitalyサーバーを使用できます。
  • Gitalyアドレスは、すべてのGitalyクライアントに対して正しく解決されるように指定する必要があります。
  • Gitalyクライアントは次のとおりです:
    • Puma。
    • Sidekiq。
    • GitLab Workhorse。
    • GitLab Shell。
    • Elasticsearch Indexer。
    • Gitaly自体。
  • Gitalyサーバーは、/config/gitlab.ymlで指定されているように、独自の(Gitaly address, Gitaly token)ペアを使用して、自身に対してRPC呼び出しを実行できる必要があります。
  • 認証は、GitalyノードとGitLab Railsノード間で共有されるスタティックトークンを介して行われます。

次の図は、HTTPおよびHTTPs通信のデフォルトポートを示すGitalyサーバーとGitLab Rails間の通信を示しています。

情報を交換する2つのGitalyサーバーとGitLab Rails。

Gitalyのネットワークトラフィックはデフォルトで暗号化されていないため、Gitalyサーバーをパブリックインターネットに公開しないでください。Gitalyサーバーへのアクセスを制限するために、ファイアウォールの使用を強くお勧めします。別のオプションは、TLSを使用することです。

次のセクションでは、シークレットトークンabc123secretを使用して2つのGitalyサーバーを構成する方法について説明します:

  • gitaly1.internal
  • gitaly2.internal

お客様のGitLab環境には、3つのリポジトリストレージがあることを前提としています:

  • default
  • storage1
  • storage2

必要に応じて、1つのリポジトリストレージを備えたサーバーを少数使用できます。

Gitalyをインストールする

次のいずれかを使用して、各GitalyサーバーにGitalyをインストールします:

Gitalyサーバーを構成する

Gitalyサーバーを構成するには、次の操作を行う必要があります:

  • 認証を構成します。
  • リポジトリストレージのパスを構成します。
  • ネットワークリスナーを有効にします。

gitユーザーは、構成されたストレージパスに対する読み取り、書き込み、および権限の設定を実行できる必要があります。

Gitalyトークンのローテーション中にダウンタイムが発生しないように、gitaly['auth_transitioning']設定を使用して、一時的に認証を無効にすることができます。詳細については、認証移行モードの有効化を参照してください。

認証を構成する

GitalyとGitLabは、認証に2つの共有シークレットを使用します:

  • Gitalyトークン: GitalyへのgRPCリクエストを認証するために使用されます。
  • GitLab Shellトークン: GitLab ShellからGitLab内部APIへの認証コールバックに使用されます。
  1. _Gitalyトークン_を構成するには、/etc/gitlab/gitlab.rbを編集します:

    gitaly['configuration'] = {
       # ...
       auth: {
         # ...
         token: 'abc123secret',
       },
    }
  2. _GitLab Shellトークン_を構成するには、次の2つの方法があります:

    • 方法1(推奨: ): GitalyクライアントからGitalyサーバーおよびその他のGitalyクライアント上の同じパスに/etc/gitlab/gitlab-secrets.jsonをコピーします。

    • 方法2:

      1. GitLab Railsを実行しているすべてのノードで、/etc/gitlab/gitlab.rbを編集します。

      2. GITLAB_SHELL_SECRET_TOKENを実際のシークレットに置き換えます:

        • GitLab 17.5以降:

          gitaly['gitlab_secret'] = 'GITLAB_SHELL_SECRET_TOKEN'
        • GitLab 17.4以前:

          gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
      3. Gitalyを実行しているすべてのノードで、/etc/gitlab/gitlab.rbを編集します。

      4. GITLAB_SHELL_SECRET_TOKENを実際のシークレットに置き換えます:

        • GitLab 17.5以降:

          gitaly['gitlab_secret'] = 'GITLAB_SHELL_SECRET_TOKEN'
        • GitLab 17.4以前:

          gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
      5. これらの変更後、GitLabを再構成します:

      sudo gitlab-ctl reconfigure
  1. GitalyクライアントからGitalyサーバー(およびその他のGitalyクライアント)上の同じパスに/home/git/gitlab/.gitlab_shell_secretをコピーします。

  2. Gitalyクライアントで、/home/git/gitlab/config/gitlab.ymlを編集します:

    gitlab:
      gitaly:
        token: 'abc123secret'
  3. ファイルを保存して、GitLabを再起動します。

  4. Gitalyサーバーで、/home/git/gitaly/config.tomlを編集します:

    [auth]
    token = 'abc123secret'
  5. ファイルを保存して、GitLabを再起動します。

Gitalyサーバーを構成する

Gitalyサーバーを構成します。

  1. /etc/gitlab/gitlab.rbを編集します:

    # Avoid running unnecessary services on the Gitaly server
    postgresql['enable'] = false
    redis['enable'] = false
    nginx['enable'] = false
    puma['enable'] = false
    sidekiq['enable'] = false
    gitlab_workhorse['enable'] = false
    gitlab_exporter['enable'] = false
    gitlab_kas['enable'] = false
    
    # If you run a separate monitoring node you can disable these services
    prometheus['enable'] = false
    alertmanager['enable'] = false
    
    # If you don't run a separate monitoring node you can
    # enable Prometheus access & disable these extra services.
    # This makes Prometheus listen on all interfaces. You must use firewalls to restrict access to this address/port.
    # prometheus['listen_address'] = '0.0.0.0:9090'
    # prometheus['monitor_kubernetes'] = false
    
    # If you don't want to run monitoring services uncomment the following (not recommended)
    # node_exporter['enable'] = false
    
    # Prevent database connections during 'gitlab-ctl reconfigure'
    gitlab_rails['auto_migrate'] = false
    
    # 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.
    # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from Gitaly client to Gitaly server.
    gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
    
    gitaly['configuration'] = {
       # ...
       #
       # Make Gitaly accept connections on all network interfaces. You must use
       # firewalls to restrict access to this address/port.
       # Comment out following line if you only want to support TLS connections
       listen_addr: '0.0.0.0:8075',
       auth: {
         # ...
         #
         # Authentication token to ensure only authorized servers can communicate with
         # Gitaly server
         token: 'AUTH_TOKEN',
       },
    }
  2. それぞれのGitalyサーバーについて、次の内容を/etc/gitlab/gitlab.rbに追加します:

    gitaly1.internalの場合:

    gitaly['configuration'] = {
       # ...
       storage: [
          {
             name: 'default',
             path: '/var/opt/gitlab/git-data/repositories',
          },
          {
             name: 'storage1',
             path: '/mnt/gitlab/git-data/repositories',
          },
       ],
    }

    gitaly2.internalの場合:

    gitaly['configuration'] = {
       # ...
       storage: [
          {
             name: 'storage2',
             path: '/srv/gitlab/git-data/repositories',
          },
       ],
    }
  3. ファイルを保存してGitLabを再設定します。

  4. GitalyがGitLab内部APIにコールバックを実行できることを確認します:

    sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml
  1. /home/git/gitaly/config.tomlを編集します:

    listen_addr = '0.0.0.0:8075'
    
    runtime_dir = '/var/opt/gitlab/gitaly'
    
    [logging]
    format = 'json'
    level = 'info'
    dir = '/var/log/gitaly'
  2. それぞれのGitalyサーバーについて、次の内容を/home/git/gitaly/config.tomlに追加します:

    gitaly1.internalの場合:

    [[storage]]
    name = 'default'
    path = '/var/opt/gitlab/git-data/repositories'
    
    [[storage]]
    name = 'storage1'
    path = '/mnt/gitlab/git-data/repositories'

    gitaly2.internalの場合:

    [[storage]]
    name = 'storage2'
    path = '/srv/gitlab/git-data/repositories'
  3. /home/git/gitlab-shell/config.ymlを編集します:

    gitlab_url: https://gitlab.example.com
  4. ファイルを保存して、GitLabを再起動します。

  5. GitalyがGitLab内部APIにコールバックを実行できることを確認します:

    sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml

GitLabサーバーからGitalyにリポジトリデータを直接コピーする場合は、メタデータファイル(デフォルトパス/var/opt/gitlab/git-data/repositories/.gitaly-metadata)が転送に含まれていないことを確認してください。このファイルをコピーすると、GitLabがGitalyサーバーでホストされているリポジトリへの直接ディスクアクセスを使用するようになり、Error creating pipelineおよびCommit not foundエラー、または古いデータが発生します。

Gitalyクライアントを設定します

最後の手順として、Gitalyクライアントを更新して、ローカルのGitalyサービスの使用から、構成したばかりのGitalyサーバーを使用するように切り替える必要があります。

GitLabでは、defaultリポジトリストレージを構成する必要があります。この制限の詳細をご覧ください。

GitalyクライアントがGitalyサーバーにアクセスできなくなるようなことがあれば、すべてのGitalyリクエストが失敗するため、これは危険な場合があります。たとえば、ネットワーク、ファイアウォール、または名前解決の問題などです。

Gitalyは次のことを前提としています:

  • gitaly1.internal Gitalyサーバーには、Gitalyクライアントからgitaly1.internal:8075でアクセスでき、そのGitalyサーバーは/var/opt/gitlab/git-data/mnt/gitlab/git-dataの読み取り、書き込み、および権限の設定を実行できます。
  • gitaly2.internal Gitalyサーバーには、Gitalyクライアントからgitaly2.internal:8075でアクセスでき、そのGitalyサーバーは/srv/gitlab/git-dataの読み取り、書き込み、および権限の設定を実行できます。
  • gitaly1.internalおよびgitaly2.internal Gitalyサーバーは、相互にアクセスできます。

混合構成を使用しない限り、一部をローカルGitalyサーバー(gitaly_addressなし)として、一部をリモートサーバー(gitaly_addressあり)としてGitalyサーバーを定義することはできません。

次の2つの方法のいずれかでGitalyクライアントを構成します。これらの手順は暗号化されていない接続用ですが、TLSサポートを有効にすることもできます:

  1. /etc/gitlab/gitlab.rbを編集します:

    # Use the same token value configured on all Gitaly servers
    gitlab_rails['gitaly_token'] = '<AUTH_TOKEN>'
    
    gitlab_rails['repositories_storages'] = {
      'default'  => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
      'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
      'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
    }

    または、各Gitalyサーバーが異なる認証トークンを使用するように構成されている場合:

    gitlab_rails['repositories_storages'] = {
      'default'  => { 'gitaly_address' => 'tcp://gitaly1.internal:8075', 'gitaly_token' => '<AUTH_TOKEN_1>' },
      'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075', 'gitaly_token' => '<AUTH_TOKEN_1>' },
      'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075', 'gitaly_token' => '<AUTH_TOKEN_2>' },
    }
  2. ファイルを保存してGitLabを再設定します。

  3. Gitalyクライアント(たとえば、Railsアプリケーション)でsudo gitlab-rake gitlab:gitaly:checkを実行して、Gitalyサーバーに接続できることを確認します。

  4. ログを追跡してリクエストを確認します:

    sudo gitlab-ctl tail gitaly
  1. /home/git/gitlab/config/gitlab.ymlを編集します:

    gitlab:
      repositories:
        storages:
          default:
            gitaly_address: tcp://gitaly1.internal:8075
            gitaly_token: AUTH_TOKEN_1
          storage1:
            gitaly_address: tcp://gitaly1.internal:8075
            gitaly_token: AUTH_TOKEN_1
          storage2:
            gitaly_address: tcp://gitaly2.internal:8075
            gitaly_token: AUTH_TOKEN_2
  2. ファイルを保存して、GitLabを再起動します。

  3. sudo -u git -H bundle exec rake gitlab:gitaly:check RAILS_ENV=productionを実行して、GitalyクライアントがGitalyサーバーに接続できることを確認します。

  4. ログを追跡してリクエストを確認します:

    tail -f /home/git/gitlab/log/gitaly.log

GitalyサーバーのGitalyログをプルすると、リクエストが届いていることがわかります。Gitalyリクエストをトリガーする確実な方法の1つは、HTTPまたはHTTPS経由でGitLabからリポジトリをクローンすることです。

サーバーフックを構成している場合、リポジトリごとまたはグローバルに、これらをGitalyサーバーに移動する必要があります。複数のGitalyサーバーがある場合は、サーバーフックをすべてのGitalyサーバーにコピーします。

混合構成

GitLabは、多くのGitalyサーバーの1つと同じサーバー上に存在できますが、ローカル構成とリモート構成を混在させる構成はサポートされていません。次の設定は正しくありません。理由:

  • すべてのアドレスは、他のGitalyサーバーから到達できる必要があります。
  • storage1には、一部のGitalyサーバーに対して無効なgitaly_addressのUnixソケットが割り当てられています。
gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
  'storage1' => { 'gitaly_address' => 'unix:/var/opt/gitlab/gitaly/gitaly.socket' },
  'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
}

ローカルGitalyサーバーとリモートGitalyサーバーを組み合わせるには、ローカルGitalyサーバーに外部アドレスを使用します。例:

gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
  # Address of the GitLab server that also has Gitaly running on it
  'storage1' => { 'gitaly_address' => 'tcp://gitlab.internal:8075' },
  'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
}

gitaly['configuration'] = {
  # ...
  #
  # Make Gitaly accept connections on all network interfaces
  listen_addr: '0.0.0.0:8075',
  # Or for TLS
  tls_listen_addr: '0.0.0.0:9999',
  tls: {
    certificate_path:  '/etc/gitlab/ssl/cert.pem',
    key_path: '/etc/gitlab/ssl/key.pem',
  },
  storage: [
    {
      name: 'storage1',
      path: '/mnt/gitlab/git-data/repositories',
    },
  ],
}

pathは、ローカルGitalyサーバー上のストレージシャードに対してのみ含めることができます。除外した場合、そのストレージシャードにはデフォルトのGitストレージディレクトリが使用されます。

GitLabにはデフォルトのリポジトリストレージが必要です

Gitalyサーバーを環境に追加する場合、元のdefault Gitalyサービスを置き換えることができます。ただし、GitLabではdefaultというストレージが必要なため、defaultストレージを削除するようにGitLabアプリケーションサーバーを再構成することはできません。この制限事項の詳細についてをご覧ください。

制限を回避するには:

  1. 新しいGitalyサービス上に追加のストレージ場所を定義し、その追加のストレージがdefaultになるように構成します。ストレージの場所には、動作中のストレージを想定するデータベース移行の問題を回避するために、Gitalyサービスが実行されていて、利用可能である必要があります。
  2. 管理者エリアで、defaultをゼロのウェイトに設定して、リポジトリがそこに格納されないようにします。

不要なGitalyを無効にする(オプション)

Gitalyをリモートサービスとして実行する場合は、デフォルトでGitLabサーバー上で実行されるローカルGitalyサービスを無効にすることを検討し、必要な場合にのみ実行します。

GitalyをGitLabインスタンス上で無効にすることは、GitalyがGitLabインスタンスとは別のマシン上で実行されるカスタムクラスター構成でGitLabを実行する場合にのみ意味があります。クラスター内のすべてのマシンでGitalyを無効にすることは、有効な構成ではありません(一部のマシンはGitalyサーバーとして動作する必要があります)。

次の2つの方法のいずれかで、GitLabサーバー上のGitalyを無効にします:

  1. /etc/gitlab/gitlab.rbを編集します:

    gitaly['enable'] = false
  2. ファイルを保存してGitLabを再設定します。

  1. /etc/default/gitlabを編集します:

    gitaly_enabled=false
  2. ファイルを保存して、GitLabを再起動します。

Gitalyリスナーインターフェースを変更する

Gitalyがリッスンするインターフェースを変更できます。Gitalyと通信する必要のある外部サービスがある場合は、リスナーインターフェースを変更することがあります。たとえば、完全一致コードの検索が有効になっているが、実際のサービスが別のサーバーで実行されている場合にZoektを使用する完全一致コードの検索などです。

gitaly_tokenは、gitaly_tokenがGitalyサービスとの認証に使用されるため、シークレット文字列である必要があります。このシークレットは、ランダムな32文字の文字列を生成するためにopenssl rand -base64 24で生成できます。

たとえば、Gitalyリスナーインターフェースを0.0.0.0:8075に変更するには:

# /etc/gitlab/gitlab.rb
# Add a shared token for Gitaly authentication
gitlab_shell['secret_token'] = 'your_secure_token_here'
gitlab_rails['gitaly_token'] = 'your_secure_token_here'

# Gitaly configuration
gitaly['gitlab_secret'] = 'your_secure_token_here'
gitaly['configuration'] = {
  listen_addr: '0.0.0.0:8075',
  auth: {
    token: 'your_secure_token_here',
  },
  storage: [
    {
      name: 'default',
      path: '/var/opt/gitlab/git-data/repositories',
    },
  ]
}

# Tell Rails where to find Gitaly
gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://ip_address_here:8075' },
}

# Internal API URL (important for multi-server setups)
gitlab_rails['internal_api_url'] = 'http://ip_address_here'

コントロールグループ

コントロールグループの詳細については、Cgroupsを参照してください。

バックグラウンドリポジトリの最適化

Gitリポジトリのオブジェクトデータベースにデータが格納される方法は、時間の経過とともに非効率になる可能性があり、Git操作が遅くなります。これらのアイテムをクリーンアップしてパフォーマンスを向上させるために、最大期間で毎日のバックグラウンドタスクを実行するようにGitalyをスケジュールできます。

バックグラウンドリポジトリの最適化は、実行中にホストに大きな負荷をかける可能性があります。ピーク時以外の時間にスケジュールし、期間を短く(たとえば、30〜60分)してください。

次の2つの方法のいずれかで、バックグラウンドリポジトリの最適化を構成します:

/etc/gitlab/gitlab.rbを編集して、以下を追加します:

gitaly['configuration'] = {
  # ...
  daily_maintenance: {
    # ...
    start_hour: 4,
    start_minute: 30,
    duration: '30m',
    storages: ['default'],
  },
}

/home/git/gitaly/config.tomlを編集して、以下を追加します:

[daily_maintenance]
start_hour = 4
start_minute = 30
duration = '30m'
storages = ["default"]

Gitaly認証トークンをローテーションする

本番環境で認証情報をローテーションすると、ダウンタイムが必要になったり、停止が発生したりすることがよくあります。

ただし、サービスを中断することなく、Gitaly認証情報をローテーションできます。Gitaly認証トークンのローテーションには、次のものがあります:

この手順は、単一サーバー上でGitLabを実行している場合にも機能します。その場合、GitalyサーバーとGitalyクライアントは同じマシンを参照します。

認証モニタリングを検証する

Gitaly認証トークンをローテーションする前に、Prometheusを使用してGitLabインストールの認証動作をモニタリングできることを確認してください。

その後、手順の残りを続行できます。

認証移行モードを有効にする

次の手順に従って、Gitalyサーバーを認証移行モードにすることで、GitalyサーバーでのGitaly認証を一時的に無効にします:

# in /etc/gitlab/gitlab.rb
gitaly['configuration'] = {
  # ...
  auth: {
    # ...
    transitioning: true,
  },
}

この変更を加えた後、Prometheusクエリは次のようなものを返すはずです:

{enforced="false",status="would be ok"}  4424.985419441742

enforced="false"のため、新しいトークンのロールアウトを開始しても安全です。

Gitaly認証トークンを更新する

新しいGitaly認証トークンに更新するには、各GitalyクライアントおよびGitalyサーバーで次の手順を実行します:

  1. 設定を更新します:

    # in /etc/gitlab/gitlab.rb
    gitaly['configuration'] = {
       # ...
       auth: {
          # ...
          token: '<new secret token>',
       },
    }
  2. Gitalyを再起動します:

    gitlab-ctl restart gitaly

この変更のロールアウト中にPrometheusクエリを実行すると、enforced="false",status="denied"カウンターにゼロ以外の値が表示されます。

認証の失敗がないことを確認する

新しいトークンが設定され、関係するすべてのサービスが再起動された後、次のものが一時的に表示されます:

  • status="would be ok"
  • status="denied"

新しいトークンがすべてのGitalyクライアントとGitalyサーバーによってプルされた後、ゼロ以外のレートはenforced="false",status="would be ok"のみになります。

認証移行モードを無効にする

Gitaly認証を再度有効にするには、認証移行モードを無効にします。次の手順に従って、Gitalyサーバーで構成を更新します:

# in /etc/gitlab/gitlab.rb
gitaly['configuration'] = {
  # ...
  auth: {
    # ...
    transitioning: false,
  },
}

この手順を完了しないと、Gitaly認証は行われません。

認証が適用されていることを確認する

Prometheusクエリを更新します。これで、開始時と同じような結果が表示されるはずです。例:

{enforced="true",status="ok"}  4424.985419441742

enforced="true"は、認証が適用されていることを意味します。

Pack-objectsキャッシュ

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

Gitaly(Gitリポジトリのストレージを提供するサービス)は、Gitフェッチ応答の短いローリングウィンドウをキャッシュするように構成できます。これにより、サーバーが大量のCIフェッチトラフィックを受信した場合に、サーバーの負荷を軽減できます。

パックオブジェクトのキャッシュは、Gitの内部的な部分であるgit pack-objectsをラップし、PostUploadPackおよびSSHUploadPack Gitaly RPCを使用して間接的に呼び出されます。ユーザーがHTTPを使用してGitフェッチを実行すると、GitalyはPostUploadPackを実行し、ユーザーがSSHを使用してGitフェッチを実行すると、SSHUploadPackを実行します。キャッシュが有効になっている場合、PostUploadPackまたはSSHUploadPackを使用するものはすべて、そのメリットをプルできます。以下とは無関係で、影響を受けません:

  • トランスポート(HTTPまたはSSH)。
  • Gitプロトコルバージョン(v0またはv2)。
  • フルクローン、増分フェッチ、シャロークローン、または部分クローンなどのフェッチのタイプ。

このキャッシュの強みは、同時実行される同一のフェッチを重複排除できることです。それは:

  • ユーザーが多数の同時ジョブでCI/CDパイプラインを実行するGitLabインスタンスに役立ちます。サーバーのCPU使用率が大幅に低下するはずです。
  • まったく独自のフェッチにはメリットがありません。たとえば、リポジトリをローカルコンピューターにクローンしてスポットチェックを実行する場合、フェッチはおそらく一意であるため、このキャッシュからメリットが得られる可能性は低いです。

パックオブジェクトのキャッシュはローカルキャッシュです。それは:

  • 有効になっているGitalyプロセスのメモリにメタデータを格納します。
  • ローカルストレージ上のファイルにキャッシュしている実際のGitデータを格納します。

ローカルファイルを使用すると、オペレーティングシステムがパックオブジェクトのキャッシュファイルの一部をRAMに自動的に保持し、高速化できるというメリットがあります。

パックオブジェクトのキャッシュにより、ディスク書き込みIOが大幅に増加する可能性があるため、デフォルトではオフになっています。

設定を構成

これらの構成設定は、パックオブジェクトのキャッシュで使用できます。各設定については、以下で詳しく説明します。

設定デフォルト説明
enabledfalseキャッシュをオンにします。オフの場合、Gitalyはリクエストごとに専用のgit pack-objectsプロセスを実行します。
dir<PATH TO FIRST STORAGE>/+gitaly/PackObjectsCacheキャッシュファイルを格納するローカルディレクトリ。
max_age5m(5分)これより古いエントリは削除され、ディスクから削除されます。
min_occurrences1キャッシュエントリが作成される前に、キーが発生する必要がある最小回数。

/etc/gitlab/gitlab.rbで、次のように設定します:

gitaly['configuration'] = {
  # ...
  pack_objects_cache: {
    enabled: true,
    # The default settings for "dir", "max_age" and "min_occurences" should be fine.
    # If you want to customize these, see details below.
  },
}

enabledのデフォルトはfalse

キャッシュは、極端な増加を招く場合があるため、デフォルトで無効になっています。GitLab.comでは、リポジトリストレージディスクがこの追加のワークロードを処理できることを確認していますが、どこでもこれが当てはまるとは限りません。

キャッシュストレージディレクトリdir

キャッシュには、ファイルを格納するためのディレクトリが必要です。このディレクトリは次のようになります:

  • 十分なスペースのあるファイルシステム内。キャッシュファイルシステムのスペースがなくなると、すべてのフェッチが失敗し始めます。
  • 十分なIO帯域幅を持つディスク上。キャッシュディスクのIO帯域幅がなくなると、すべてのフェッチ、おそらくサーバー全体が遅くなります。

指定されたディレクトリ内の既存のデータはすべて削除されます。既存のデータを含むディレクトリは使用しないように注意してください。

デフォルトでは、キャッシュストレージディレクトリは、設定ファイルで定義されている最初のGitalyストレージのサブディレクトリに設定されます。

複数のGitalyプロセスで、キャッシュストレージに同じディレクトリを使用できます。各Gitalyプロセスは、作成するキャッシュファイル名の一部として、一意のランダム文字列を使用します。これは、次の意味をもちます:

  • 衝突しません。
  • 別のプロセスのファイルを再利用しません。

デフォルトのディレクトリは、リポジトリデータと同じファイルシステムにキャッシュファイルをパックしますが、これは要件ではありません。インフラストラクチャに適している場合は、キャッシュファイルを別のファイルシステムにパックできます。

ディスクから必要なIO帯域幅の量は、次によって異なります:

  • Gitalyサーバー上のリポジトリのサイズと形状。
  • ユーザーが生成するタイプのトラフィック。

キャッシュヒット率が0%であると仮定して、gitaly_pack_objects_generated_bytes_totalメトリクスを悲観的な見積もりとして使用できます。

必要なスペースの量は、次によって異なります:

  • ユーザーがキャッシュからプルする1秒あたりのバイト数。
  • max_ageキャッシュ削除ウィンドウのサイズ。

ユーザーが100 MB/秒をプルし、5分のウィンドウを使用すると、平均して5*60*100 MB = 30 GBのデータがキャッシュディレクトリにパックされます。この平均は、保証ではなく、予想される平均です。ピークサイズがこの平均を超える場合があります。

キャッシュ削除ウィンドウmax_age

max_age構成設定を使用すると、キャッシュヒットの可能性と、キャッシュファイルで使用されるストレージの平均量を制御できます。max_ageより古いエントリはディスクから削除されます。

削除は、進行中のリクエストを妨げません。Unixファイルシステムは、削除されたファイルを読み取っているすべてのプロセスがファイルを閉じるまで、ファイルを実際に削除しないため、低速接続でフェッチを実行するのにかかる時間よりもmax_ageが短くても問題ありません。

キーの発生回数min_occurrences

min_occurrences設定は、新しいキャッシュエントリを作成する前に、同一のリクエストが発生する必要がある頻度を制御します。デフォルト値は1で、一意のリクエストはキャッシュに書き込まれません。

次の場合:

  • この数値を増やすと、キャッシュヒット率が低下し、キャッシュの使用ディスクスペースが少なくなります。
  • この数値を減らすと、キャッシュヒット率が上がり、キャッシュの使用ディスクスペースが増えます。

min_occurrences1に設定する必要があります。GitLab.comでは、0から1にすると、キャッシュヒット率にほとんど影響を与えずに、キャッシュディスクスペースが50%節約されました。

キャッシュを監視する

メトリクスを使用して、および次のログに記録された情報でキャッシュを監視できます。これらのログはgRPCログの一部であり、呼び出しが実行されると検出できます。

フィールド説明
pack_objects_cache.hit現在のパックオブジェクトのキャッシュがヒットしたかどうかを示します(trueまたはfalse)。
pack_objects_cache.keyパックオブジェクトのキャッシュに使用されるキーです
pack_objects_cache.generated_bytes書き込まれている新しいキャッシュのサイズ(バイト単位)
pack_objects_cache.served_bytes処理されているキャッシュのサイズ(バイト単位)
pack_objects.compression_statisticsパックオブジェクトの生成に関する統計
pack_objects.enumerate_objects_msクライアントから送信されたオブジェクトの列挙に費やされた合計時間(ミリ秒単位)
pack_objects.prepare_pack_msクライアントに送り返す前に、パックファイルの準備に費やされた合計時間(ミリ秒単位)
pack_objects.write_pack_file_msクライアントにパックファイルを送り返すのに費やされた合計時間(ミリ秒単位)。クライアントのインターネット接続に大きく依存します
pack_objects.written_object_countGitalyがクライアントに送り返すオブジェクトの合計数

次の場合:

  • キャッシュミス、Gitalyはpack_objects_cache.generated_bytesメッセージとpack_objects_cache.served_bytesメッセージの両方をログに記録します。Gitalyは、パックオブジェクトの生成に関するより詳細な統計もログに記録します。
  • キャッシュヒット、Gitalyはpack_objects_cache.served_bytesメッセージのみをログに記録します。

例:

{
  "bytes":26186490,
  "correlation_id":"01F1MY8JXC3FZN14JBG1H42G9F",
  "grpc.meta.deadline_type":"none",
  "grpc.method":"PackObjectsHook",
  "grpc.request.fullMethod":"/gitaly.HookService/PackObjectsHook",
  "grpc.request.glProjectPath":"root/gitlab-workhorse",
  "grpc.request.glRepository":"project-2",
  "grpc.request.repoPath":"@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git",
  "grpc.request.repoStorage":"default",
  "grpc.request.topLevelGroup":"@hashed",
  "grpc.service":"gitaly.HookService",
  "grpc.start_time":"2021-03-25T14:57:52.747Z",
  "level":"info",
  "msg":"finished unary call with code OK",
  "peer.address":"@",
  "pid":20961,
  "span.kind":"server",
  "system":"grpc",
  "time":"2021-03-25T14:57:53.543Z",
  "pack_objects.compression_statistics": "Total 145991 (delta 68), reused 6 (delta 2), pack-reused 145911",
  "pack_objects.enumerate_objects_ms": 170,
  "pack_objects.prepare_pack_ms": 7,
  "pack_objects.write_pack_file_ms": 786,
  "pack_objects.written_object_count": 145991,
  "pack_objects_cache.generated_bytes": 49533030,
  "pack_objects_cache.hit": "false",
  "pack_objects_cache.key": "123456789",
  "pack_objects_cache.served_bytes": 49533030,
  "peer.address": "127.0.0.1",
  "pid": 8813,
}

cat-fileキャッシュ

多くのGitaly RPCは、リポジトリからGitオブジェクトを検索する必要があります。ほとんどの場合、git cat-file --batchプロセスを使用します。パフォーマンスを向上させるために、Gitalyはこれらのgit cat-fileプロセスをRPC呼び出し全体で再利用できます。以前に使用されたプロセスは、git cat-fileキャッシュに保持されます。システムリソースの消費量を制御するために、キャッシュにパックできるcat-fileプロセスの最大数があります。

デフォルトの制限は100 cat-fileであり、git cat-file --batchおよびgit cat-file --batch-checkプロセスのペアを構成します。“too many open files"に関するエラー、または新しいプロセスを作成できないというエラーが表示される場合は、この制限を下げたい場合があります。

理想的には、この数は標準的なトラフィックを処理するのに十分な大きさである必要があります。制限を引き上げる場合は、前後にキャッシュヒット率を測定する必要があります。ヒット率が向上しない場合、制限を高くしても意味のある違いは生じない可能性があります。ヒット率を確認するためのPrometheusクエリの例を次に示します:

sum(rate(gitaly_catfile_cache_total{type="hit"}[5m])) / sum(rate(gitaly_catfile_cache_total{type=~"(hit)|(miss)"}[5m]))

Gitaly構成ファイルでcat-fileキャッシュを設定します。

GitLab UIコミットのコミット署名を構成する

GitLab Self-Managedでは、デフォルトでこの機能を利用できます。この機能を非表示にするために、管理者はgitaly_gpg_signingという名前の機能フラグを無効にできます。GitLab.comでは、この機能は利用できません。GitLab Dedicatedでは、この機能は利用できません。

デフォルトでは、GitalyはGitLab UIを使用して作成されたコミットに署名しません。たとえば、次を使用して作成されたコミット:

  • Webエディタ。
  • Web IDE。
  • マージリクエスト。

Gitalyでコミット署名を有効にすると:

  • GitLabは、UIを介して作成されたすべてのコミットに署名します。
  • 署名は、作成者のIDではなく、コミッターのIDを検証します。
  • committer_emailcommitter_nameを設定することで、コミットがインスタンスによってコミットされたことを反映するようにGitalyを構成できます。たとえば、GitLab.comでは、これらの構成オプションはnoreply@gitlab.comGitLabに設定されています。

rotated_signing_keysは、検証にのみ使用するキーのリストです。Gitalyは、設定されたsigning_keyを使用してWebコミットを検証しようとし、成功するまでローテーションされたキーを1つずつ使用します。いずれかの場合、rotated_signing_keysオプションを設定します:

  • 署名キーがローテーションされます。
  • 他のインスタンスからプロジェクトを移行するための複数のキーを指定し、Webコミットを検証済みとして表示する場合。

GitLab UIで作成されたコミットに署名するようにGitalyを構成するには、次の2つの方法があります:

  1. GPGキーを作成してエクスポートするか、SSHキーを作成します。最適なパフォーマンスを得るには、EdDSAキーを使用します。

    エクスポートGPGキー:

    gpg --export-secret-keys <ID> > signing_key.gpg

    または、(パスフレーズなしで)SSHキーを作成します:

    ssh-keygen -t ed25519 -f signing_key.ssh
  2. Gitalyノードで、キーを/etc/gitlab/gitaly/にコピーし、gitユーザーにファイルを読み取る権限があることを確認します。

  3. /etc/gitlab/gitlab.rbを編集し、gitaly['git']['signing_key']を構成します:

    gitaly['configuration'] = {
       # ...
       git: {
         # ...
         committer_name: 'Your Instance',
         committer_email: 'noreply@yourinstance.com',
         signing_key: '/etc/gitlab/gitaly/signing_key.gpg',
         rotated_signing_keys: ['/etc/gitlab/gitaly/previous_signing_key.gpg'],
         # ...
       },
    }
  4. ファイルを保存してGitLabを再設定します。

  1. GPGキーを作成してエクスポートするか、SSHキーを作成します。最適なパフォーマンスを得るには、EdDSAキーを使用します。

    エクスポートGPGキー:

    gpg --export-secret-keys <ID> > signing_key.gpg

    または、(パスフレーズなしで)SSHキーを作成します:

    ssh-keygen -t ed25519 -f signing_key.ssh
  2. Gitalyノードで、キーを/etc/gitlabにコピーします。

  3. /home/git/gitaly/config.tomlを編集し、signing_keyを構成します:

    [git]
    committer_name = "Your Instance"
    committer_email = "noreply@yourinstance.com"
    signing_key = "/etc/gitlab/gitaly/signing_key.gpg"
    rotated_signing_keys = ["/etc/gitlab/gitaly/previous_signing_key.gpg"]
  4. ファイルを保存して、GitLabを再起動します。

外部コマンドを使用して設定を生成する

外部コマンドを使用して、Gitaly構成の一部を生成できます。これは、次の場合に行うことができます:

  • 各ノードに完全な構成を配布しなくても、ノードを設定するため。
  • ノードの設定の自動検出を使用して構成するため。たとえば、DNSエントリを使用します。
  • ノードの起動時にシークレットを設定し、プレーンテキストで表示する必要がないようにするため。

外部コマンドを使用して設定を生成するには、Gitalyノードの目的の設定をJSON形式で標準出力にダンプするスクリプトを提供する必要があります。

たとえば、次のコマンドは、AWSシークレットを使用してGitLab内部APIへの接続に使用されるHTTPパスワードを設定します:

#!/usr/bin/env ruby
require 'json'
JSON.generate({"gitlab": {"http_settings": {"password": `aws get-secret-value --secret-id ...`}}})

次に、スクリプトのパスをGitalyに次の2つの方法のいずれかで認識させる必要があります:

/etc/gitlab/gitlab.rbを編集し、config_commandを構成します:

gitaly['configuration'] = {
    config_command: '/path/to/config_command',
}

/home/git/gitaly/config.tomlを編集し、config_commandを構成します:

config_command = "/path/to/config_command"

設定後、Gitalyは起動時にコマンドを実行し、標準出力をJSONとして解析中します。結果として得られる設定は、他のGitaly構成にマージされます。

Gitalyは、次のいずれかの場合に起動に失敗します:

  • 構成コマンドが失敗します。
  • コマンドによって生成された出力を有効なJSONとして解析できません。

サーバー側のバックアップを構成する

リポジトリバックアップは、各リポジトリをホストするGitalyノードがバックアップの作成とオブジェクトストレージへのストリーミングを担当するように構成できます。これにより、バックアップの作成と復元に必要なネットワークリソースを削減できます。

各Gitalyノードは、バックアップのためにオブジェクトストレージに接続するように構成する必要があります。

サーバー側のバックアップを構成した後、サーバー側のリポジトリバックアップを作成できます。

Azure Blob Storageを設定するには、次の手順に従います。

バックアップのためにAzure BLOBストレージを構成する方法は、お使いのインストールの種類によって異なります。セルフコンパイルインストールでは、AZURE_STORAGE_ACCOUNTAZURE_STORAGE_KEYの環境変数をGitLabの外部に設定する必要があります。

/etc/gitlab/gitlab.rbを編集し、go_cloud_urlを構成します:

gitaly['env'] = {
    'AZURE_STORAGE_ACCOUNT' => 'azure_storage_account',
    'AZURE_STORAGE_KEY' => 'azure_storage_key' # or 'AZURE_STORAGE_SAS_TOKEN'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 'azblob://<bucket>'
    }
}

Helmベースのデプロイについては、Gitalyチャートのサーバー側のバックアップドキュメントを参照してください。

/home/git/gitaly/config.tomlを編集し、go_cloud_urlを構成します:

[backup]
go_cloud_url = "azblob://<bucket>"

Google Cloud Storageを構成する

Google Cloud Storage(GCP)は、アプリケーションデフォルトの認証情報を使用して認証します。各Gitalyサーバーで、次のいずれかの方法でアプリケーションデフォルトの認証情報を設定します:

  • gcloud auth application-default loginコマンド。
  • GOOGLE_APPLICATION_CREDENTIALS環境変数。セルフコンパイルインストールの場合、環境変数をGitLabの外部に設定します。

詳細については、アプリケーションデフォルトの認証情報を参照してください。

宛先バケットは、go_cloud_urlオプションを使用して構成されます。

/etc/gitlab/gitlab.rbを編集し、go_cloud_urlを構成します:

gitaly['env'] = {
    'GOOGLE_APPLICATION_CREDENTIALS' => '/path/to/service.json'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 'gs://<bucket>'
    }
}

Helmベースのデプロイについては、Gitalyチャートのサーバー側のバックアップドキュメントを参照してください。

/home/git/gitaly/config.tomlを編集し、go_cloud_urlを構成します:

[backup]
go_cloud_url = "gs://<bucket>"

S3ストレージを構成する

S3ストレージの認証を構成するには、以下を実行します:

  • AWS CLIで認証する場合は、デフォルトのAWSセッションを使用できます。
  • それ以外の場合は、AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYの環境変数を使用できます。セルフコンパイルインストールでは、環境変数をGitLabの外部に設定します。

詳細については、AWSセッションのドキュメントを参照してください。

宛先バケットとAWSリージョンは、go_cloud_urlオプションを使用して構成されます。

/etc/gitlab/gitlab.rbを編集し、go_cloud_urlを構成します:

gitaly['env'] = {
    'AWS_ACCESS_KEY_ID' => 'aws_access_key_id',
    'AWS_SECRET_ACCESS_KEY' => 'aws_secret_access_key'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 's3://<bucket>?region=us-west-1'
    }
}

Helmベースのデプロイについては、Gitalyチャートのサーバー側のバックアップドキュメントを参照してください。

/home/git/gitaly/config.tomlを編集し、go_cloud_urlを構成します:

[backup]
go_cloud_url = "s3://<bucket>?region=us-west-1"

S3互換サーバーを構成する

MinIOなどのS3互換サーバーは、endpointパラメータを追加して、S3と同様に構成されます。

次のパラメータがサポートされています:

  • region: AWSリージョン。
  • endpoint: は、エンドポイントのURLです。
  • disabledSSL: trueの値は、SSLを無効にします。
  • s3ForcePathStyle: trueの値は、パススタイルのアドレス指定を強制します。

Helmベースのデプロイについては、Gitalyチャートのサーバー側のバックアップドキュメントを参照してください。

/etc/gitlab/gitlab.rbを編集し、go_cloud_urlを構成します:

gitaly['env'] = {
    'AWS_ACCESS_KEY_ID' => 'minio_access_key_id',
    'AWS_SECRET_ACCESS_KEY' => 'minio_secret_access_key'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 's3://<bucket>?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true'
    }
}

/home/git/gitaly/config.tomlを編集し、go_cloud_urlを構成します:

[backup]
go_cloud_url = "s3://<bucket>?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true"