passingloop

  • アーカイブ
  • RSS

Linux のオーバーコミットについて調べてみた

Linux のオーバーコミットのはなし

(これを書いたのは Linux 2.6.38 のとき)

Linux カーネルは実メモリ以上にメモリをプロセスに割り当てることができる この仕組みをオーバーコミット (over-commit) と呼ぶ オーバーコミットでは,とりあえずメモリを malloc させて仮のアドレスを返しておき, 実際に使われる段になってはじめて実メモリを確保する.

実験

ただ malloc し続けるだけのプログラムを作って実験してみる.

このプログラムをメモリ 1 GB + スワップ 1 GB のホストで実行してみると,

$ free -t
             total       used       free     shared    buffers     cached
Mem:       1022404      82992     939412          0       4172      12280
-/+ buffers/cache:      66540     955864
Swap:      1044476          0    1044476
Total:     2066880      82992    1983888
$ gcc -o oc_test oc_test.c
$ ./oc_test
76152GB

76152GB = 74TB も malloc できた計算になる.つまり,Linux では

(オーバーコミットできるメモリの大きさ)>(実際に利用可能なメモリの大きさ)

となる.

しかし,オーバーコミットしたメモリは実際には存在しないので, いつかはメモリが足りなくなるときが来る.そんなときはどうするのか. 何のことはない,カーネルが OOM killer (out of memory killer) というロシアンルーレットを回して, メモリが空くまで手当たり次第にプロセスを殺していくのである. ただし,カーネルスレッドとか init とかは殺さないし,また, sshd のようにディストリビューションのデフォルトで oom_score が 0 に設定されるプロセスも OOM killer の対象外となる.(oom_score については後述)

試しに実際に利用可能な量を越えて, オーバーコミットしたメモリを使おうとすると

$ ./oom_killer_test
Killed

と OOM killer がやってきて殺される. この場合は犯人の oom_killer_test が殺されたが, OOM killer は犯人以外のプロセスを殺すこともある. それゆえ,先に「ロシアンルーレット」という表現を使ったのである. OOM killer が殺すプロセスを決定するルールは, http://www.kernel.org/doc/Documentation/vm/overcommit-accounting に詳しい.

オーバーコミットの設定

OOM killer が発動すると,犯人以外のプロセスが殺されることもある, と先に述べた.言い換えると OOM killer が無実の重要なプロセスを殺すかも しれないということである.これでは困るので, 重要なプロセスが走っているホストではオーバーコミットを無効にすることがある.

オーバーコミットの有効・無効を切り替えるには, sysctl vm.overcommit_memory を設定する. vm.overcommit_memory の値は,

  • 0
    • オーバーコミット有効
    • 一回の malloc で確保できるのは実際に利用可能なメモリの大きさまで
  • 1
    • どんなときでもオーバーコミット可
    • 一回の malloc で実際に利用可能なメモリを越える大きさでも確保可能
  • 2
    • オーバーコミット無効
    • malloc で割り当てられるメモリの総量は (スワップの大きさ)+(物理メモリの大きさ)* vm.overcommit_ratio / 100

なので,OOM killer を避けたいときには

vm.overcommit_memory=2

を /etc/sysctl.conf に追加して,sysctl -p すればよい.

ただし,オーバーコミットを無くせば out of memory が無くなるというわけ ではないので,vm.overcommit_memory=2 しても,OOM killer を完全には止められない.どうしても死んで欲しくないプロセスには, oom_adj を設定しよう.これは,OOM killer に殺される 確率を調整するパラメータで,-17 にすると OOM killer の対象外になる. process_id の oom_adj を

$ sudo echo -17 > /proc/864/oom_adj

すると,

$ cat /proc/864/oom_score
0

ここで,864 はプロセス id である.

OOM killer が発動する前にリブートさせる戦略

OOM killer が発動すると重要なプロセスを殺してしまい, システムが不安定になるかもしれない. そもそも,OOM killer が発動する状況では, メモリなどのリソースが不足していると想定されるので, そのままシステムを稼動させていると,いつ不安定になるか分からない.

そこで,OOM killer が発動するようなメモリが不足する状況になったら, システムをリブートしてしまうという戦略をとることがある. この戦略を実現するためには,まず sysctl で, vm.panic_on_oom に 1 を設定して OOM 時にカーネルパニックになるようにする.そして, kernel.panic に適当な秒数を設定し, カーネルパニックが起きたら自動でリブートするよう設定する.

$ sudo sysctl -w vm.panic_on_oom=1
$ sudo sysctl -w kernel.panic=60

この例では OOM →即,カーネルパニック→ 60 秒後再起動となるよう設定している.

おすすめ設定

(守備的な設定)

システムが不安定になるのを避けたいときは, オーバーコミットを無効にするのがよい. 加えて,重要なプロセスには oom_adj=-17 して, OOM killer の対象外となるようにする.

$ sudo sysctl -w vm.overcommit_memory=2
$ sudo echo -17 > /proc/864/oom_adj

この設定の場合,利用できるメモリは実際の物理メモリと比べて少なくなる. デフォルトでは vm.overcommit_ratio が 50 なので, 全プロセスが利用できるメモリは物理メモリの 50% となる. (残りはカーネルがおいしく頂くことになる)

(攻撃的な設定)

システムが不安定になるリスクと引き換えにメモリを目一杯使いたいときは, オーバーコミットを無制限にして, メモリが足りなくなったら潔く再起動すればよい.

$ sudo sysctl -w vm.overcommit_memory=1
$ sudo sysctl -w vm.panic_on_oom=1
$ sudo sysctl -w kernel.panic=60

おわりに

Linux のオーバーコミットについて調べたことをまとめてみた. メモリをたくさん使うジョブを走らせているホストが不安定になったら, それは,OOM killer のせいかもしれない.そんなときには, オーバーコミットの設定を変更することを考えてみよう.

    • #linux
  • 2年前
  • 10
  • Comments
  • 固定リンク
  • Share
    Tweet

10 Notes/ Hide

  1. sibukixxxがこの投稿を「スキ!」と言っています
  2. kysnmがこの投稿を「スキ!」と言っています
  3. ykhrokiがこの投稿を「スキ!」と言っています
  4. tropicalsantaがこの投稿を「スキ!」と言っています
  5. passingloopの投稿です

最近のコメント

コメント機能はDisqusから提供されています
← 前へ • 次へ →
 
 
  • passingloop の日記
  • passingloop のブックマーク

Twitter

loading tweets…

  • RSS
  • ランダム
  • アーカイブ
  • 携帯電話

Amazon.co.jpアソシエイト

Effector Theme by Carlo Franco.

Tumblrによって提供されています