
引用元:linux-kvm.org
前の記事
本記事では、KVMの初期設定が完了していることを前提としています。
初期設定手順に興味のある方は、以下の記事もご参照ください。
virt-manager、Cockpitのセットアップについては、以下の記事をご参照ください。
お伝えしたいこと
KVMの基本操作をケース別に紹介します。
基本はCLIの手順紹介がメインです。
virt-managerとCockpitのスクリーンショットも載せていますが、今後画面のデザインが変わっても原則更新しません。
GUIの手順については、雰囲気を掴むためのおまけと思っていただければ幸いです。
- 前の記事
- お伝えしたいこと
- VMの作成
- VMの削除
- VMの起動
- VMの停止
- VMのクローン
- CDドライブにISOファイルをセットする
- 起動順序の設定
- 仮想ネットワークの作成
- ストレージプールの作成
- 仮想ディスクイメージファイルの拡張
- (参考) DHCPで割り当てているIPアドレスの一覧表示
- まとめ
VMの作成
virt-installで行う場合
過去記事を参照してください。
virt-managerで行う場合
過去記事を参照してください。
Cockpitで行う場合
過去記事を参照してください。
VMの削除
virshで行う場合
過去記事を参照してください。
virt-managerで行う場合
VMを右クリックして "Delete" します。


Cockpitで行う場合
仮想マシン一覧の画面で … をクリックして "Delete" します。


VMの起動
virshで行う場合
VMの起動にはvirsh startを使います。
コマンドがわかりやすいので、普段GUIを使っていてもvirsh startだけはCLIといった使い方ができるかなと思います。
virsh start vm_name
以下に具体例を示します。
# VMの一覧を表示 virsh list --all # - fedora33 shut off virsh start fedora33 # Domain 'fedora33' started
virt-managerで行う場合
トップ画面で対象のVMを右クリック → Runで起動します。

Cockpitで行う場合
仮想マシン一覧の画面で対象のVMを探し、"Run"をクリックします。

VMの停止
virshで行う場合
VMの停止にはvirsh shutdownを使います。
このコマンドはshutdownシーケンスがちゃんと走るので、VMに優しいです。
VMがハングしている場合や、OSインストール画面などOS起動前の状態など、shutdownを受け付けないケースもありえます。
そんなときは、virsh destroyを使います。
destroyというとVMを破壊しそうですが、実際にはVMの強制終了を意味します。
ニュアンスとしては「VMプロセスをdestroy (kill) する」のであって、VMのXML定義ファイルには触れません。
virsh shutdown fedora33
virsh destroy fedora33
virt-managerで行う場合
トップ画面で対象のVMを右クリック → Shut Down → Shut Down でシャットダウンします。
右クリック → Shut Down → Forced Off で強制終了します。

Cockpitで行う場合
仮想マシン一覧の画面で対象のVMを探し、Shut downでVMをシャットダウンします。
… をクリックして "Force shut down" でVMを強制終了します。

VMのクローン
virt-cloneで行う場合
virt-cloneコマンドでクローンできます。
前提として、まずはVM名を調べておきます。
virsh listはデフォルトで起動しているVMしか表示しませんが、--allをつけることで全てのVMを表示できます。
virsh list --all # Id Name State # --------------------------- # - fedora33 shut off
fedora33というVMをクローンします。
新しいVMの名前は、f33_newとします。
virt-clone --original fedora33 --name f33_new --auto-clone # Allocating 'f33_new.qcow2' | 20 GB 00:00:05 # Clone 'f33_new' created successfully.
virt-cloneの主なオプションは以下のとおりです。
--originalでコピー元のVM名、--nameでコピー先のVM名、--fileでコピー先のVMイメージファイルのフルパスを指定するのが基本です。
個人的には、上記のように--nameと--auto-cloneを併用し、イメージファイル名を--nameで指定した文字列から自動生成させるのが便利に感じました。
| オプション | 意味 |
|---|---|
| -o, --original |
コピー元のVM名を指定 |
| -n, --name |
コピー先のVM名を指定 |
| -f, --file |
コピー先のVMが利用するディスクイメージファイルのフルパスを指定 |
| --auto-clone | --name、--fileの片方または両方を自動的に決定する。--nameを自動生成するときは、fedora33-cloneのように-cloneをつける。更にクローンすると、 fedora33-clone-1, fedora33-clone-2, ...と連番をつける。--fileを自動補完した場合、defaultプール配下にVM名.qcow2が生成した(※)。--nameのみ明示的に指定した場合は、イメージファイル名の自動補完には--nameの文字列が使用された(※) |
(※) man virt-cloneにはこの仕様は書いていません。私の環境で実機検証した結果、このようになりました
virt-cloneはvirt-installパッケージに同梱されています。
dnf provides virt-cloneや、dnf repoquery -l virt-installなどで確認できます。
virt-managerで行う場合
VM名を右クリックして "Clone" します。


