Gitlab CEのメモリ食いすぎ問題

はじめに

Gitlab CEがメモリを食いすぎてスワップも出すので、色々調べたことを書いています。
環境:Proxmox VM、CPU 2core、MEM 4GB, ubuntu 22.04、GitLab CE(Community Edition)17.7.0

TL;DR

GitLab CEのメモリ問題、pumaがでかい。他のサービス停止しても効果薄い。pumaのworker減らすと手っ取り早い。

Gitlabを構成するサービスたち

まず、Gitlabがどんなサービスたちから成り立っているのか、理解して置く必要があります。gitlab-ctl restartしてみると、下記の複数プロセスを再起動しているのがわかります。

root@mygitlab:~# gitlab-ctl status
                    run: alertmanager: (pid 128100) 36s; run: log: (pid 97297) 88530s
                    run: gitaly: (pid 128110) 35s; run: log: (pid 97305) 88530s
                    run: gitlab-exporter: (pid 128118) 34s; run: log: (pid 97322) 88530s
                    run: gitlab-kas: (pid 128129) 23s; run: log: (pid 97300) 88530s
                    run: gitlab-workhorse: (pid 128135) 23s; run: log: (pid 97301) 88530s
                    run: logrotate: (pid 128145) 22s; run: log: (pid 97311) 88530s
                    run: nginx: (pid 128153) 22s; run: log: (pid 97306) 88530s
                    run: node-exporter: (pid 128163) 21s; run: log: (pid 97313) 88530s
                    run: postgres-exporter: (pid 128168) 21s; run: log: (pid 97307) 88530s
                    run: postgresql: (pid 128176) 20s; run: log: (pid 97308) 88530s
                    run: prometheus: (pid 128185) 20s; run: log: (pid 97303) 88530s
                    run: puma: (pid 128196) 19s; run: log: (pid 97304) 88530s
                    run: redis: (pid 128201) 19s; run: log: (pid 97310) 88530s
                    run: redis-exporter: (pid 128208) 18s; run: log: (pid 97298) 88530s
                    run: sidekiq: (pid 128217) 12s; run: log: (pid 97326) 88530s

さて、これらのサービス(プロセス)は何をしているのでしょうか?

サービス 説明
alertmanager GitLabのモニタリングシステムの一部で、Prometheusから受信したアラートを管理し、必要に応じて通知(メールやチャットツールへの通知など)を送信します。
gitaly Gitリポジトリに対するすべての操作を処理するサービス。Gitリポジトリのデータに効率的にアクセスできるように設計されています。
gitlab-exporter GitLabの内部メトリクス(システムの稼働状況やパフォーマンスデータ)をPrometheusにエクスポートします。
gitlab-kas GitLab Agent for Kubernetes(KAS)を通じて、Kubernetesとの統合を管理するサービスです。
gitlab-workhorse HTTPリクエストを処理するプロキシ。静的ファイルの配信やGitリポジトリへのスマートなアクセスなどを担当します。
logrotate GitLabのログファイルを管理するサービス。一定期間後にログファイルをローテーション(古いログを圧縮して新しいログを生成)します。
nginx Webサーバー兼リバースプロキシとして機能し、GitLabへのHTTP(S)リクエストをGitLab Workhorseに転送します。
node-exporter GitLabサーバーのハードウェアリソース(CPU、メモリ、ディスクなど)をPrometheusにエクスポートします。
postgres-exporter PostgreSQLのメトリクスをPrometheusにエクスポートします。
postgresql GitLabの主要なデータベース。ユーザー情報、プロジェクト情報、CI/CDパイプラインなどのデータを管理します。
prometheus GitLabの監視システムの中核。各エクスポーター(例: node-exporter、gitlab-exporter)からデータを収集し、システムの状態を可視化します。
puma GitLabのWebアプリケーションサーバーで、RailsベースのWebリクエストを処理します。
redis GitLabのキャッシュおよびキューデータを保存するためのインメモリデータストア。
redis-exporter RedisのパフォーマンスメトリクスをPrometheusにエクスポートします。
sidekiq GitLabのバックグラウンドジョブを処理するワーカー。通知メールの送信やCI/CDパイプラインの実行などを担当します。

