Linux OOM Killer Tuning for VPS: 実践ガイド

12分で読めます - 2026年6月8日

hero section cover
目次
  • VPS 向け Linux OOM キラーの調整
  • OOMキラーが犠牲者を選ぶ仕組み
  • システム停止前にメモリ圧迫を検知する
  • oom_score_adj による重要プロセスの保護
  • cgroupsとsystemdによるメモリの上限設定
  • OOMイベント発生後のログの確認
  • まとめ
共有

VPSのLinux OOMキラーをチューニングして、データベースとSSHを保護し、cgroupsで暴走プロセスに上限を設定し、間違ったサービスが強制終了されないようにしましょう。

VPS 向け Linux OOM キラーの調整

LinuxのOOMキラーは、メモリが不足した際のカーネルの最終手段です。システムを維持するために、あるプロセスを選択して強制終了させます。RAMが限られており、代替手段がないVPS環境では、デフォルトの設定が誤った選択となることがよくあります。 データベースプロセスが強制終了され、長時間実行されているワーカプロセスが生き残り、その原因を突き止める羽目になることがあります。本ガイドでは、OOMキラーがプロセスをどのように評価するか、その評価を重要なサービスに有利にする方法、そしてcgroupsを使用して、1つの暴走プロセスがシステム全体をダウンさせないようにする方法について解説します。


 

OOMキラーが犠牲者を選ぶ仕組み

カーネルがページキャッシュの追い出しやスワップによって十分なメモリを回収できない場合、OOMキラーが起動されます。各プロセスには oom_score 0から1000までのスコアを持ち、これは主にそのプロセスの常駐セットサイズ(RSS)とスワップ使用量に基づいて算出されます。スコアが最も高いプロセスがSIGKILLを受けます。

RSSが計算において支配的な役割を果たすため、キル対象はほぼ常に最大のメモリ消費プロセスとなります。それは多くの場合、データベースやアプリケーションサーバー、あるいは最も有用な作業を行っている長期実行プロセスです。実際に割り当てをトリガーしたプロセス、つまり「呼び出し元」が終了させられることはめったにありません。

OOMイベントには、区別して理解すべき2つの種類があります:

  • グローバル OOM:ホスト(または VPS 全体)の RAM とスワップが不足している状態。カーネルはすべてのプロセスをスキャンし、スコアが最も高いプロセスを強制終了します。
  • cgroup OOM:特定のcgroupがメモリ制限に達した状態。システム全体に空きメモリがあっても、カーネルはそのcgroup内でのみプロセスを強制終了します。

systemdユニットの制限を設定している場合や、コンテナを実行している場合、OOMイベントのほとんどはcgroup OOMになります。これは良いことです。影響範囲が限定されるからです。

システム停止前にメモリ圧迫を検知する

OOM(メモリ不足)イベントが突然発生することはほとんどありません。通常、メモリ圧力が徐々に高まる前兆の期間があり、監視の目的は、その期間内に問題を捕捉することにあります。

free -h はシステムビューを表示します。重要なのは availableであり、 free:これは回収可能なページキャッシュを考慮したもので、スワップを行わずに実際に割り当て可能な容量を示しています。 MemAvailable ピーク負荷時の MemTotal に保つようにしてください。

プロセスごとの割り当てを確認するには、RSSで並べ替えます:

ps aux --sort=-%mem | head -10

または htop を使用し、 RESで並べ替えます。ここに表示される値はカーネルのスコアリングに直接反映されるため、上位のエントリがOOMの対象となる可能性が最も高いものです。

カーネル 4.20 以降では、Pressure Stall Information が監視システムに組み込む価値のある早期警告システムとなります:

cat /proc/pressure/memory

この some avg10 この数値は、過去10秒間に少なくとも1つのタスクがメモリ待ちでストールしていた時間の割合です。5%未満であれば問題ありません。10%を超える値が持続している場合は、システムがメモリ回収のために実時間をブロックされていることを意味し、OOMキルが発生する可能性があります。

スワップスラッシングは vmstat 1 でゼロ以外の値として si および so 列に、一定時間継続して表示されます。少量の常駐スワップは問題ありませんが、絶え間ないスワップインとスワップアウトは問題です。

oom_score_adj による重要プロセスの保護

カーネルが計算するスコアは、-1000(影響なし)から+1000(優先的に終了)のスケールで oom_score_adj-1000(免疫)から +1000(優先的に終了)までのスケールで、プロセスごとにバイアスをかけることができます。この調整値は、最終スコアに直接加算されます。

実行中のプロセスに対して一度だけ変更を加える場合は、次のようにします。

echo -500 | sudo tee /proc/$(pidof sshd)/oom_score_adj

再起動後も設定を保持したい場合は、systemd ユニットで設定します。sshd、データベース、その他失うわけにはいかないものについては、ここが適切な場所です:

[Service]
OOMScoreAdjust=-900

適切な初期設定値:

  • sshd: -1000。メモリ不足時にリモートアクセスを失うと、復旧がはるかに困難になります。
  • MySQL、PostgreSQL、Redis: -800 ~ -900。真に壊滅的な状況下でも完全に手出し不能にすることなく、強力な保護を実現します。
  • アプリケーションワーカー、バッチジョブ、cronタスク:+100~+500。これらは、データベースよりも先に終了させておきたいプロセスです。

すべてを -1000 に設定しないでください。何も終了させられない状態になると、カーネルは最終的にパニック状態になったりフリーズしたりすることになり、かえって事態を悪化させます。

cgroupsとsystemdによるメモリの上限設定