Cockpitで行う場合
仮想マシン一覧の画面で … をクリックして "Clone" します。


CDドライブにISOファイルをセットする
virshで行う場合
まずはVM名を指定して、紐付いているデバイス名を確認します。
VM名を調べたい場合は、virsh list --allを先に実行してください。
以下のコマンド出力から、sdaにCDドライブが存在することがわかりました。
virsh domblklist fedora33 --details # Type Device Target Source # ------------------------------------------------------------------- # file disk vda /home/shared/libvirt/disks/fedora33.qcow2 # file cdrom sda - # file cdrom sdb -
virsh change-mediaコマンドにより、CDROMにISOファイルをセットします。
virsh change-media fedora33 sda /home/shared/isos/fedora/Fedora-Server-dvd-x86_64-33-1.2.iso # Successfully updated media.
もう一度確認コマンドを実行し、ISOファイルがセットされたことを確認します。
virsh domblklist fedora33 --details # Type Device Target Source # ----------------------------------------------------------------------------------------- # file disk vda /home/shared/libvirt/disks/fedora33.qcow2 # file cdrom sda /home/shared/isos/fedora/Fedora-Server-dvd-x86_64-33-1.2.iso # file cdrom sdb -
virsh change-mediaの構文は以下のとおりです。
virsh change-media domain-name path [--eject|--insert|--update] [source]
キーワードの意味は下表のとおりです。
| キーワード | 説明 |
|---|---|
| domain-name | domain、つまりVMの名前 |
| path | 捜査対象のCDドライブのデバイス名。 sda, vda, hda などの文字列が入る |
| --eject | CDドライブの中身を空にする。 sourceの指定は不要 |
| --insert | CDドライブにISOファイルをセットする。 sourceの指定は必須 |
| --update | sourceを指定した場合、--ejectしてから--insertする。 sourceを指定しなかった場合、--ejectのみ実行する。 --eject, --insert, --update をいずれも指定しなかった場合、デフォルトで--updateが選択される |
| source | ISOファイルを指定する。 --ejectを指定した場合は、sourceの入力は不要。 --insertを指定した場合はsourceの入力は必須。 --updateを指定した場合は、sourceを入力するか否かで挙動が変わる |
virt-managerで行う場合
VMの詳細画面で、"SATA CDROM"からISOファイルのパスを指定します。

Cockpitで行う場合
仮想マシン一覧の画面で、捜査対象の仮想マシン名をクリックして詳細画面を開きます。
中段の "Disks" セクションの "Add disk" をクリックし、以下のように選択します。
| 設定項目 | 詳細 |
|---|---|
| Source | Custom path |
| Custom path | (ISOファイルのパス) |
| Device | CD/DVD dusk |


起動順序の設定
virshで行う場合
HDD、CDドライブなど複数のディスクを持ったVMを起動する際の起動順序の制御方法を紹介します。
起動順序を制御するためのvirshサブコマンドは、2021年時点では存在しないようです。
従って、virsh edit VM_NAMEでXMLファイルを直接編集します。
編集は以下のように行います。
<os>セクション配下の<boot>セクションを削除する<disk>セクション配下に<boot order>セクションを追加する
例えば、編集前のファイルが以下の状態だったとします。
(中略) <os> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <boot dev='hd'/> </os> (中略) <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/home/shared/libvirt/disks/fedora33.qcow2'/> <backingStore/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> </disk> <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <target dev='sda' bus='sata'/> <readonly/> <address type='drive' controller='0' bus='0' target='0' unit='0'/> </disk> (中略)
編集後のファイルは、以下のようになります。
<os>配下の<boot>を削除し、<disk>配下に<boot order>を追加しました。
<boot order>には'1'以上の値を指定し、値が小さいほど優先順位が高くなります。
今回の場合は、device='disk'が第一優先で、device='cdrom'が第二優先になっています。
<boot order>が付いていないデバイスは、そもそも起動デバイスの候補から外れます。
(中略) <os> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> </os> (中略) <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/home/shared/libvirt/disks/fedora33.qcow2'/> <backingStore/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> <boot order='1'/> </disk> <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <target dev='sda' bus='sata'/> <readonly/> <address type='drive' controller='0' bus='0' target='0' unit='0'/> <boot order='2'/> </disk>
手順としては以上です。
最後に、libvirt公式サイトのリンクを貼ります。
公式に書いてあるように、<boot order>が使えるかどうかはハイパーバイザー次第のようです。
幸いにも、QEMUは<boot order>に対応していました。
<boot order>より以前にある指定方法として<boot>もありますが、こちらは理由がなければ基本使いません。
Disk、CDといった粒度で起動の優先順位を指定することはできますが、Diskが2つ以上存在した時、どちらのDiskを使うかの挙動が複雑です。
可能な限り、DiskやCDが同種類で複数存在する場合でも優先順位を指定できる<boot order>を使うようにしましょう。
<boot>に関する情報は以下のリンクにあります。
virt-managerで行う場合
GUIを使えば、virshよりも簡単な操作で設定できます。
以下のVMの設定画面で、起動デバイスに設定したいデバイスにチェックを入れ、▲▼で優先順位を指定するだけです。
※以下の画像は▲▼が黒くて見えづらいので若干合成してあります

