この記事では、その仕組みについて解説しています。 oom キラー Linux メモリが急激に不足した際にどのように介入し、サーバーを稼働状態に保つためにサービスを強制終了するのかについて解説します。トリガーを特定し、スコアリングを理解し、適切な設定によってメモリ負荷時の動作を制御する方法を、段階を追って説明します。.
中心点
- トリガー: OOMイベントは、RAMが満杯になり、スワップ領域が枯渇し、リクレイム処理が失敗した際に発生します。.
- スコアリング: カーネルは
oom_scoreそして、メモリ使用率の高いプロセスを終了させる。. - レコグニション: 詳細は以下の資料に記載されています
dmesg「Out of memory」や「Killed process」といったエラーが表示されます。. - 制御システムと
oom_score_adj重要度に応じて、サービスを的確に優先順位付けしています。. - 予防: モニタリング、制限値、スワップ戦略、およびリーク分析により、ハードキルを未然に防ぎます。.
LinuxカーネルにおけるOOMキラーとは何ですか?
OOMキラーは最後の手段です 安全ライン カーネルは、利用可能なメモリページがなくなった場合、プロセスを終了させます。私はこれを、システム全体のダウンを防ぎ、即座にRAMを解放する「制御された緊急停止」と捉えています。その前に、システムはページのスワップやキャッシュのクリアを試みますが、負荷が継続する場合は、この「ハードカット」しか手段が残されません。 ログでは、この瞬間を「Out of memory」や「Killed process」というエントリで確認でき、多くの場合、SIGKILLが伴います。この動作はデフォルトで有効になっており自動的に実行されるため、本番環境では重要なサービスが予告なしに停止してしまうという予期せぬ事態がしばしば発生します。.
この仕組みはいつ作動するのでしょうか?
OOMイベントは、物理RAMがほぼ満杯になり、スワップがバッファを提供できなくなり、新しいページへの要求が失敗した際に発生します。この状況では、カーネルは ページキャッシュ そして、スワッピングがまだ有効な間は、状況が絶望的になって初めてキラーを起動します。一時的なピークだけではこのメカニズムは直接トリガーされず、持続的な負荷と、解放の試みが無駄に終わる状態が必要です。 分析にあたっては、RSS、スワップ使用量、ページキャッシュの割合、および各コントロールグループごとの割り当て状況を確認することが役立ちます。キャッシュの追い出しがどのように作用するかをより深く理解したい方は、その背景について ページキャッシュの追い出し 確認し、自身のシステムでその効果を測定する。.
カーネルはどのように「犠牲」となる対象を選定するのでしょうか?
この選択は、以下の基準に基づいて行われます。 スコアリング, Linuxを oom_score プロセスごとに計算されます。総メモリに占める割合が高く、RSSが多く、重要度が低いプロセスほどスコアが高くなります。initのようなシステム関連のプロセスには減点が行われる一方、メモリを大量に消費するワーカーやキャッシュは、多くの場合上位にランクインします。について oom_score_adj スコアを意図的に調整することで、犠牲となるプロセスの順序を制御できます。通常、カーネルはスコアが最も高いプロセスをSIGKILLで終了させ、一気にできるだけ多くのRAMを解放します。.
痕跡の特定:ログとシグナル
突然の勤務終了後、まず確認するのは dmesg そしてカーネルログです。そこに「Out of memory」や「Killed process」という記述が見つかれば、PID、プロセス名、ユーザー、および算出されたスコアを記録します。SIGKILLではクリーンアップフェーズが許可されないため、アプリケーション自体にエラーログがないことがよくあります。 その時点の状況をモニタリングデータと照合し、プロセスごとのRAM、スワップ、RSSの増加状況を追跡します。これにより、メモリリーク、ヒープの過剰なサイズ、制限の欠如などを確実かつ迅速に特定します。.
oom_score と oom_score_adj を使って制御を確立する
あらゆるプロセスには /proc/[PID]/oom_score 最新の 価値 その危険な状況について。~で /proc/[PID]/oom_score_adj これにより、カーネルがこのプロセスを終了させる確率を低下させたり、高めたりすることができます。データベースなどの重要なサービスは負のAdjで保護し、重要度の低いワーカープロセスは正のAdjを設定して「犠牲にできる」状態にします。この変更は即座に反映されるため、ロールアウトや負荷テストの際に特に役立ちます。 このようにして、予測不可能な緊急メカニズムを、自分の優先順位に従うツールへと変えるのです。.
ストレージ容量の逼迫が見られる典型的なホスティングのシナリオ
コンテナやデータベース、キャッシュが多数存在する環境では、OOMキラーが特に頻繁に発生するのを目にします。制御不能に肥大化するデータベースが、他のサービスを RAM そして、致命的な障害を引き起こします。Webアプリケーションにおけるメモリリークは、数時間にわたって負荷を蓄積させ、最終的にはリクレイムではどうにもならなくなるほどになります。容量が小さすぎるホスト上でコンテナの制限を甘く設定しすぎると、状況はさらに悪化します。こうしたパターンを把握している人は、早期にアラートを設定し、障害が事態を支配してしまう前に介入します。.
ハードキルを回避するためのベストプラクティス
ストレージは現実的な計画に基づき、ピーク負荷に備えた余裕を設け、サービスごとに明確な上限を設定しています。モニタリングでは、プロセスごとにRSS、スワップ使用量、および oom_score, 、緊急事態に備えて警告が発せられるようにするためです。 コンテナ環境では、個々のサービスがホストのリソースを独占しないよう、Cgroupの制限を設定しています。適切なスワップ戦略により、システムのパフォーマンスを恒久的に低下させることなく、負荷のピークを吸収します。より深い理解と計画立案のために、以下の実践ガイドを参考にしています。 仮想メモリの管理, ワークロードに確実に余裕を持たせるため。.
OOMインシデント発生時の体系的な対応手順
その出来事の後、まずログを抽出する dmesg kern.log を確認し、時間軸に沿って整理します。モニタリングでは、RAM、スワップ、RSS、ページキャッシュのグラフを確認して、負荷の推移を把握します。その後、ulimits、Cgroup およびコンテナの制限、さらに JVM のヒープなどのアプリケーションパラメータを確認します。続いて、 oom_score_adj より重要なものが残るように、不要なものは先に処理するようにします。最後に、根本的な原因を解決します。具体的には、リークの修正、キャッシュの制限、並列処理の削減、そしてリソースの適切な規模設定を行います。.
VPSおよびクラウド環境における特徴
仮想マシンでは、ハイパーバイザーやオーケストレーションなどによって、制限がさらに一段階加わります。そのため、割り当てられた RAM-量を正確に設定し、Kubernetes やコンテナの制限を適切に設定してください。 LinuxのOOMキラーは前述の通り動作し続けますが、プロバイダーのメカニズムによって追加のスロットリングが発生する可能性があります。特にPodの数が多い場合は、明確な優先順位付けが有効です。重要なDeploymentにはリソースの余裕を確保し、重要度の低いジョブはより厳しい制限下で実行されます。プラットフォームプロバイダーのドキュメントを参照し、独自のテストを行うことで、本番環境での予期せぬ事態を防ぐことができます。.
メモリの微調整:オーバーコミット、スワップニネス、キャッシュ
OOMのリスクを管理したいのであれば、カーネルパラメータを慎重に調整し、それらの相互作用を理解する必要があります。. vm.overcommit_memory そして vm.overcommit_ratio Linuxが仮想割り当てをどの程度寛大に許可するかを制御し、一方で vm.swappiness スワッピングとリクレイムの比率に影響を与える。. vm.vfs_cache_pressure これは、iノードおよびデントリーキャッシュの解放時の積極性を制御し、それによってページキャッシュの余裕に直接影響を与えます。私は常に現実的な条件下でその効果を検証しています。 負荷, 、メトリクスを記録し、変更は段階的に行うようにしてください。背景やシナリオについては、以下を参照すると参考になります。 メモリのオーバーコミット, 、自分なりのデフォルト設定を適切に選ぶために。.
| パラメータ/指標 | システムにおける役割 | どこで確認するか | 通常の方向 |
|---|---|---|---|
| フリーラム | ハードキルに対する緩衝策 | free, /proc/meminfo | 十分な予備を確保する |
| スワップの利用 | ピーク用ショックアブソーバー | free、vmstat | 低~中程度 |
| vm.overcommit_memory | 仮想割り当て | sysctl | 0/2(リスクに応じて) |
| vm.overcommit_ratio | オーバーコミットの割り当て | sysctl | ワークロードに合わせて |
| vm.swappiness | スワップ傾向 | sysctl | 極端な値ではなく平均値 |
| vm.vfs_cache_pressure | VFSキャッシュの解放 | sysctl | 100を起点として |
グローバルOOMとCgroup-OOM:具体的に何が終了するのか?
Cgroups(v1/v2)を採用した最新の環境では、OOMイベントが発生することがあります ローカル Memory-Cgroup 内で、または グローバル ホスト上で起動される。コンテナ内でプロセスが実行されている場合、厳格な メモリ.max (あるいはリミット)の場合、カーネルは通常、このCgroup内のプロセス(「memcg OOM」)のみを終了させ、システム全体は引き続き動作し続けます。 dmesg 次のような兆候から、それを認識します。 constraint=CONSTRAINT_MEMCG または、該当するCgroupへの参照。どのCgroupもRAMを割り当てられなくなり、グローバルメモリが枯渇して初めて、 システム全体にわたる OOMキラー。安定性を確保するためには、リミットを適切に設定し、Cgroup内でリソースを過剰に消費するサービスが、ホスト全体に影響を及ぼすことなく、そのCgroup内でのみ停止するようにすることが重要です。Cgroups v2では、さらに メモリ.high 緩やかなスロットル制御を設定し、 memory.oom.group 緊急時にはグループ全体を終了させるように定義しておく――中途半端に残ったプロセスよりも、すっきりしている。.
実践におけるツールと指標
原因を迅速に特定するために、再現可能なデータを収集しています。以下のツールは、私が日常的に活用しているものです:
- プロセスの概要:
ps -eo pid,ppid,cmd,%mem,rss --sort=-rss | headメモリを大量に消費しているプロセスを表示します。. - Smapsロールアップ:
cat /proc//smaps_rollupプロセスのRSS/PSS/スワップを、時間のかかる解析を行わずに取得します。. - pmap:
pmap -x | sort -nrk3 | headサイズとRSSを含むマッピングを一覧表示し、ヒープや大きなセグメントに適しています。. - スラブの利用:
slabtop -o高負荷時に肥大化する可能性のあるカーネルキャッシュを表示します。. - システム圧力:
vmstat 1そしてsar -r 1ページング、スワップI/O、およびフリー操作に関する背景を説明する。. - Cgroupの統計情報: v2では、次のようにチェックしています
/sys/fs/cgroup/memory.current,memory.swap.currentそしてmemory.stat当該サービス。.
# OOMログを簡単に確認する
dmesg -T | egrep -i 'out of memory|oom-kill|killed process'
# oom_score 順に上位候補を並べ替える
for p in /proc/[0-9]*; do
pid=${p##*/}
[ -r "$p/oom_score" ] || continue
printf "%6s %5s %-30s\n" \
"$(cat $p/oom_score)" \
"$(cat $p/oom_score_adj 2>/dev/null || echo 0)" \
"$(tr -d '\0' < $p/comm)"
done | sort -nr | head -n 20
OOMが繰り返し発生する場合は、その状況を記録します。 ベースライン 通常運転時のこれらの値を記録し、インシデントウィンドウと比較します。PSSの抑制されない上昇や、不釣り合いに大きなスラブなど、異常はすぐに目につきます。.
systemd、コンテナ、オーケストレーション:的確な制御
systemd では、優先順位と制限を設定しています 宣言された Unitファイル内では:
[サービス]
# プロセスを保護するか、犠牲にできるようにする
OOMScoreAdjust=-900
# ハード/ソフトメモリ制限 (cgroup v2)
MemoryMax=8G
MemoryHigh=6G
# オプション:スワップの制限
MemorySwapMax=2G
# systemd における OOM 時の動作
# (例:再起動を強制)
Restart=on-failure
RestartSec=5
コンテナ環境では、サービスごとに明確な制限値を設定しています。私にとって重要なのは、以下の区別です。 リクエスト (予約予定)および 制限 (厳格な上限)。リクエストや制限が適切に設定されたポッドは、より高いQoSランクが割り当てられます。「ベストエフォート」のワークロードは、OOM(メモリ不足)のリスクにさらされます。実運用上の注意点として、カーネルがCgroupのOOMを理由にコンテナを終了させた場合、よく見かける終了コードは 137 および出来事と OOMKilled; ホスト内――dmesg これらは相関関係にある。生産環境のクラスターでは、重要なデプロイを「Guaranteed」としてスケジュールする一方、バッチジョブは意図的により短い実行時間設定にし、優先順位を下げて先に処理されるようにしている。.
カーネルの詳細:OOM Reaper、THP、および断片化
キル後、その OOM リーパー: カーネルスレッドは、RAMを確実に解放するために、被害プロセスからメモリマッピングをできるだけ早く解除します。これが、メモリが時々 への キルエントリとして目に見える形で戻ってくる。これと並行して、 ストレージの圧縮 限界に直面する――RAMが著しく断片化されていると、大規模な割り当て(例えばTransparent Huge Pages、THPなど)を行うための連続した領域が不足してしまう。 THPはパフォーマンスを向上させますが、負荷がかかると割り当てが困難になる場合があります。レイテンシが重要なワークロードでは、試験的にTHPを無効化または制限し、その影響を測定します。.
もう一つの要因は スラブキャッシュ そしてページキャッシュ:I/O負荷の高いワークロードでは、これらのキャッシュは大幅に増加します。 vm.vfs_cache_pressure 的を絞ったリクレイムを行うことで、その割合を調整できます。一律にキャッシュを空にする(ドロップ・キャッシュ)操作は、せいぜい診断ツールとしてのみ使用し、恒久的な解決策としては用いません。さらに、私は以下の点にも注意を払っています。 NUMA: メモリノードが枯渇している場合、グローバルなRAMに空きがあっても、そのNUMAゾーン内のプロセスが失敗する可能性があります。これに関するメッセージもカーネルログに記録されます。.
スワップ戦略の理解を深める:スワップニス、ZRAM/Zswap、I/Oバジェット
スワップは悪ではなく、むしろ ショックアブソーバー. 重要なのは、それを賢く活用することです。 vm.swappiness カーネルがスワップにいつ移行するかを調整します。値が低すぎるとページキャッシュが支配的になり、OOMが早期に発生する可能性があります。逆に値が高すぎると、スワップI/Oへの負荷が高まり、システムの動作が重くなります。コンパクトなホストでは、私はよく ZRAM 或いは ツースワップ, 、ディスクに過負荷をかけずにピークを吸収する圧縮バッファを作成するためです。重要な点は、スワップは不足している容量の代わりにはならないということです。スワップは、OOMキラーが作動する必要がないよう、単に時間を稼ぐだけなのです。.
特殊なケース:mlock、RLIMITS、オーバーコミットの落とし穴
いくつかの制約条件により、OOMのリスクが高まったり、挙動が変化したりすることがあります:
- ロックされたストレージ: 以下の方法を通じて行われるプロセス
mlock()ページをピン留めすると、それらは「リクレイム」の対象外となる。このレートが高くなると、リーパーの進行を遅らせることができる。. - RLimits:
RLIMIT_ASそしてRLIMIT_RSSプロセスごとに上限を設定し、個々のサービスが制御不能になるのを防ぎます。これはOOMを防ぐための重要な要素の一つです。. - オーバーコミット: オーバーコミット設定が過度に緩いと、後で物理的に確保できないほど大きな仮想アドレス空間が割り当てられてしまいます。特に、多数のスレッドによる割り当てのピークが同時に発生すると、アクセス失敗を引き起こし、OOMイベントを早めることになります。.
- panic_on_oom: 極めて重要なシステムの場合、OOMが発生した際にカーネルパニックで対応するという選択肢があります。これは、厳密に定義されたHAシナリオにおいてのみ有効であり、それ以外の場合は逆効果となります。.
- „「不死身」というのは危険だ:
oom_score_adj=-1000キラーからの保護にはなりますが、システム全体を停止させてしまう可能性があります。私はこれを、絶対に不可欠な小さなプロセス(例:init)にのみ使用しており、メモリを大量に消費するサーバーサービスには使用しません。.
実務:優先順位を定め、変更を確実に反映させる
チーム内で、私は ランキング 各サービスのうち、何が残すべきで、何が真っ先に削ってもよいのか?この優先順位を、私は次のように反映させる。 oom_score_adj, 、Cgroupリミット、および(利用可能な場合は)再起動ポリシー。変更内容は、モニタリングにおける測定ポイントとともに、UnitマニフェストまたはDeploymentマニフェストにコードとして反映されます。 負荷テストでは、ストレージへの負荷をシミュレートします。データ量を増やし、並列処理を強化し、キャッシュを拡大させ、中核となるプロセスがオンラインのまま維持される一方で、まさに「犠牲にしてもよい」プロセスが停止するかどうかを観察します。この動作が再現可能になって初めて、その構成を本番環境に導入します。.
診断パターン:リーク、ヒープ、断片化の区別
RSSが上昇したからといって、すべてがリークというわけではありません。私は次のように体系的に区別しています:
- リーク: RSS/PSSは、負荷が増加していなくても単調に上昇する;;
smaps_rollup均一に増加しており、GCサイクル(マネージドランタイムの場合)では改善されない。. - ヒープのピーク: RSSは負荷の増加に伴い上昇し、その後再び低下する。ページキャッシュはI/Oパターンと相関関係にある。.
- フラグメンテーション: 空きRAMは十分にあるが、大規模な割り当てが失敗する。ログには圧縮の試みが記録されており、THPの割り当てが頻繁に失敗している。.
JVM または Node のワークロードについては、ランタイムがコンテナの制限を認識しているかどうかを確認します。ヒープや JIT コードキャッシュのサイズが大きすぎると、一見余裕があるように見えても、制限を超えて計画され、OOM を引き起こす可能性があります。私は、オーバーヘッドを含めたヒープサイズを、以下の条件下で メモリーマックス ネイティブ部分のバッファ、スレッドスタック、ページキャッシュ用の余裕が残っている。.
ストレージ負荷下でのロールアウトおよび負荷テストのためのプレイブック
- ベースラインを測定する: サービスごとのRSS/PSS、スラブ占有率、スワップ率、キャッシュサイズ、,
oom_score. - 境界線を引く: メモリ上限/最大 あるいは、現実的な余裕を持たせたコンテナの制限を定義する;;
OOMScoreAdjust優先順位に基づいて割り当てる。. - ストレスを生み出す: データ量、同時実行数、キャッシュの増加率;I/OおよびCPUのプロファイルを記録する。.
- 観察する:
dmesg -T, 、ホストおよびCgroupのメトリクス;どちらが先に負荷にさらされるかを確認する。. - 反復処理: 制限値/調整値を調整し、スワップネスを調整し、THP設定をテストし、再度測定する。.
- 自動化: CI/CDへのチェックの組み込み、閾値超過時のアラート、影響を受けたサービスに対する再起動ポリシー。.
簡単にまとめると:具体的な措置
私が理解するところでは、OOMキラーとは 信号, 、以前のシステムではバッファが不足していたか、プロセスの優先順位設定が不適切だったということだ。モニタリング、現実的な制限値、適切なスワップ戦略、そして意識的な oom_score_adj これにより、システムが急停止する事態を大幅に減らしています。生産環境では、中核となるプロセスを保護し、周辺サービスは不要なものと見なし、あらゆる変更を測定しています。 コンテナについては、あるサービスがホストシステム全体をブロックしないよう、Cgroupの制限を厳格に設定しています。この規律を守り続ければ、負荷がかかっている状況でもLinuxの応答性を維持でき、原因の特定にかかる時間を大幅に短縮できます。.