つまり、GitLabのメインの機能は、
nginx -> gitlab-workhorse -> puma -> gitaly -> redis or postgresql の流れで処理されています。
sidekiqはバックグラウンドで動いているジョブを処理し、その他(prometheusやexporter)は監視系ですね。

誰がメモリとスワップを食っているのか

Proxmox上のCPU 2core, MEM 4GBのVMでGitLabを動かしていますが、メモリかつかつでスワップが出ています。

root@mygitlab:~# free -h
                    total        used        free      shared  buff/cache   available
     Mem:           3.8Gi       3.0Gi       114Mi        70Mi       701Mi       483Mi
     Swap:          2.0Gi       203Mi       1.8Gi

ちょっとhtopで見てみたのが下記になりますが、やはりpumaがダントツにメモリ(RES)を使ってますね。

    PID  SWAP USER      PRI  NI  VIRT   RES△  SHR S CPU% MEM%   TIME+  Command
     1     8 root       20   0  162M  8580  4964 S  0.0  0.2  0:10.36 /sbin/init
 97281     0 root       20   0  2812  1432  1332 S  0.0  0.0  0:01.61 ├─ runsvdir -P /opt/gitlab/service log: ...............................................
 97289     0 root       20   0  2660  1228  1220 S  0.0  0.0  0:00.01 │  ├─ runsv puma
 97304     0 root       20   0  2808  1700  1608 S  0.0  0.0  0:00.01 │  │  ├─ svlogd -tt /var/log/gitlab/puma
128196 21892 git        20   0 1079M  790M 11548 S  0.0 20.2  1:14.77 │  │  └─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp://12
128277     0 git        20   0 1079M  790M 11548 S  0.0 20.2  0:00.01 │  │     ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
128341     0 git        20   0 1079M  790M 11548 S  0.0 20.2  0:00.00 │  │     ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
128343     0 git        20   0 1079M  790M 11548 S  0.0 20.2  0:00.76 │  │     ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
128344     0 git        20   0 1079M  790M 11548 S  0.0 20.2  0:00.41 │  │     ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
128345     0 git        20   0 1079M  790M 11548 S  0.0 20.2  0:00.61 │  │     ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
128346 13944 git        20   0 1319M  905M 10156 S  0.0 23.1  0:10.80 │  │     ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128347     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.00 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128350     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.91 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128351     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.42 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128352     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.37 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128353     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.30 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128354     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.00 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128360     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.02 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128361     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:02.46 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128362     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:01.64 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128364     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:01.58 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128365     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:01.68 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128367     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.30 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128368     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.00 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128370     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.03 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128371     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.09 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128414     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.00 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
129269     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.00 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
130861     0 git        20   0 1319M  905M 10156 S  0.0 23.1  0:00.00 │  │     │  ├─ puma: cluster worker 0: 128196 [gitlab-puma-worker]
128348 12648 git        20   0 1368M  912M 14108 S  0.0 23.3  0:11.68 │  │     └─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128349     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.00 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128355     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.96 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128356     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.43 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128357     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.38 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128358     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.30 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128359     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.01 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128363     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.02 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128366     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:01.78 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128369     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:02.54 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128372     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:01.73 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128373     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:01.68 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128374     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.30 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128375     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.01 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128376     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.03 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128377     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.09 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
128382     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.01 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
129274     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.00 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130142     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.00 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130143     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.00 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130144     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.06 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130145     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.00 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130146     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.00 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130147     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.00 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130148     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.09 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130149     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.08 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130150     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.03 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130151     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.05 │  │        ├─ puma: cluster worker 1: 128196 [gitlab-puma-worker]
130153     0 git        20   0 1368M  912M 14108 S  0.0 23.3  0:00.06 │  │        └─ puma: cluster worker 1: 128196 [gitlab-puma-worker]