Cockpitで行う場合
仮想マシンの詳細画面を開き、"Boot order" の "edit" をクリックして編集するだけです。
こちらも簡単ですね。


仮想ネットワークの作成
概要
仮想ネットワークにはいくつかのタイプがあります。
私が使ったことがあるのは、以下の2種類です。
多くの場合はNATのみで事足りますが、VM間通信用のネットワークセグメントを複数作成したい場合はNoneのネットワークも1つ追加すると便利です。
また、仮想ネットワーク内でDHCPを使うことができます。
DHCPにより、作成したVMに自動的にIPアドレスやデフォルトゲートウェイの設定を配布できます。
ネットワークサイズが/24だとすると、DHCPアドレスを.101〜.254のようにしておくと、.2〜.100を静的に割り当てることもできるので便利です。
.1はゲートウェイのアドレスに使われるので、この部分は残しておきます。
さて、以降で具体的な手順に入ります。
virshで行う場合
CLIの手順はlibvirt wikiを参考にしました。
net-createというコマンドがありますが、xmlファイルを指定することでしか作成できません。
従って、基本的には既存のXMLファイルを雛形にして編集することになると思います。
まず、virsh net-list --allで仮想ネットワーク名を確認します。
--allをつけることで、起動していない仮想ネットワークも表示します。
virsh net-list --all # Name State Autostart Persistent # ---------------------------------------------- # default active yes yes # internal1 active yes yes
新規の仮想ネットワークを作る場合は、/usr/share/libvirt/networks/default.xmlを雛形にすると便利です。
以下のようにXMLファイルをコピーします。
cp /usr/share/libvirt/networks/default.xml tmp.xml cat tmp.xml # <network> # <name>default</name> # <bridge name="virbr0"/> # <forward/> # <ip address="192.168.122.1" netmask="255.255.255.0"> # <dhcp> # <range start="192.168.122.2" end="192.168.122.254"/> # </dhcp> # </ip> # </network>
既に作成済みの仮想ネットワークを雛形にする場合は、virsh net-dumpxmlで既存の仮想ネットワークのXMLファイルをtmp.xmlとして保存しておきます。
virsh net-dumpxml default | tee tmp.xml # <network connections='1'> # <name>default</name> # <uuid>b130cf72-a5eb-4414-9fd8-7d1182f2b50b</uuid> # <forward mode='nat'> # <nat> # <port start='1024' end='65535'/> # </nat> # </forward> # <bridge name='virbr0' stp='on' delay='0'/> # <mac address='52:54:00:96:e6:67'/> # <ip address='192.168.122.1' netmask='255.255.255.0'> # <dhcp> # <range start='192.168.122.101' end='192.168.122.254'/> # </dhcp> # </ip> # </network>
<name>と<domain nameを仮想ネットワーク名に変更します。
(※) domain nameの行は、場合によっては存在しないこともあります
<uuid>、<bridge name、<mac addressの行を削除します。
これらの値はlibvirtによって重複しない値を自動生成させます。
書き換え後の例を以下に示します。
ちなみにlibvirt wikiによると、<forward/>の部分は<forward mode='nat'/>がデフォルト値となります。
NATモードではなく、None (Isolated) モードにしたい場合は、<forward/>行を削除してください。
cat tmp.xml # <network> # <name>tmp</name> # <forward/> # <ip address="192.168.200.1" netmask="255.255.255.0"> # <dhcp> # <range start="192.168.200.101" end="192.168.200.254"/> # </dhcp> # </ip> # </network>
以下のコマンドにより、仮想ネットワークを作成します。
net-defineコマンドの場合は、XMLファイルとして構成を保持します。
net-defineをnet-createに置き換えることで、undefined状態 (メモリ上にしか存在せず、destroyすると直ちに消える) の仮想ネットワークを作成することもできます。
virsh net-define tmp.xml
# Network tmp defined from tmp.xml
作成したtmpの情報を表示します。
net-listの出力より、tmpの定義直後はまだ起動しておらず、OSブート時に自動起動もしないことがわかります。
net-dumpxmlの出力より、UUIDやMACアドレスの値、NAT設定などが自動生成していることがわかります。
virsh net-list --all # Name State Autostart Persistent # ------------------------------------------------ # default active yes yes # internal1 active yes yes # tmp inactive no yes virsh net-info tmp # Name: tmp # UUID: 3bfd3e32-9531-4e67-a2b0-963df9f4cc85 # Active: yes # Persistent: yes # Autostart: no # Bridge: virbr2 virsh net-dumpxml tmp # <network> # <name>tmp</name> # <uuid>85a1cccf-dc54-4164-8e72-a6f020b4883c</uuid> # <forward mode='nat'/> # <bridge name='virbr2' stp='on' delay='0'/> # <mac address='52:54:00:55:21:d6'/> # <ip address='192.168.200.1' netmask='255.255.255.0'> # <dhcp> # <range start='192.168.200.101' end='192.168.200.254'/> # </dhcp> # </ip> # </network>
以下のコマンドによって仮想ネットワークを起動し、通信可能な状態にします。
更に、自動起動も有効化します。
virsh net-start tmp # Network tmp started virsh net-autostart tmp # Network tmp marked as autostarted
再び確認コマンドで表示します。
State=active, Autostart=yesとなりました。
virsh net-list --all # Name State Autostart Persistent # ---------------------------------------------- # default active yes yes # internal1 active yes yes # tmp active yes yes
仮想ネットワークを削除する際は、destroy (強制終了。startの反対) とundefine (設定削除。defineの反対) を行います。
virsh net-destroy tmp # Network tmp destroyed virsh net-undefine tmp # Network tmp has been undefined
削除後、tmpが表示されなくなることを確認します。
virsh net-list --all # Name State Autostart Persistent # ---------------------------------------------- # default active yes yes # internal1 active yes yes
virt-managerで行う場合
トップ画面において、コネクション、またはコネクション配下のVMを選択した状態で、上部メニューからEdit > Connection Detailsを開きます。
または、下図赤枠部分のコネクション名の部分を右クリックして、Detailsを選択します。

