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

GitLabパッケージのバンドルされたPumaインスタンスを設定する

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

Pumaは、Rubyアプリケーション向けの高速、マルチスレッド、高度な並行処理が可能なHTTP 1.1サーバーです。これは、GitLabのユーザー向け機能を提供するコアRailsアプリケーションを実行します。

メモリ使用量の削減

メモリ使用量を削減するために、Pumaはワーカープロセスをフォークします。ワーカーが作成されるたびに、プライマリプロセスとメモリ使用量を共有します。ワーカーは、メモリ使用量ページを変更または追加する場合にのみ、追加のメモリ使用量を使用します。これにより、ワーカーが追加のWebリクエストを処理するにつれて、Pumaワーカーが時間の経過とともにより多くの物理メモリ使用量を使用する可能性があります。時間の経過とともに使用されるメモリ使用量は、GitLabの使用状況によって異なります。GitLabユーザーが使用する機能が多いほど、時間の経過とともに予想されるメモリ使用量が高くなります。

制御されないメモリ使用量の増加を止めるため、GitLab Railsアプリケーションは、特定の時間に対して、指定された常駐セットサイズ(RSS)のしきい値を超えた場合、ワーカーを自動的に再起動する監視スレッドを実行します。

GitLabは、メモリ使用量制限のデフォルトを1200Mbに設定します。デフォルト値をオーバーライドするには、per_worker_max_memory_mbを新しいRSS制限(MB単位)に設定します:

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

    puma['per_worker_max_memory_mb'] = 1024 # 1 GB
  2. GitLabを再設定します:

    sudo gitlab-ctl reconfigure

ワーカーを再起動すると、GitLabを実行する能力が短時間低下します。ワーカーの交換頻度が高すぎる場合は、per_worker_max_memory_mbをより高い値に設定します。

ワーカー数は、CPUコアに基づいて計算されます。4〜8個のワーカーを持つ小規模なGitLabデプロイでは、ワーカーの再起動頻度が高すぎる場合(1分間に1回以上)、パフォーマンスの問題が発生する可能性があります。

サーバーに空きメモリ使用量がある場合、1200以上の値を大きくすると効果がある可能性があります。

データベース接続の計画

Pumaのワーカーまたはスレッドを増やす前に、PostgreSQLのmax_connections設定に対するデータベース接続の影響を考慮してください。

詳細な接続計画と計算については、PostgreSQLのチューニングページを参照してください。

ワーカーの再起動を監視する

メモリ使用量が多いことが原因でワーカーが再起動された場合、GitLabはログイベントを生成します。

以下は、/var/log/gitlab/gitlab-rails/application_json.logのこれらのログイベントの1つの例です:

{
  "severity": "WARN",
  "time": "2023-01-04T09:45:16.173Z",
  "correlation_id": null,
  "pid": 2725,
  "worker_id": "puma_0",
  "memwd_handler_class": "Gitlab::Memory::Watchdog::PumaHandler",
  "memwd_sleep_time_s": 5,
  "memwd_rss_bytes": 1077682176,
  "memwd_max_rss_bytes": 629145600,
  "memwd_max_strikes": 5,
  "memwd_cur_strikes": 6,
  "message": "rss memory limit exceeded"
}

memwd_rss_bytesは実際に消費されたメモリ使用量であり、memwd_max_rss_bytesper_worker_max_memory_mbを介して設定されたRSS制限です。

ワーカータイムアウトを変更する

デフォルトのPuma タイムアウトは60秒です。

puma['worker_timeout']設定は、最大リクエスト時間を設定するものではありません。

ワーカータイムアウトを600秒に変更するには:

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

    gitlab_rails['env'] = {
       'GITLAB_RAILS_RACK_TIMEOUT' => 600
     }
  2. GitLabを再設定します:

    sudo gitlab-ctl reconfigure

メモリ使用量が制限された環境でPumaクラスタ化モードを無効にする

