しばたテックブログ

気分で書いている技術ブログです。

Hyper-Vのホストで予約されるメモリサイズについて

ちょっとハマったのでメモ。

ハマったこと

お仕事でとあるWindows Server 2008 R2のサーバーをハードウェアはそのままにWindows Server 2012 R2にアップグレード*1しました。

このサーバーはメモリを16GB積んだHyper-Vのホストとして利用しており、Windows Server 2008 R2の時点で複数の仮想マシンを稼働させトータルで14GB程度のメモリを使う設定にしていました。
そしてWindows Server 2012 R2にアップグレードした後に同スペックの仮想マシンを稼働させようとするとメモリ不足のエラーが出てしまいました。

その時点では『まあホストOSが使うメモリ量も変わってるからだろう。』と軽く考え仮想マシンが使うメモリサイズを適当に調整し対応したのですが、調整しつつ調査した結果、今回の環境では仮想マシンに使用可能なメモリサイズが約12GBになっていることがわかりました。

14GB→12GBと予想以上に仮想マシンで使用可能なメモリサイズが減っているのが気になり詳細を調べてみたのが今回のエントリの内容になります。

Hyper-Vのホストで予約されるメモリサイズ

Hyper-VのホストサーバーではOSが使用しているメモリサイズに加えてホスト自身がメモリ不足にならない様にするために一定量のメモリサイズを予約します。*2

このため仮想マシンに使えるメモリサイズは、ざっくりとした式ですが、

仮想マシンに使えるメモリ = 物理メモリ - ( ホストOS自身が使用しているメモリ + 予約サイズ )

となります。
後述のKBによれば具体的には、

仮想マシンに使えるメモリ = タスクマネージャーの"利用可能"メモリ – 予約サイズ

になるそうです。

Windows Server 2008 R2での予約サイズ

この予約サイズについてですがWindows Server 2008 R2についてはこちらの記事に詳しく記載されています。
この記事によれば予約サイズは、デフォルト設定の場合、

384MB + 30MB per 1GB of physical memory on the host machine.

との事ですので、物理メモリ16GBの今回の環境では、

384MB + ( 30MB * 16 ) = 864 MB

となります。
ちなみにOS自身が使用しているメモリサイズは約1.1GB程度でしたので、ざっくり計算で約14GBを仮想マシンで利用できることがわかります。

Windows Server 2012 R2での予約サイズ

Windows Server 2012 R2での予約サイズはKB2962295に記載*3されています。
このKBでは具体的な計算式までは公開されておらず物理メモリのサイズに応じたテーブルのみ公開されています。

ただ、仮想マシンに使えるメモリサイズはパフォーマンスカウンタのHyper-V Dynamic Memory Balancer\Available Memoryの値を実測すると直ちに取得できるとの事です。
今回の環境では仮想マシンを全て停止した状態でHyper-V Dynamic Memory Balancer\Available Memoryの値を取得すると12,736MB(約12.43GB)となりました。

ちなみに予約サイズはKBによると、

2–2.5 GB

とされています。
OS自身が使用しているメモリサイズは約1.5GB程度であったため、ざっくり計算してみると、

(物理メモリ) 16,384MB - (OS使用メモリ) 約1,536MB - (利用可能メモリ) 12,736MB = 約2,112MB

となりテーブルに記載されている数値と確かに一致しています。

より細かい計算については、

仮想マシンが使用できるメモリーサイズ

の記事の内容が参考になります。

対応方法について

今回は仮想マシンのメモリサイズを割と自由に変えることができる環境だったので大きな問題になりませんでしたが、仮想マシンの構成を容易に変えることが出来ない場合は以下の対応方法が考えられます。

1. レジストリMemoryReserveの値を変更する

前項で紹介したリンク先を見ればわかりますが、予約サイズはレジストリの設定を変更することで固定値に変更することができます。
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\VirtualizationキーのMemoryReserve(DWORD)に予約サイズをMB単位で指定できます。

Windows Server 2012 R2の環境でもこのレジストリキーを設定して予約サイズを1GB程度まで落とせばWindows Server 2008 R2と同程度のサイズを仮想マシンに割り当てることが出来ます。
ただしKB2962295によればこのレジストリ設定は非推奨とされていますので実際に行う場合は注意してください。

2. Dynamic Memoryを有効にする

今回の環境では仮想マシンでDynamic Memoryを有効にしてなかったので仮想マシンに割り当てたメモリサイズ = OSで使用するメモリサイズとなり直ちにメモリ不足になりましたが、Dynamic Memoryを有効にすることで実際に使用されるメモリサイズを節約し対応することが可能です。

Dynamic Memoryとは何ぞやといった話については小塚さんの以下の記事が参考になりますのでご覧ください。

コラム - Hyper-V の部屋 | 第2回 仮想マシンの作成と動的メモリ機能について|CTC教育サービス 研修/トレーニング

最後に

とりあえずこんな感じでした。
特にオチはないのですが、ホストOSが変わると仮想マシンに使えるメモリサイズが結構変わることがわかりましたので仮想マシンのサイジングをする際は気を付けます。

*1:実際にはOSを入れなおして再構築

*2:ここで言う予約は物理メモリを確保するのではなく空き領域の予約になります。

*3:非常に腹立たしいことに、いつの間にか改版履歴が更新されることすらなくテーブルの内容が削除されてしまっていました。私の記憶の範囲では「ホストのメモリサイズが32GB以下の場合2–2.5 GB」「ホストのメモリサイズが64GB以下の場合(思い出せない)」「ホストのメモリサイズが128GB以下の場合3~4GB程度」「ホストのメモリサイズが128GB以上の場合(思い出せない)」くらいのテーブルだったはずですが正確さは保証できません...