Groongaという全文検索エンジンの開発に参加している橋田です。
Windows仮想環境(以下、Windowsゲストと表記します)を構築して、その中でHyper-Vを使用する機会がありました。
今回は、QEMU/KVMを使ってWindowsゲストでHyper-Vを使用する方法について紹介します。
Hyper-VはDocker DesktopやWSL2でも利用されるため、Windowsゲストでこれらを使用する際にも必要な設定となります。
QEMU/KVMではなく、VirtualBoxでもWindows環境を構築することはできます。しかしバージョン6.1現在、ゲストOS上でHyper-Vを利用することが出来ません。(参考)
そのため、QEMU/KVMで環境構築を行います。
virt-managerでVM/QEMUの仮想環境上にWindowsをインストールする
ホストOSには Ubuntu 20.04.3 LTS を使用しています。
今回の動作確認に必要なコマンドをインストールします。
今回はGUIから設定を行うため、virt-managerもインストールしています。
$ sudo apt install libvirt-clients virtinst libvirt-daemon-system qemu-utils qemu-system-ppc virt-manager
Windowsのディスクイメージを用意します。
ここでは Win10_21H2_Japanese_x64.iso
とします。
virt-managerを起動し、 [新しい仮想マシン] の [ローカルのインストールメディア] から上記のディスクイメージを指定しインストールします。
その後ダイアログに従いメモリサイズ、ディスクイメージサイズなどを適切に設定し、Windowsをインストールします。
Windowsが起動しました。
Hyper-Vが利用可能か確認する
ここでは、WSL2がHyper-Vの機能を使用しているため、WSL2をインストールすることで、Hyper-Vが利用可能かどうか確認します。
起動したWindowsのPowerShellを管理者権限で起動し、以下のコマンドを実行します。
> wsl --install
インストール中: 仮想マシン プラットフォーム
仮想マシン プラットフォーム はインストールされました。
インストール中: Linux 用 Windows サブシステム
Linux 用 Windows サブシステム はインストールされました。
ダウンロード中: WSL カーネル
インストール中: WSL カーネル
WSL カーネル はインストールされました。
ダウンロード中: Ubuntu
要求された操作は正常に終了しました。変更を有効にするには、システムを再起動する必要があります。
再起動し、上記でインストールされたUbuntuを起動しようとすると、Hyper-Vを利用することができず、起動しません。
ゲストOSでHyper-Vを使えるように、QEMU/KVMの設定を変更する必要があります。
Nested Guestsを有効にする
ゲストOS上で更に仮想化技術を使うには、まずNested Guestsを有効にする必要があります。 (参考)
以下のコマンドで設定状況を確認します。
Y
が出力されれば有効です。
$ cat /sys/module/kvm_intel/parameters/nested
無効な場合は、設定を有効にするため以下の変更を行い、再起動します。
Intel CPUの場合:
$ echo "options kvm_intel nested=1" | sudo tee /etc/modprobe.d/kvm_intel.conf
AMD CPUの場合:
$ echo "options kvm-amd nested=1" | sudo tee /etc/modprobe.d/kvm_amd.conf
libvirtの設定ファイルを変更する
libvirtの設定ファイルを変更します。 (参考)
hypervisor機能を無効化
ゲストOSのWindowsに仮想マシン上で動いていないと認識させるための設定です。
<cpu>
に以下のタグを追加します。
<feature policy='disable' name='hypervisor'/>
vmx機能を有効化
ゲストOSのWindowsで他の仮想マシンを動作させるための設定です。
<cpu>
に以下のタグを追加します。
<feature policy="require" name="vmx"/>
CPUのモデルをnoTSXのものに変更
デフォルトのCPUで動かなければこの設定をします。
筆者の環境では Skylake-Client-noTSX-IBRS に設定しました。
<cpu>
に以下のタグを追加します。
<model fallback="allow">Skylake-Client-noTSX-IBRS</model>
SynIC機能を有効化
合成割り込みコントローラー (SynIC) を有効化します。(参考)
必要でない環境もあります。筆者の環境では不要でした。
<features>
の<hyperv>
に以下のタグを追加します。
<synic state='on'/>
clockのsyncをUTCに変更
必要でない環境もあります。筆者の環境では不要でした。
<clock>
タグを以下のように変更します。
<clock offset='utc'/>
最終的な設定
最終的に、筆者の環境では設定ファイルを以下のように変更する必要がありました。
<cpu mode='custom' match='exact' check='partial'>
<model fallback='allow'>Skylake-Server-noTSX-IBRS</model>
<feature policy='disable' name='hypervisor'/>
<feature policy='require' name='vmx'/>
</cpu>
virt-managerの設定から、XMLを編集し、保存します。
ゲストOSのWindowsを起動し、インストールされたUbuntuを起動すると、期待通り動いています!
まとめ
QEMU/KVMを使ってWindowsゲストでHyper-Vを使用する方法について紹介しました。
このような環境が必要になる機会は少ないかもしれませんが、このような環境もQEMU/KVMを使うことで構築できます。