スコアを調整することで、どのプロセスが強制終了されるかが決まります。cgroupsは、グローバルな強制終了が実行されるかどうかに影響を与えます。各サービスに厳格な上限を設定することで、1つのプロセスがVPS全体のメモリを消費してしまうのを防ぎ、メモリ障害を単一のcgroupに限定することができます。

systemdのユニットファイル内では:

[Service]
MemoryHigh=400M
MemoryMax=512M
OOMPolicy=stop
Restart=on-failure
RestartSec=5s

MemoryHigh はソフトスロットルです。カーネルはこの値を超えるとcgroupからページを積極的に回収しますが、プロセスを強制終了(kill)することはありません。 MemoryMax はハード上限です。cgroupがこの上限を超えて割り当てを試みると、カーネルはそのcgroup内のプロセスを強制終了します。 Restart=on-failure サービスは直ちに再起動します。

cgroup v2(Ubuntu 22.04以降、最近のDebian、RHEL 9)では、 memory.oom.group 孤立したプロセスを残すことなく、cgroup内のすべてのプロセスをまとめて終了させます。PHP-FPMプールのようなマルチプロセスサービスにおいて、グループが中途半端に終了すると動作が不安定になる場合に有用です。

適用すべきアプリケーション固有の注意事項がいくつかあります:

  • PHP-FPM: 小さなVPSインスタンスでは pm = ondemand に設定し、サイズを pm.max_children をデフォルト値ではなく、ワーカーごとの平均RSSに基づいて設定してください。2GBのVPSで4GBの余裕を持たせてプールサイズを設定すると、初めて満杯になった時点でOOMエラーが発生します。
  • Node.js: V8ヒープの上限を --max-old-space-size=512 (MB単位)で上限を設定してください。これを行わないと、Nodeはカーネルが介入するまで無制限に拡大し続けます。
  • MySQL および PostgreSQL: innodb_buffer_pool_size および shared_buffers OSのページキャッシュ、接続メモリ、およびサーバー上の他のテナントのために十分な余裕を残しておく必要があります。デフォルト設定は専用サーバーを前提としています。

OOMイベント発生後のログの確認

OOMキラーが起動すると、カーネルは詳細なレポートをリングバッファにダンプします。以下のコマンドで取得します:

dmesg -T | grep -iE 'killed process|out of memory'
journalctl -k --grep='Out of memory'

注意深く読むべきブロックは、呼び出し元(invoker)から始まり、犠牲プロセス(victim)で終わります。カーネルは、各プロセスのRSS、スワップ使用量、および最終的な oom_score_adj。確認すべき点は以下の3つです:

  • 制約条件CONSTRAINT_NONE はグローバルなOOMを意味し、 CONSTRAINT_MEMCG はcgroupが制限に達したことを意味します。対処法はケースごとに異なります。
  • Free swap。これが 0kBの場合、RAMとスワップの両方が枯渇しています。スワップ領域を追加するか、 MemoryMax 、あるいは並行処理数を減らす。
  • 対象プロセスと他のすべてのプロセスのスコアを比較します。対象プロセスのスコアが、それに続く数つのプロセスよりもそれほど高くない場合、 oom_score_adj 設定値が十分な効果を発揮していません。差を広げてください。

特に cgroup における OOM の場合、kill カウンターは memory.events cgroup内部に存在します:

cat /sys/fs/cgroup/system.slice/mysql.service/memory.events

カウント値の増加は oom_kill カウントは、そのサービスが繰り返し制限に達していることを意味します。これは、 MemoryMax、ワークロードをプロファイリングする、あるいはサービスをより大きなプランに移行するべきであり、ループ状に再起動し続けるべきではないという合図です。

まとめ

OOMキラーの調整は、単にそれを無効にすることではありません。メモリが不足した際にどのプロセスが犠牲になるかを制御し、その影響範囲を最小限に抑えることが目的です。本番環境で有効なパターンは以下の通りです:

  • 失うわけにはいかないサービス、特にsshdやデータベースにはスコアプロテクトを設定する。
  • その他すべてのプロセスには MemoryMax で制限し、単一の暴走がシステム停止ではなく、単なる再起動で済むようにする。
  • PSIを監視し、 MemAvailable を監視し、 dmesg が事後報告をするのを待つのではなく、
  • RAMの15~20パーセントを余裕として確保してください。ワークロードに対して単純に容量が不足しているVPSについては、チューニングでは補えません。

メモリの負荷が設定で解決できるものではなく構造的なものである場合は、より多くの RAM またはより高速なスワップ用ストレージが必要です。FDC Servers の VPS プランは、NVMe ストレージを搭載した AMD EPYC で動作しており、スワップによる読み取りが十分に高速に保たれるため、一時的なメモリ不足がプロセス強制終了に発展することはありません。

ブログ

今週の特集

その他の記事
Linux OOM Killer Tuning for VPS: 実践ガイド

Linux OOM Killer Tuning for VPS: 実践ガイド

VPSのLinux OOMキラーをチューニングして、データベースとSSHを保護し、cgroupsで暴走プロセスに上限を設定し、間違ったサービスが強制終了されないようにしましょう。

12分で読めます - 2026年6月8日

Linuxトラフィック制御(tc):実践ガイド

12分で読めます - 2026年6月5日

その他の記事
background image

ご質問またはカスタムソリューションが必要ですか?

icon

柔軟なオプション

icon

グローバル・リーチ

icon

即時展開

icon

柔軟なオプション

icon

グローバル・リーチ

icon

即時展開