Virtual Networksタブを開き、左下の+ボタンから仮想ネットワークを追加します。
※以下の画像は+-が黒くて見えづらいので若干合成してあります


Cockpitで行う場合
仮想マシン一覧から、右上の"Networks"を選択します。

右上の"Create virtual network"を選択します。

必要事項を入力して、Createします。
Cockpit 249では、Forward modeがNAT、Open、None (isolated mode) の3種類しか選べませんでした。
将来的にアップデートされるとは思いますが、もし機能的に困る場合はvirshかvirt-managerを使うようにしてください。
私の検証用途では凝ったことはしないので、私としてはそれほど困りませんでした。

ストレージプールの作成
ストレージプールという言葉自体の解説は、KVMの初期設定、及びvirsh, virt-installによるVM作成 - pool作成の事前準備を参照してください。
virshで行う場合
以下のコマンドでPoolを定義します。
Pool名、Poolと紐付けるディレクトリパスは適宜変更してください。
virsh pool-define-as kickstart dir --target /home/shared/libvirt/kickstarts
virsh pool-define-asのSyntaxは以下のとおりです。
| パラメータ | 意味 |
|---|---|
kickstart(第一引数) |
Pool名 |
dir(第二引数) |
Pool Type名。 他にも fsやdiskなど多数あるが、本ブログで紹介したのはdirのみ (参考) |
--target .. |
dir Typeの場合は指定必須。Poolと紐付けるディレクトリパスを指定する |
作成したPoolを確認します。
作成直後のPoolは停止しているので、--allオプションをつけることで停止中のPoolも含めて表示します。
virsh pool-list --all # Name State Autostart # --------------------------------- # default active yes # kickstart inactive no
Poolを今すぐ起動します。
また、Autostartを有効化することで、OS起動時にPoolも自動起動するように設定します。
virsh pool-start kickstart # Pool kickstart started virsh pool-autostart kickstart # Pool kickstart marked as autostarted
Poolの状態を再度確認します。
Poolが起動状態になり、Autostartも有効化されました。
virsh pool-list # Name State Autostart # --------------------------------- # default active yes # kickstart active yes
Poolの停止はvirsh pool-destroy kickstart、Poolの定義削除はvirsh pool-undefine kickstartコマンドにて行います。
virt-managerで行う場合
トップ画面において、コネクション、またはコネクション配下のVMを選択した状態で、上部メニューからEdit > Connection Detailsを開きます。
または、下図赤枠部分のコネクション名の部分を右クリックして、Detailsを選択します。

