oom-killer対策

ここ数年、サーバが急激に重くなり、機能しなくなることが数か月に一度くらい発生していました。この現象が発生すると、SSHによる接続もままならない状態になるので、なかなか原因調査が進んでいませんでした。

ここ最近発生頻度が上がってきているように感じて、本腰を入れて調査してみました。VPSコントロールパネルのターミナル画面から、oom-killerが関連していることは分かっていましたが、カーネルログ(/var/log/messages)の内容を見て詳細な状況が見えてきました。

Oct 23 16:28:06 omoshiro-joho kernel: ib_clone_gtid invoked oom-killer: gfp_mask=0x1140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=0
Oct 23 16:28:06 omoshiro-joho kernel: CPU: 0 PID: 152669 Comm: ib_clone_gtid Not tainted 5.14.0-162.6.1.el9_1.x86_64 #1
...
Oct 23 16:28:06 omoshiro-joho kernel: [ 152632]    27 152632   428373    91416  1130496        0             0 mysqld
Oct 23 16:28:06 omoshiro-joho kernel: [ 152679]     0 152679      330        1    36864        0             0 sshd
Oct 23 16:28:06 omoshiro-joho kernel: oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/system.slice/mysqld.service,task=mysqld,pid=152632,uid=27
Oct 23 16:28:06 omoshiro-joho kernel: Out of memory: Killed process 152632 (mysqld) total-vm:1713492kB, anon-rss:365664kB, file-rss:0kB, shmem-rss:0kB, UID:27 pgtables:1104kB oom_score_adj:0

メモリの使用量が一定量を超えて物理的に枯渇してくると、oom-killerがinvokeされます。その時点で最もメモリを食っているプロセスがkillされるのですが、そのターゲットがmysqldとなります。ただし、実際にはWEBサーバに対するリクエスト起因で作成されるWEBサーバやPHPのプロセスがたくさん起動することで、メモリを食っています。その後mysqldは自動的に再起動しますが、メモリが枯渇気味という状況に変化はないので、再びoom-killerによってkillされる、ということの繰り返しになっていました。この繰り返しにより、サーバが高負荷状態になっていたようです。

とりあえず対策を2つ打ちました。1つ目は、oom-killerでmysqldのプロセスをkillされにくくなるように、スコアを変更しました。-1000にするとkill対象外とできますが、mysqldで本当に問題が発生してメモリを不正に取得した場合に微妙なので、-500くらいにしてあります。

$ sudo systemctl edit mysqld.service

OOMScoreAdjust=-500

2つ目の対策は、php-fpmの起動数の抑制です。AlmaLinux9の場合、下記のように設定ファイルの内容を変更します。10という数字にあまり根拠はありません。元の50から減らしてみた、という程度です。

;pm.max_children = 50
pm.max_children = 10
;pm.max_spare_servers = 35
pm.max_spare_servers = 10

問題となっている現象自体は忘れた頃に発生するので、これらの対策の効果をすぐに確認できませんが、ここ最近の発生頻度を鑑みて、半年間現象が再現しなかったら効果があったと判断するつもりです。

【追記】上記設定に変更したは良いものの、php-fpmとapacheの再起動をかけていなかったので現象が再現してしまいました。ただoomの設定変更によりmysqldはkillされなかったので、サーバが異常に重くなる原因はやはりphp-fpmだと特定ができました。そして下記のコマンドでphp-fpmを再起動しました。

systemctl restart php-fpm.service

すると下記のエラーメッセージ。

Nov 25 09:54:17 omoshiro-joho php-fpm[228519]: [25-Nov-2023 09:54:17] NOTICE: PHP message: PHP Warning:  Module "gd" is already loaded in Unknown on line 0
Nov 25 09:54:17 omoshiro-joho php-fpm[228519]: [25-Nov-2023 09:54:17] ALERT: [pool www] pm.min_spare_servers(5) and pm.max_spare_servers(35) cannot be greater than pm.max_children(10)
Nov 25 09:54:17 omoshiro-joho php-fpm[228519]: [25-Nov-2023 09:54:17] ERROR: failed to post process the configuration
Nov 25 09:54:17 omoshiro-joho php-fpm[228519]: [25-Nov-2023 09:54:17] ERROR: FPM initialization failed
Nov 25 09:54:17 omoshiro-joho systemd[1]: php-fpm.service: Main process exited, code=exited, status=78/CONFIG
Nov 25 09:54:17 omoshiro-joho systemd[1]: php-fpm.service: Failed with result 'exit-code'.
Nov 25 09:54:17 omoshiro-joho systemd[1]: Failed to start The PHP FastCGI Process Manager.

エラーメッセージに従い、pm.max_spare_serversの値も修正しました。前述のコード表示には反映済みです。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする