本章では、 openSUSE Leap 15.7 を QEMU-KVM ベースの仮想マシンホストとして動作させるまでの手順と、その使用方法について説明しています。
一般的に、仮想マシンのゲストシステムには、物理マシンにインストールする場合と同じだけのハードウエアリソースが必要となります。 VM ホストサーバ システム内で多くのゲストシステムを稼働させる場合、それだけ多くの CPU コアやディスク、メモリやネットワークなどを必要とすることになります。
KVM を動作させるには、お使いの CPU が仮想化機能に対応し、 BIOS 側でも仮想化機能が有効化されていなければなりません。 CPU の機能について調べるには、 /proc/cpuinfo
ファイル内に情報が書かれています。
KVM ホストに対しては、いくつかのパッケージをインストールする必要があります。必要な全てのパッケージをインストールするには、下記の手順を実施します:
まずは yast2-vm パッケージがインストールされていることを確認します。このパッケージは YaST の設定ツールで、仮想化のハイパーバイザのインストールを簡略化することができるものです。
› › を選択します。
を選択します。なお、必要であれば も選択します。選択を行ったら を押します。
インストール処理が始まります。なお、処理の途中で YaST 側から、
の自動作成を行うかどうかを尋ねられます。仮想化ゲストに対して専用のネットワークインターフェイスを割り当てるような場合は不要ですが、それ以外の場合はここでブリッジを作成して、ゲストマシンをネットワークに接続するのが一般的です。必要なパッケージを全てインストールし、必要であれば新しいネットワークブリッジの作成を行ったら、お使いの CPU の種類に合わせて KVM のカーネルモジュールを読み込みます。具体的には kvm_intel
もしくは kvm_amd
のいずれかを読み込みます:
#
modprobe kvm_intel
モジュールが正しく読み込めていることを確認します:
>
lsmod | grep kvm
kvm_intel 64835 6
kvm 411041 1 kvm_intel
これで KVM ホストの準備が整い、 KVM の VM ゲスト を開始することができるようになります。続きは 第36章 「qemu-system-ARCH を利用した仮想マシンの実行」 をお読みください。
VM ホストサーバ のハードウエアの機能を完全に生かし切る ( 準仮想化 を使用します) ことによって、 KVM ベースの VM ゲスト の性能を改善することができます。本章では、エミュレーションを介することなく、ゲスト側から物理ホストのハードウエアを直接アクセスするための技術について説明しています。
本章内で示しているコマンド例では、 qemu-system-ARCH
コマンドのオプションについて知っていることを前提にして説明しています。詳しくは 第36章 「qemu-system-ARCH を利用した仮想マシンの実行」 をお読みください。
virtio-scsi
を利用したホスト側ストレージの使用 #Edit sourcevirtio-scsi
は KVM 向けの高度なストレージスタックです。これは従来 SCSI デバイスのパススルーで使用していた virtio-blk
スタックの置き換えとして生まれた仕組みでもあります。 virtio-blk
と比較すると、下記の利点があります:
KVM ゲストに設定できる PCI コントローラには制限が存在することから、接続できるデバイス数にも制限が生まれる結果になっています。 virtio-scsi
では、複数のストレージデバイスを単一のコントローラにまとめることによって、この制限を乗り越えることができるようになっています。 virtio-scsi
コントローラ内のデバイスは論理ユニット (LUN) として現れるようになっています。
virtio-blk
では virtio-blk
のドライバと仮想マシンモニタの両方で共通する少数のコマンドセットのみを使用していたため、新しいコマンドを追加するにも、ドライバとモニタの両方を更新する必要がありました。
virtio-scsi
ではコマンドを定義せずに伝送プロトコルを定義し、それらのコマンドを工業規格である SCSI 仕様に従って送信するようになっています。このようなアプローチにより、ファイバーチャネルや ATAPI, USB デバイスなどの他の技術とも共用がはかれるようになっています。
virtio-blk
でのデバイスはゲスト内で /dev/vdX
として現れるようになっていました。そのため物理システムとはデバイス名が異なることにより、移行時の障害になっていました。
virtio-scsi
では物理システムと同じデバイス名になるようになっています。そのため、仮想マシンを容易に再配置できるようになっています。
ホスト内の LUN 全体を表す仮想ディスクの場合、ゲストから SCSI コマンドを直接 LUN に送信 (パススルー) したほうが良い場合があります。これは virtio-blk
の場合、ゲスト側では SCSI コマンドではなく virtio-blk プロトコルを使用していることから実現できませんし、 Windows ゲストの場合でも利用できません。 virtio-scsi
では SCSI そのものを使用しますので、何も問題なく対応できることになります。
virtio-scsi
の使用方法 #Edit sourceKVM では virtio-scsi-pci
デバイスで SCSI のパススルー機能に対応しています:
#
qemu-system-x86_64 [...] \
-device virtio-scsi-pci,id=scsi
vhost-net
を利用したネットワーク処理の高速化 #Edit sourcevhost-net
モジュールは KVM の準仮想化ネットワークドライバを高速化するために使用するモジュールです。遅延とスループットの改善をそれぞれ提供します。 vhost-net
ドライバを使用するには、下記のようにしてコマンドラインで指定します:
#
qemu-system-x86_64 [...] \
-netdev tap,id=guest0,vhost=on,script=no \
-net nic,model=virtio,netdev=guest0,macaddr=00:16:35:AF:94:4B
ここで、 guest0
はデバイスの識別用文字列です。
VM ゲスト 内での仮想 CPU 数を増やす場合、 QEMU では マルチキュー と呼ばれる仕組みを利用して、ネットワーク性能を改善することができます。マルチキュー型の virtio-net では、複数の VM ゲスト の仮想 CPU が同時にパケットを送信することができるようになりますので、ネットワークの性能を大きく向上させることができます。なお、マルチキューへの対応は、 VM ホストサーバ と VM ゲスト の両方で行う必要があります。
マルチキュー型の virtio-net ソリューションは、下記のような場合に有用です:
ネットワークトラフィックのパケットが大きい場合。
VM ゲスト 内で多数の接続を同時に処理する必要がある場合。これはゲストシステム間だけでなく、ゲストとホストの間やゲストと外部システムの間でも有用です。
VM ゲスト 内での有効なキュー数と仮想 CPU の数が一致している場合。
マルチキュー型の virtio-net は全体のネットワーク性能を強化する仕組みであるため、仮想 CPU の使用率も上がることになります。
下記の手順では qemu-system-ARCH
を利用してマルチキュー機能を有効化する場合の、主な流れを説明しています。なお、 VM ホストサーバ 側にはマルチキュー機能に対応した tap ネットワークデバイス (カーネルバージョン 3.8 以降で対応しています) が既に設定されているものとします。
tap デバイスに対してマルチキュー機能を有効化するには、 qemu-system-ARCH
に下記を追加します:
-netdev tap,vhost=on,queues=2*N
ここで、 N
にはキュー対の数を指定します。
さらに qemu-system-ARCH
側でマルチキューを有効化し、 virtio-net-pci デバイスに対する MSI-X (Message Signaled Interrupt (メッセージシグナル型割り込み)) ベクトルを指定します:
-device virtio-net-pci,mq=on,vectors=2*N+2
ここで、 MSI-X ベクトルの数 (vectors=) は下記のようにして計算します: まず TX (送信) キュー用に N 個、 RX (受信) 用に N 個、設定用に 1 個、そして発生しうる VQ (Vector Quantization (ベクトル量子化)) 制御用に 1 個を用意します。つまり、合計で 2*N+2 になります。
VM ゲスト 側でネットワークインターフェイスに対してマルチキューを有効化します (下記はデバイスが eth0
である場合の例です):
>
sudo
ethtool -L eth0 combined 2*N
生成された qemu-system-ARCH
のコマンドラインは、下記のようになるはずです:
qemu-system-x86_64 [...] -netdev tap,id=guest0,queues=8,vhost=on \ -device virtio-net-pci,netdev=guest0,mq=on,vectors=10
ここで、ネットワークデバイスの id
( guest0
) は、両方に同じ値を指定する必要があることに注意してください。
VM ゲスト 内では、 root
権限で下記のようなコマンドを入力して実行します:
>
sudo
ethtool -L eth0 combined 8
これでゲストシステムのネットワークインターフェイスは、 qemu-system-ARCH
ハイパーバイザが提供するマルチキュー機能に対応するようになっています。
VM ゲスト に対する PCI デバイスの直接割り当て (PCI パススルー) を使用することで、性能を重視する環境ではエミュレーションに必要な処理を回避することができます。 VFIO は従来の KVM PCI パススルー デバイス割り当てを置き換えるよう作成された仕組みで、この機能を利用するには 重要: VFIO および SR-IOV の要件について で説明している要件を満たす必要があります。
VFIO を利用して PCI デバイスを VM ゲスト に割り当てることができるようにするには、まず所属する IOMMU グループが何であるのかを調べる必要があります。 IOMMU (Input/Output Memory Management Unit; メインメモリへの直接メモリアクセスに対応した I/O バス) API にはグループという概念があります。グループはデバイスの集合で、システム内での境界線として使用しているものです。そのため、グループは VFIO が使用する所有権の単位であると言えます。
まずはゲストに割り当てるホスト側の PCI デバイスを識別します。
>
sudo
lspci -nn [...] 00:10.0 Ethernet controller [0200]: Intel Corporation 82576 \ Virtual Function [8086:10ca] (rev 01) [...]
対象のデバイスのデバイス ID (この例では 00:10.0
) と製造元 ID ( 8086:10ca
) をそれぞれメモしておきます。
このデバイスの IOMMU グループを判別します:
>
sudo
readlink /sys/bus/pci/devices/0000\:00\:10.0/iommu_group ../../../kernel/iommu_groups/20
このデバイスの IOMMU グループは 20
であることがわかりました。あとは同じ IOMMU グループに属しているデバイスを確認します:
>
sudo
ls -l /sys/bus/pci/devices/0000\:01\:10.0/iommu_group/devices/ [...] 0000:00:1e.0 -> ../../../../devices/pci0000:00/0000:00:1e.0 [...] 0000:01:10.0 -> ../../../../devices/pci0000:00/0000:00:1e.0/0000:01:10.0 [...] 0000:01:10.1 -> ../../../../devices/pci0000:00/0000:00:1e.0/0000:01:10.1
デバイスドライバからデバイスを取り外します:
>
sudo
echo "0000:01:10.0" > /sys/bus/pci/devices/0000\:01\:10.0/driver/unbind
上記で取得した製造元 ID を指定して、デバイスを vfio-pci ドライバに接続します:
>
sudo
echo "8086 153a" > /sys/bus/pci/drivers/vfio-pci/new_id
上記を実行すると、 /dev/vfio/IOMMU_グループ
という新しいデバイスが作成されます。上記の例の場合は /dev/vfio/20
になります。
新しく作成したデバイスの所有者を変更します:
>
sudo
chown qemu.qemu /dev/vfio/デバイス名
あとは割り当てた PCI デバイスを指定して VM ゲスト を起動します。
>
sudo
qemu-system-ARCH [...] -device vfio-pci,host=00:10.0,id=ID
openSUSE Leap 15.7 では、 VFIO を介した PCI デバイスのホットプラグによる VM ゲスト への接続はサポートしていません。
VFIO ドライバに関するさらに詳しい情報については、 /usr/src/linux/Documentation/vfio.txt
(英語) をお読みください (kernel-source
パッケージをインストールする必要があります) 。
VM ゲスト は通常、個別の作業領域で動作します。メモリ範囲や CPU を独自に割り当てるほか、ファイルシステムも別々になります。 VM ホストサーバ 側のファイルシステムとの間で共有を行うことで、相互のデータ交換をより柔軟に行うことができるようになります。 CIFS や NFS などのネットワーク型のファイルシステムでもディレクトリの共有を行うことができますが、これらは仮想化用に設計されたものではありませんので、十分な性能を提供することができないほか、機能面の問題に直面する可能性もあります。
KVM では新しく最適化された VirtFS (「ファイルシステムのパススルー」 と呼ぶこともあります) を提供しています。 VirtFS は準仮想化型のファイルシステムドライバで、ゲスト側でのファイルシステム操作をブロックデバイスの操作に変換する処理を行うことなく、そのままホスト側のファイルシステム操作に変換することができます。
VirtFS の機能は下記のような用途で使用することができます:
複数のゲストから共通のディレクトリにアクセスする必要がある場合や、ゲスト間で同じファイルシステムにアクセスする必要がある場合。
ゲスト側の RAM ディスクで、起動時にアクセスするルートファイルシステムの代替として使用したい場合。
クラウド環境で、ホスト側のファイルシステムを複数の顧客に提供するようなストレージサービスを構成するような場合。
QEMU では、 VirtFS の実装を下記の 2 種類のデバイスとして提供しています:
virtio-9p-pci
: プロトコルのメッセージとデータを、ホストとゲストの間で伝送するデバイス。
fsdev
: ファイルシステムの種類やセキュリティモデルなど、ファイルシステムの属性情報を提供するためのデバイス。
>
sudo
qemu-system-x86_64 [...] \ -fsdev local,id=exp11,path=/tmp/2,security_model=mapped3 \ -device virtio-9p-pci,fsdev=exp14,mount_tag=v_tmp5
公開するファイルシステムの識別子を指定します。 | |
公開するファイルシステムのホスト内でのパスを指定します。 | |
使用するセキュリティモデルを指定します。 | |
| |
ゲスト側でマウントを行う際、タグとして使用する名前を指定します。 |
上記のようにファイルシステムを公開した場合、ゲスト側では下記のようにしてマウントすることができます:
>
sudo
mount -t 9p -o trans=virtio v_tmp /mnt
ここで、 v_tmp
は -device mount_tag=
で指定したタグ名を、 /mnt
は公開されたファイルシステムをマウントする先をそれぞれ指定します。
Kernel Same Page Merging ( KSM ) は Linux カーネルの機能で、複数のプロセス内にある同一のメモリページを、 1 つのメモリ領域にまとめる機能のことを指します。 KVM ゲストは Linux 内のプロセスとして存在することになりますので、 KSM を使用することでハイパーバイザがメモリをより効率的に使用し、オーバーコミット機能 (搭載されているメモリよりも多くのメモリを提供する機能) を提供することにもなります。そのため、メモリの限られたホスト内で複数の仮想マシンを動作させる必要がある場合、 KSM を利用することで解決できる場合があることになります。
KSM では、 /sys/kernel/mm/ksm
ディレクトリ内に、その状態に関する情報を含むファイルを提供します:
>
ls -1 /sys/kernel/mm/ksm
full_scans
merge_across_nodes
pages_shared
pages_sharing
pages_to_scan
pages_unshared
pages_volatile
run
sleep_millisecs
/sys/kernel/mm/ksm/*
ファイルのそれぞれの意味について、詳しくは /usr/src/linux/Documentation/vm/ksm.txt
(英語) をお読みください (kernel-source
パッケージ内に含まれています) 。
KSM を使用するには、下記の手順を実施します:
openSUSE Leap では、 KSM のサポートがカーネル内に含まれていますが、既定では無効化されています。有効化するには、下記のコマンドを実行します:
#
echo 1 > /sys/kernel/mm/ksm/run
あとは必要な VM ゲスト を KVM 内で動作させます。機能が正しく動作しているかどうかを調べるには、 pages_sharing
と pages_shared
のファイルの内容を調べてください:
>
while [ 1 ]; do cat /sys/kernel/mm/ksm/pages_shared; sleep 1; done
13522
13523
13519
13518
13520
13520
13528