これは実験的機能であり、予告なく変更される場合があります。この機能は本番環境での使用には対応していません。この機能を使用する場合は、まず本番環境以外でテストする必要があります。詳細については、既知の問題を参照してください。

メモリ使用量が制限された環境で、使用可能なRAMが4 GB未満の場合は、Pumaのクラスタ化モードを無効にすることを検討してください。

workersの数を0に設定して、数百MB単位でメモリ使用量を削減します:

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

    puma['worker_processes'] = 0
  2. GitLabを再設定します:

    sudo gitlab-ctl reconfigure

デフォルトでセットアップされているクラスタ化モードとは異なり、単一のPumaプロセスのみがアプリケーションを提供します。Pumaのワーカーとスレッドの設定の詳細については、Pumaの要件を参照してください。

この設定でPumaを実行することの短所は、スループットが低下することです。これは、メモリ使用量が制限された環境では公平なトレードオフと見なすことができます。

メモリ使用量不足(OOM)状態を回避するために、十分なスワップを確保してください。詳細については、メモリ使用量の要件をご覧ください。

Pumaシングルモードの既知の問題

シングルモードでPumaを実行する場合、一部の機能はサポートされていません:

詳細については、エピック5303を参照してください。

SSL経由でリッスンするようにPumaを設定する

Linuxパッケージのインストールでデプロイすると、PumaはデフォルトでUnixソケットを介してリッスンします。代わりにHTTPSポートを介してリッスンするようにPumaを設定するには、以下の手順に従ってください:

  1. PumaがリッスンするアドレスのSSL証明書キーペアを生成します。以下の例では、これは127.0.0.1です。

    カスタム認証局からの自己署名証明書を使用している場合は、他のGitLabコンポーネントから信頼されるように、ドキュメントに従ってください。

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

    puma['ssl_listen'] = '127.0.0.1'
    puma['ssl_port'] = 9111
    puma['ssl_certificate'] = '<path_to_certificate>'
    puma['ssl_certificate_key'] = '<path_to_key>'
    
    # Disable UNIX socket
    puma['socket'] = ""
  3. GitLabを再設定します:

    sudo gitlab-ctl reconfigure

Unixソケットに加えて、PumaはPrometheusによってスクレイプされるメトリクスを提供するために、ポート8080でHTTPを介してリッスンします。PrometheusにHTTPS経由でそれらをスクレイプさせることはできず、それに対するサポートがこのイシューで議論されています。したがって、Prometheusメトリクスを失うことなく、このHTTPリスナーをオフにすることは技術的に不可能です。

暗号化されたSSLキーの使用

