NovaScheduler RamFilterのメモリ計算を追う

VM作成時のホスト決定のためのSchedulerにおいて、デフォルトで利用されるFilterの1つにRamFilterがあります。

これはホストの残りメモリ容量にたいして何倍まで許容するかというフィルタらしいですが、デフォ値が 1.5 なので計算内容や状況によっては SWAP / OOM Killer 逝きになる可能性があるのかな、と気になったので良い子の私は、どのようなメモリ値を使ってどのように計算しているのか確認してみることにしました。



リンク

Schedulerについてはこの2箇所を見ておけば大体よさそうです。
  • Chapter 10. Scheduling – OpenStack Compute Administration Guide – Grizzly, 2013.1
  • OSSはアルミニウムの翼で飛ぶ: nova-scheduler in OpenStack Grizzly


  • デフォルト設定の確認

    Schedulerは nova.conf に記述されてなかったりするけど、これがデフォ

    RamFilterのデフォ値はこう

    例では、残りメモリ 1GB だと 1.5GB までのVMが作れますよ、と。
    …ということは、残り 100GB だと最後のVMは 150GB にできるってこと?挙動バランス悪くね?
    (実際、そんなデカい flavor 作らんけど)


    RamFilterを追う

    とりあえず適当に grep して該当箇所を見つけてきました。

    /usr/share/pyshared/nova/scheduler/filters/ram_filter.py

    requested_ram

    新規VMの割り当てメモリ容量ですよ、と。

    free_ram_mb

    どうやら、総メモリは libvirt の getInfo から取得してるっぽく、
    空き容量は /proc/meminfo の MemFree, Buffers, Cached を足した値としているとわかります。

    この足し算値は、実際に /proc/meminfo と Schedulerのデバッグログを比較してみたけど、ジャストその通りでした。

    /usr/share/pyshared/nova/virt/libvirt/driver.py

    total_usable_ram_mb

    ホストの総メモリ容量はここではDBの novadb.compute_nodes:memory_mb から持ってきているようです。

    /usr/share/pyshared/nova/scheduler/host_manager.py

    /usr/share/pyshared/nova/db/sqlalchemy/api.py

    memory_mb_limit, used_ram_mb, usable_ram

    ホストの総メモリに、設定値の倍率をかけて水増し、
    本来の総メモリ容量から空き容量を引いて、実際の使用中容量を出しておき、
    水増しパターンでの利用可能な容量を算出しています。

    で、VMメモリ容量が水増し残量を超えたらアウト判定。


    例題で考える

    余裕シャクシャクの場合

  • 総メモリ 128GB, 使用中メモリ 4GB, 残りメモリ 124GB
  • (128 * 1.5) – (128 – 124) = 188
  • 188GB までのVMを作成できる

  • そこそこ使ってそこそこ余ってる場合

  • 総メモリ 128GB, 使用中メモリ 64GB, 残りメモリ 64GB
  • (128 * 1.5) – (128 – 64) = 128
  • 128GB までのVMを作成できる

  • パツパツの場合

  • 総メモリ 128GB, 使用中メモリ 124GB, 残りメモリ 4GB
  • (128 * 1.5) – (128 – 4) = 68
  • 68GB までのVMを作成できる

  • 極端に考えると

    総メモリ128GBのホストで、カーネルとかその他デーモンのメモリを無視したら、
    1VM目は 192GB までのVMが作れて、SWAPするくらい崖っぷちでも常に 64GB のVMを作成できるということになります。(Quotaに引っかからない限り)

    え”。

    イヤ、でもそうとしか読み取れない… ヤバい、意外すぎて自信なくなった……w


    考察

    上記説明が正しいとすると、ドキュメントの説明と内容が異なっており、
    残りメモリ容量に対しての倍率ではなく、総メモリ容量に対する倍率となっています。

    単純に現在の空き容量に倍率を掛けて比較したら良いだけな気がするのですが…。
    そうしないと、このフィルタだけでは(Quotaを無視すると)無限にVMを作れてしまいます。

    しかし、仮に空き容量に対するものだとしても、上記例だと 192GB ~ 1GB(下限はflavor任意)までの幅ある上限であることに変りはないです。違う所は、極端に残りが少なくなると最低 0.67GB は残っていないと 1GB のVMを作れない、という点は大きいです。

    作者の意図はわからないけど、私は最初、kvmを起動して利用しても実際は全kvmプロセスがMAXまで使わないことを想定しての 1.5倍 かと思っていました。あと、空きメモリの計算は厳密には正確ではないから、とかかんとか。

    が、全然予想と異なっていたので
    (調査結果に納得いかなくていまだ解読が正しいか自信ないけど)、
    今のところは ram_allocation_ratio=1.0 にしつつ、ちゃんと nova quota-update –ram で管理することでSWAP / OOM Killerを回避していこうかと。そして想定より早くフィルターに引っかかったら、設定を再調整する、それが健全な運用であると思います(キリッ

    本件、突っ込み大歓迎でございます!