pumaのチューニングから手をつけるべきか、gitlabの使ってないサービスを停止するか、一旦後者で進めてみます。

不要なサービスを停止する

以下の起動中サービスからGitLab CEの不要なサービスを停止してみる。

root@mygitlab:~# gitlab-ctl service-list
                    alertmanager*
                    gitaly*
                    gitlab-exporter*
                    gitlab-kas*
                    gitlab-workhorse*
                    logrotate*
                    nginx*
                    node-exporter*
                    postgres-exporter*
                    postgresql*
                    prometheus*
                    puma*
                    redis*
                    redis-exporter*
                    sidekiq*

まずは、prometheusとexporterですかね。

root@mygitlab:~# gitlab-ctl stop gitlab-exporter && gitlab-ctl stop node-exporter && gitlab-ctl stop postgres-exporter && gitlab-ctl stop prometheus && gitlab-ctl stop redis-exporter
                    ok: down: gitlab-exporter: 1s, normally up
                    ok: down: node-exporter: 0s, normally up
                    ok: down: postgres-exporter: 0s, normally up
                    ok: down: prometheus: 1s, normally up
                    ok: down: redis-exporter: 0s, normally up

再度、メモリ使用量を確認してみます。

root@mygitlab:~# free -h
                    total        used        free      shared  buff/cache   available
     Mem:           3.8Gi       3.0Gi       122Mi        71Mi       744Mi       548Mi
     Swap:          2.0Gi       161Mi       1.8Gi

多少メモリ使用状況が変化しましたが、大きな効果は得られません。

pumaのworkerを減らしてみる

Qiita によると、pumaのworkerのメモリ上限に達するとプロセス再起動する設定がある。
でも、これだと一生プロセス再起動を繰り返しそう&個人利用なので、workerを減らす方向で進めようか。

先ほどのtopの結果からpumaがメモリを食っているのは明らかなので、クラスタモードを無効にしてみる。

公式の解説 通りに設定を変更してみます。
/etc/gitlab/gitlab.rbを下記に変更して、gitlab-ctl reconfigureする。

puma['worker_processes'] = 0

再度、htopみます。

    
  PID  SWAP USER      PRI  NI  VIRT   RES▽  SHR S CPU% MEM%   TIME+  Command
 97289     0 root       20   0  2660  1352  1268 S  0.0  0.0  0:00.01    ├─ runsv puma
131580     0 git        20   0 1198M  907M 28904 S  0.0 23.2  1:10.78    │  ├─ /opt/gitlab/embedded/bin/puma -C /var/opt/gitlab/gitlab-rails/etc/puma.rb
131598     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.00    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131602     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.04    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131603     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.07    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131605     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.04    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131606     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.04    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131607     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.04    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131611     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.00    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131633     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.00    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131635     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.00    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131636     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:01.47    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131637     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.19    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131638     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.15    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131639     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.14    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131640     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.02    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131641     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.00    │  │  ├─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
131642     0 git        20   0 1198M  907M 28904 S  0.0 23.2  0:00.00    │  │  └─ puma 6.5.0 (unix:///var/opt/gitlab/gitlab-rails/sockets/gitlab.socket,tcp:/
 97304     0 root       20   0  2808  1700  1608 S  0.0  0.0  0:00.01    │  └─ svlogd -tt /var/log/gitlab/puma
                

pumaプロセスが一つになりました。
freeもみてみます。

root@mygitlab:~# free -h
                    total        used        free      shared  buff/cache   available
     Mem:           3.8Gi       2.5Gi       391Mi        86Mi       966Mi       985Mi
     Swap:          2.0Gi       206Mi       1.8Gi
メモリ使用量の減少

pumaのクラスタモードを無効にすることで、workerが減りメモリ使用量が減少しました。
個人での利用であれば、問題ないと思います。
まだスワップがありますが、一旦スワップオフしてどうなるか観察しようと思います。

まとめ

pumaから対応すべし。他のサービス停止しても効果薄い。個人利用なら、pumaのworker減らすと手っ取り早い。

TECH BLOG BY OZAKI