Storageタブを開き、左下の+マークを選択します。

必要なパラメータを入力し、Finishを選択します。

Cockpitで行う場合
仮想マシン一覧の画面で、左上にあるStorage poolsのリンクをクリックし、Pool一覧の画面を開きます。

画面右上のCreate storage poolをクリックし、Pool作成画面を開きます。

必要なパラメータを指定してPoolを作成します。
以下は/home/shared/libvirt/kickstarts/ディレクトリと紐づく、kickstartという名前のPoolを作成する例です。

Activateボタンをクリックし、作成したPoolを起動します。

仮想ディスクイメージファイルの拡張
ディスクファイル (qcow2) のサイズ変更は、2021/11時点ではCLIでしかできないようです。
したがって、virshの手順のみ紹介します。
virshで行う場合
Linuxのディスク拡張手順 #qcow2ファイルの拡張を参照してください。
(参考) DHCPで割り当てているIPアドレスの一覧表示
virshで行う場合
virsh net-dhcp-leases <network-name>でDHCPリースしているIPアドレスを一覧表示できます。
VMのIPアドレスをDHCPで設定しているとき、VMにSSHする前にIPアドレスを調べる際に便利です。
ネットワークの一覧はvirsh net-listで確認できますが、多くの場合はdefaultを使っているのではないかと思います。
virsh net-dhcp-leases default # Expiry Time MAC address Protocol IP address Hostname Client ID or DUID # ------------------------------------------------------------------------------------------------------ # 2022-02-27 13:41:03 52:54:00:6c:54:c8 ipv4 192.168.122.127/24 stream9-1 01:52:54:00:6c:54:c8
よく使うコマンドなので、ワンライナーをaliasとして登録するのも便利かもしれません。
私の環境では、以下の内容を~/.bashrcに登録しています。
alias ips=$'virsh net-dhcp-leases default | sed -ne \'3,$p\' | grep -v ^$ | awk \'gsub(/\/[0-9]+/, "", $0) { print $6,$5 }\''
実行すると以下のようになります。
短い入力でコピペしやすいシンプルな出力が得られます。
ips
# stream9-1 192.168.122.127
上記はANSI C Quoting ($' ')を使っています。
通常のシングルクォーテーション (' ')と比較して、シングルクォーテーション自体を \' でエスケープできるのが便利なので使っています。
bash以外の環境ではANSI C Quotingが使えないかもしれないので、ダブルクォーテーションを使ったパターンも併記しておきます。
ダブルクォーテーションを使う場合は$"\、そしてバックティックもエスケープ対象になるので、少々見づらくなります。
(参考: Double Quotes)
#alias ips="virsh net-dhcp-leases default | sed -ne '3,\$p' | grep -v ^\$ | awk 'gsub(/\/[0-9]+/, \"\", \$0) { print \$6,\$5 }'"
virt-managerで行う場合
virt-managerには、DHCPリースを一覧表示する機能は無いようです。
仮想マシンの詳細設定画面でNICの項目から読み取ることはできます。
しかし、仮想マシン1台分の情報しか確認できません。

Cockpitで行う場合
Cockpitには、DHCPリースを一覧表示する機能は無いようです。
仮想マシンの詳細設定画面でNetwork Interfacesの項目から読み取ることはできます。
しかし、仮想マシン1台分の情報しか確認できません。

まとめ
KVM周りの各種基本操作についてご紹介しました。
慣れないうちはGUIで、慣れてきたらVMの起動/停止など簡単な部分からCLIに移行し、徐々に作業効率を上げていきましょう。