Pumaは、ランタイム時に復号化することができる、暗号化されたプライベートSSLキーの使用をサポートしています。以下の手順は、これを行う方法を示しています:

  1. キーがまだ暗号化されていない場合は、パスワードで暗号化します:

    openssl rsa -aes256 -in /path/to/ssl-key.pem -out /path/to/encrypted-ssl-key.pem

    暗号化されたファイルを書き込むには、パスワードを2回入力します。この例では、some-password-hereを使用します。

  2. パスワードを出力するスクリプトまたは実行可能ファイルを作成します。たとえば、パスワードをエコーする/var/opt/gitlab/gitlab-rails/etc/puma-ssl-key-passwordに基本的なスクリプトを作成します:

    #!/bin/sh
    echo some-password-here

    パスワードをディスクに保存することは避け、Vaultなどのパスワード取得ための安全なメカニズムを使用してください。たとえば、スクリプトは次のようになります:

    #!/bin/sh
    export VAULT_ADDR=http://vault-password-distribution-point:8200
    export VAULT_TOKEN=<some token>
    
    echo "$(vault kv get -mount=secret puma-ssl-password)"
  3. Pumaプロセスに、スクリプトを実行し、暗号化されたキーを読み取りるための十分な権限があることを確認します:

    chown git:git /var/opt/gitlab/gitlab-rails/etc/puma-ssl-key-password
    chmod 770 /var/opt/gitlab/gitlab-rails/etc/puma-ssl-key-password
    chmod 660 /path/to/encrypted-ssl-key.pem
  4. /etc/gitlab/gitlab.rbを編集し、puma['ssl_certificate_key']を暗号化されたキーに置き換え、puma['ssl_key_password_command]を指定します:

    puma['ssl_certificate_key'] = '/path/to/encrypted-ssl-key.pem'
    puma['ssl_key_password_command'] = '/var/opt/gitlab/gitlab-rails/etc/puma-ssl-key-password'
  5. GitLabを再設定します:

    sudo gitlab-ctl reconfigure
  6. GitLabが正常に起動した場合は、GitLabインスタンスに保存されている暗号化されていないSSLキーを削除できるはずです。

UnicornからPumaへのスイッチ

Helmベースのデプロイについては、webserviceチャートドキュメントを参照してください。

PumaはデフォルトのWebサーバーであり、Unicornはサポートされなくなりました。

Pumaは、Unicornのようなマルチプロセスアプリケーションサーバーよりも少ないメモリ使用量を使用するマルチスレッドアーキテクチャを備えています。GitLab.comでは、メモリ使用量が40%削減されました。ほとんどのRailsアプリケーションリクエストには、通常、I/O待機時間の割合が含まれています。

I/O待機時間中、MRI RubyはGVLを他のスレッドにリリースします。したがって、マルチスレッドPumaは、単一のプロセスよりも多くのリクエストを処理できます。

Pumaにスイッチする場合、2つのアプリケーションサーバーの違いにより、Unicornサーバーの設定が自動的に引き継がれることはありません。

UnicornからPumaにスイッチするには:

  1. 適切なPumaワーカーとスレッドの設定を決定します。

  2. /etc/gitlab/gitlab.rbで、カスタムUnicorn設定をPumaに変換します。

    以下の表は、Linuxパッケージを使用する場合、どのUnicorn設定キーがPumaのキーに対応し、対応するキーがないかを示しています。

    UnicornPuma
    unicorn['enable']puma['enable']
    unicorn['worker_timeout']puma['worker_timeout']
    unicorn['worker_processes']puma['worker_processes']
    該当なしpuma['ha']
    該当なしpuma['min_threads']
    該当なしpuma['max_threads']
    unicorn['listen']puma['listen']
    unicorn['port']puma['port']
    unicorn['socket']puma['socket']
    unicorn['pidfile']puma['pidfile']
    unicorn['tcp_nopush']該当なし
    unicorn['backlog_socket']該当なし
    unicorn['somaxconn']puma['somaxconn']
    該当なしpuma['state_path']
    unicorn['log_directory']puma['log_directory']
    unicorn['worker_memory_limit_min']該当なし
    unicorn['worker_memory_limit_max']puma['per_worker_max_memory_mb']
    unicorn['exporter_enabled']puma['exporter_enabled']
    unicorn['exporter_address']puma['exporter_address']
    unicorn['exporter_port']puma['exporter_port']
  3. GitLabを再設定します:

    sudo gitlab-ctl reconfigure
  4. オプション。マルチノードデプロイの場合は、読み取りチェックを使用するようにロードバランサーを設定します。

トラブルシューティングPuma

Pumaが100%CPUでスピンした後の502 Gatewayタイムアウト

このエラーは、Webサーバーがタイムアウトした場合に発生します(デフォルト: Pumaワーカーからの応答がない場合は60秒)。これが進行中にCPUが100%までスピンする場合、何かが必要以上に時間がかかっている可能性があります。

この問題を修正するには、まず何が起こっているかを把握する必要があります。以下のヒントは、ユーザーがダウンタイムの影響を受けてもかまわない場合にのみお勧めします。それ以外の場合は、次のセクションに進みます。

  1. 問題のあるURLを読み込む

  2. sudo gdb -p <PID>を実行して、Pumaプロセスにアタッチします。

  3. GDBウィンドウで、次のように入力します:

    call (void) rb_backtrace()
  4. これにより、プロセスはRubyバックトレースを強制的に生成します。バックトレースについては、/var/log/gitlab/puma/puma_stderr.logを確認してください。たとえば、次のものが表示される場合があります:

    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:33:in `block in start'
    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:33:in `loop'
    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:36:in `block (2 levels) in start'
    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:44:in `sample'
    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:68:in `sample_objects'
    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:68:in `each_with_object'
    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:68:in `each'
    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:69:in `block in sample_objects'
    from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/sampler.rb:69:in `name'
  5. 現在のスレッドを表示するには、次を実行します:

    thread apply all bt
  6. gdbを使用したデバッグが完了したら、必ずプロセスからデタッチして終了してください:

    detach
    exit

これらのコマンドを実行する前にPumaプロセスが終了すると、GDBはエラーをレポートします。時間を稼ぐために、Pumaワーカータイムアウトを常に上げることができます。Linuxパッケージインストールユーザーの場合は、/etc/gitlab/gitlab.rbを編集し、60秒から600秒に増やすことができます:

gitlab_rails['env'] = {
        'GITLAB_RAILS_RACK_TIMEOUT' => 600
}

セルフコンパイルインストールの場合は、環境変数を設定します。Pumaワーカータイムアウトを参照してください。

変更を有効にするには、GitLabを再構成します

他のユーザーに影響を与えずにトラブルシューティングを行う

前のセクションは実行中のPumaプロセスにアタッチされており、この期間中にGitLabにアクセスしようとしているユーザーに望ましくない影響を与える可能性があります。本番環境システムで他のユーザーに影響を与えることを懸念している場合は、別のRailsプロセスを実行して問題をデバッグできます:

  1. GitLabアカウントにサインインします。

  2. 問題を引き起こしているURLをコピーします(たとえば、https://gitlab.com/ABC)。

  3. ユーザーのパーソナルアクセストークンを作成します(ユーザー設定 -> アクセストークン)。

  4. GitLab Railsコンソールを起動します。

  5. Railsコンソールで、次を実行します:

    app.get '<URL FROM STEP 2>/?private_token=<TOKEN FROM STEP 3>'

    例:

    app.get 'https://gitlab.com/gitlab-org/gitlab-foss/-/issues/1?private_token=123456'
  6. 新しいウィンドウで、topを実行します。このRubyプロセスが100%のCPUを使用していることが表示されます。PIDを書き留めます。

  7. GDBの使用に関する前のセクションの手順2に従います。

GitLab: APIにアクセスできません

これは、GitLab Shellが内部API(たとえば、http://localhost:8080/api/v4/internal/allowed)を介して認可をリクエストしようとしたときに、チェックで何かが失敗した場合によく発生します。この問題は、次の理由で発生する可能性があります:

  1. データベース(たとえば、PostgreSQLまたはRedis)への接続タイムアウト
  2. Gitフックまたはプッシュルールのエラー
  3. リポジトリへのアクセスエラー(たとえば、古いNFSハンドル)

この問題を診断するには、問題を再現してみて、topを介してスピンしているPumaワーカーがあるかどうかを確認します。以前にドキュメント化されたgdb手法を使用してみてください。さらに、straceを使用すると、問題を特定するのに役立つ場合があります:

strace -ttTfyyy -s 1024 -p <PID of puma worker> -o /tmp/puma.txt

どのPumaワーカーが問題であるかを特定できない場合は、すべてのPumaワーカーでstraceを実行して、/internal/allowedエンドポイントがどこでスタックするかを確認してみてください:

ps auwx | grep puma | awk '{ print " -p " $2}' | xargs  strace -ttTfyyy -s 1024 -o /tmp/puma.txt

/tmp/puma.txtの出力は、根本原因の診断に役立つ場合があります。