この記事は、インテル® デベロッパー・ゾーンに掲載されている「Enabling Virtual Machine Control Structure Shadowing On A Nested Virtual Machine With The Intel® Xeon® E5-2600 V3 Product Family」(https://software.intel.com/en-us/blogs/2014/12/12/enabling-virtual-machine-control-structure-shadowing-on-a-nested-virtual-machine/) の日本語参考訳です。
はじめに
この記事では、ネストされた仮想マシンをセットアップする手順と設定の確認/調整に役立つコマンドを説明します。私は最近、インテル® Xeon® プロセッサー E5-2600 V3 製品ファミリーで利用可能な VMCS (Virtual Machine Control Structure) シャドーイングと呼ばれる新機能をテストするため、ネストされた VM のセットアップを行いました。ネストされた仮想化では、ルート VMM (Virtual Machine Monitor) がゲスト VMM をサポートできます。ただし、追加の VM Exit 命令はパフォーマンスに影響します。VMCS シャドーイングは、ゲスト VMM の VMREAD/VMWRITE を VMCS シャドウ構造に移動することで、ネストにより生じる VM Exit 命令を減らします。結果として、VMCS シャドーイングは、仮想化のレイテンシーを軽減し、効率を向上します。
図 1 – VMCS シャドーイングにより VM Exit 命令が軽減
ネストされた仮想マシンをセットアップする利点は何でしょうか? ネストされた VM では、抽象化レイヤーが追加されます。これは、ネストされた VM をハイパーバイザーやクラウド・インフラストラクチャーから切り離すのに便利です。VM は異なるクラウドやサードパーティー・ハイパーバイザー間で簡単に移動でき、ネストされた VM により利点が得られる分野の 1 つとして IaaS (Infrastructure as a Service) が挙げられます。
セットアップの説明では、次の用語を使用します。
- L0: ホスト OS。
- L1: 最初に作成されたゲスト VM。
- L2: L1 内に作成されたネストされたゲスト VM。
ここでは、以下の OS バージョンを使用します。
L0 = Red Hat* Enterprise Linux* 7 (3.17.4-2.el7.repo.x86_64)
L1 = Red Hat* Enterprise Linux* 7 (3.10.0-123.9.3.el7.x86_64)
L2 = Red Hat* Enterprise Linux* 7 (3.10.0-123.9.3.el7.x86_64)
ホスト (L0) をセットアップする
ネスト機能と VMCS シャドーイング機能は、ホスト (L0) レベルで有効にする必要があります。次のコマンドを使用して、これらの機能が有効かどうか確認できます。
VMCS シャドーイングが有効かどうか確認する:
L0 コマンドライン: cat /sys/module/kvm_intel/parameters/enable_shadow_vmcs
有効な場合は ‘Y’ が表示されます。
ネスト機能が有効化どうか確認する:
L0 コマンドライン: cat /sys/module/kvm_intel/parameters/nested
有効な場合は ‘Y’ が表示されます。
いずれかで ‘N’ が表示された場合は、モジュールの設定ファイルを編集します。
L0 コマンドライン: cd /etc/modprobe.d/
kvm-intel.conf という名前のファイルを作成します (まだファイルが存在しない場合)。kvm-intel.conf に次のオプションを追加します。
options kvm-intel nested=1
options kvm-intel enable_shadow_vmcs=1
ファイルを保存し、ホストを再起動します。
また、VMX 機能が有効になっていることも確認する必要があります。この機能はデフォルトで有効に設定され、有効な場合は CPU 情報のリストに表示されます。
L0 コマンドライン: cat /proc/cpuinfo
最初のゲスト VM (L1) をセットアップする
VMX 機能が L1 に渡されることを確認する必要があります。L1 をインストール後、この機能が利用できない場合は、virsh ツールを使用して L1 の設定ファイルを編集します。
L0 コマンドライン: virsh edit /etc/libvirt/qemu/L1_guest.xml
CPU 情報の後に次の行を追加し、ファイルを保存します。
<cpu mode=’host-passthrough’>
</cpu>
これで、L1 のCPU 情報のリストに vmx が表示されるはずです。
L1 コマンドライン: cat /proc/cpuinfo
ネストされた VM (L2) をセットアップする
L2 をセットアップする方法はいくつかあります。イメージファイルやロー・パーティションとしてセットアップしたり、あるいはイメージファイルとしてセットアップしてからロー・パーティションへのアクセスを追加することができます。目的に応じて、セットアップ方法を選択します。例えば、パフォーマンスのテストを行うことが目的ならば、デフォルトのイメージファイルの代わりにロー・パーティションを選択すると良いでしょう。
どのセットアップでも、ネットワーク・ブリッジを設定する必要があります。
ネストされた VM (L2) のネットワーク・ブリッジを設定する
ネストされた VM (L2) から最初のゲスト VM (L1) のネットワーク・アダプターへのネットワーク・ブリッジを設定する必要があります。この設定を行わないと、OS のインストール時にエラーになります。
私は、L1 上の Gnome* の仮想マシン・マネージャーでこの設定を行いました。[System Tools] > [Virtual Machine Manager] を選択し、[Virtual Machine Manager] 画面で [Edit] > [Connection Details] > [Virtual Networks] を選択します。そして、左下の + 記号をクリックします。デフォルトでは、私のゲスト VM のネットワークは 192.168.122.0/24 でした。次の設定で追加のネットワークを作成しました。
Name: nested bridge
Device: virbr1
Active
On Boot
IPv4 Forwarding: NAT to eth0
IPv6 Forwarding: Isolated network, routing disabled
Network: 192.168.166.0/24
DHCP start: 192.168.166.128
DHCP end: 192.168.166.254
ネストされた VM をインストールするときに、ネットワーク・インターフェイスにネストされたブリッジを選択します。
L2 をイメージファイルとしてセットアップする
L1 内にネストされた VM (L2) をイメージファイルとしてインストールする場合、ハードドライブの設定にはデフォルト値を使用できます。ネットワーク・インターフェイスには、前のステップで設定したネストされたブリッジを使用します。
L2 をロー・パーティションとしてセットアップする
L2 のインストールに必要なロー・パーティションを作成する
ロー・パーティションに VM をインストールする前に、fdisk でパーティションを作成する必要があります。L0 がインストールされているドライブ (/dev/sda) に、このパーティションを作成するのに十分な空き容量があると仮定します。
L0 コマンドライン: fdisk /dev/sda
n (パーティションのセットアップ) コマンドを実行します。
p (プライマリー・パーティションの作成) コマンドを実行します。
最初のシリンダーの開始位置は、Enter キーを押してデフォルト値を使用します。
最後のシリンダーの定義も、Enter キーを押してデフォルト値を使用します (VM に必要な容量があることを確認してください)。
変更を書き込む w コマンドを実行してから、fdisk を終了します。
L0 が /dev/sda1 にインストールされている場合、L2 用のパーティションは /dev/sda2 になります。ボリュームのフォーマットは VM のインストール時に行うため、ここでは行いません。
L1 設定ファイルを編集する
L2 をインストールする前に、ロー・パーティションが L1 にアクセスできるようにします。L1 設定ファイルを編集して、L2 をインストールするパーティションの場所を含めます。
L0 コマンドライン: virsh edit /etc/libvirt/qemu/L1_guest.xml
<controller type=’scsi’ model=’virtio-scsi’/>
<disk type=’block’ device=’lun’>
<driver name=’qemu’ type=’raw’ cache=’none’/>
<source dev=’/dev/sda’/>
<target dev=’sda’ bus=’scsi’/>
</disk>
ファイルを保存します。
これで、L2 の OS をインストールするときに、/dev/sda2 にアクセスすることができます。
L2 をロー・パーティションにインストールする
以下は、L1 のコマンドラインから、ネストされた VM をロー・パーティションに作成する例です。
L1 コマンドライン: virt-install -n nested-L2 -r 16000 –vcpus=4 -l /RHEL-7.0-Server-x86_64-dvd1.iso –disk path=/dev/sda2 -w network=nested_bridge
説明:
-n: | ネストされた VM の名前。 |
-r: | メモリー (この例では 16GB)。 |
-vcpus: | ネストされた VM の CPU 数。 |
-l: | Redhat* のインストールに必要な ISO イメージの場所。 |
-disk: | インストールする場所。この例では、前述のステップで作成した直接アクセス可能なパーティションを使用します。 |
-w: | 前述のステップで設定したブリッジ・ネットワーク。インストール中、パーティションに十分な空き容量がないため、必要な領域をリクレイムするかどうかを確認するメッセージが表示される場合があります。インストールを完了するには、必要な領域をリクレイムする必要があります。処理を続行する前に、正しいパーティションが指定されていることを確認してください。 |
L2 をイメージとしてセットアップしてから直接アクセス可能なパーティションを追加する
L0 で、fdisk を使用して L2 用の EXT3 パーティションを作成します。この例では、L2 用のパーティションとしてのみ使用される別のドライブ (/dev/sdb) があると仮定します。
L0 コマンドライン: fdisk /dev/sdb
n (パーティションのセットアップ) コマンドを実行します。
p (プライマリー・パーティションの作成) コマンドを実行します。
最初のシリンダーの開始位置は、Enter キーを押してデフォルト値を使用します。
最後のシリンダーの定義も、Enter キーを押してデフォルト値を使用します (VM に必要な容量があることを確認してください)。
変更を書き込む w コマンドを実行してから、fdisk を終了します。
次に、以下のコマンドでディスクをフォーマットします。
L0 コマンドライン: mkfs.ext3 /dev/sdb1
フォーマット後、このパーティションをホスト OS (L0) や最初のゲスト VM (L1) にマウントしないでください。異なるレベルの権限により問題が生じる可能性があります。
L2 が EXT3 パーティションにアクセスできるように、L1 と L2 のどちらからもそのパーティションの場所が見えるようにする必要があります。そのためには、設定ファイルを編集します。virsh を使用して、ゲスト VM の設定ファイルに 次の行を追加します。
L0 コマンドライン: virsh edit /etc/libvirt/qemu/L1_guest.xml
<controller type=’scsi’ model=’virtio-scsi’/>
<disk type=’block’ device=’lun’>
<driver name=’qemu’ type=’raw’ cache=’none’/>
<source dev=’/dev/sdb’/>
<target dev=’sdb’ bus=’scsi’/>
</disk>
ファイルを保存します。
L1 コマンドライン: virsh edit /etc/libvirt/qemu/L2_guest.xml
<controller type=’scsi’ model=’virtio-scsi’/>
<disk type=’block’ device=’lun’>
<driver name=’qemu’ type=’raw’ cache=’none’/>
<source dev=’/dev/sdb’/>
<target dev=’sdb’ bus=’scsi’/>
</disk>
ファイルを保存します。
L2 コマンドライン: mount /dev/sdb1 /mnt
これで、/mnt ディレクトリーにネストされた VM (L2) から直接アクセス可能な EXT3 ボリュームができました。
VM での操作
ここでは、異なる VM を操作する際に役立ついくつかの一般的なツールを紹介します。
VM 間でファイルを移動する
scp コマンドを使用して VM 間でファイルを移動できます。
現在ログイン中のシステムから別のシステムにファイルを移動する (プッシュ操作) には、次のコマンドを実行します。
scp ~/my_local_file.txt user@remote_host.com:/some/remote/directory
別のシステムから現在ログイン中のシステムにファイルを移動する (プル操作) には、次のコマンドを実行します。
scp user@192.168.1.3:/some/path/file.txt
コマンドラインから登録する
VM を登録することで yum からアップデートを簡単に取得できます。プロキシーサーバーを使用している場合は、登録の前にその設定を行う必要があります。
subscription-manager config –server.proxy_hostname=name_of_your_proxy_server –server.proxy_port=port_number_for_your_proxy_server
VM を登録するには、次のコマンドを実行します。
subscription-manager register –username your_account_name –password your_password –auto-attach
VM の IP アドレスを確認する
GUI インターフェイスではなく、ssh 接続で VM を操作していて、VM に割り当てられたネットワーク・アドレスを知りたい場合 (固定 IP アドレスを指定しなかった場合)、次のコマンドを実行します。
L1 コマンドライン: nmap -v -sP 192.168.166.0/24
アクティブな接続のリストが表示され、L2 の IP アドレスを確認できます。
VM Exit でデータを収集する
VM Exit に関連するデータを確認したい場合は、次の操作を行います。
最初のゲスト VM (L1) のプロセス ID 番号を特定します。
L0 コマンドライン: pgrep qemu-kvm
perf ツールを実行して、L0 のイベントを記録します: perf kvm stat record -p qemu-kvm_ID_number
重要: データ収集プロセスを終了するには Ctrl+C キーを押します。その他の方法で終了するとデータが破損します。
出力ファイルは、perf コマンドを実行したディレクトリーに作成される perf.data.guest ファイルです。このファイルは非常に大きくなることがあります。そのため、使用後は削除するか、システム以外の場所にアーカイブしてください。
確認したい項目に応じて、出力ファイルを確認する方法はいくつかあります。出力ファイルがあるディレクトリーで次のコマンドを実行します。
L0 コマンドライン: perf kvm stat report –event=vmexit
L0 コマンドライン: perf kvm stat report –event vmexit –key=time
L0 コマンドライン: perf kvm stat report –event vmexit –key=time –vcpu=0
必要に応じて、VM に関するより一般的な情報も利用できます。次のコマンドを実行します。
最初のゲスト VM (L1) のプロセス ID 番号を特定します。
L0 コマンドライン: pgrep qemu-kvm
L0 コマンドライン: perf stat –e ‘kvm:*’ –p qemu-kvm_ID_number
結論
ネストされた VM の作成には、目的と設定内容に応じてさまざまな課題があります。ここで紹介した情報が皆さんのお役に立つことを願っています。
関連情報
クリックしてintel-vmcs-shadowing-paper.pdfにアクセス
著者: David Mulnix は、ソフトウェア・エンジニアとして、インテル コーポレーションで 15 年以上にわたって、ソフトウェアの自動化、サーバーの電力およびパフォーマンス解析、クラウド・セキュリティーに取り組んでいます。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。