Debianの仮想化環境(KVM)
仮想化の機能は様々提供されていますが、ここではDebian(Linux)で提供されているKVM(Kernel-based Virtual Machine)を試してみたいと思います。ホストとなるOSをCUIで動かせるためオーバーヘッドが少なくて済みます。
この仮想環境にはWindows10ものせられますが、Microsoft:「ライセンス簡易ガイド」にあるように、OEM版(PCにプリインストールされているもの)には仮想化環境にする権利がないそうです。
仮想化拡張機能
KVMは仮想マシンを作成実行するモジュールです。
KVMを利用するにはCPUが「仮想化拡張機能」を持っている必要があります。
仮想化拡張機能の製品名はintel VT-xまたは、AMD-Vといったものです。
まずそれを確認します。Red Hat Customer Portal「仮想化拡張機能を確認する」を参考に、Linuxのcpuinfoを確認します。
/proc/cpuinfoのflagsの項目に、「vmx」の文字があればinterl VT-x、「svm」の文字があればAMD-Vの機能があるという事になります。
ただし、BIOSやUEFIの設定でこの機能がOFFにされていたら表示されません。
# cat /proc/cpuinfo | grep flags
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust smep erms invpcid mpx rdseed smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d
土台となるDebianをインストール
Debian Wiki「KVM」や、Server World:「KVM」を参考にDebian11をホストにして、Windows10とDebian10(GUI:Xfce)をインストール作業を進めます。
Debian11のCUIをインストールします。isoをCDに焼いてもいいですが、USBメモリでも代用できます。
イメージは、cdimage.debian.or.jpからisoファイルをダウンロードして、空のUSBメモリにコピーします。
$ su - ... # dmesg ... [2324314.182218] usb 1-9: Product: Cruzer Blade [2324314.182221] usb 1-9: Manufacturer: SanDisk [2324314.182223] usb 1-9: SerialNumber: 2005224270143E40EC58 [2324314.183345] usb-storage 1-9:1.0: USB Mass Storage device detected [2324314.183662] scsi host6: usb-storage 1-9:1.0 [2324315.210537] scsi 6:0:0:0: Direct-Access SanDisk Cruzer Blade 1.26 PQ: 0 ANSI: 6 [2324315.211009] sd 6:0:0:0: Attached scsi generic sg2 type 0 [2324315.211993] sd 6:0:0:0: [sdc] 15633408 512-byte logical blocks: (8.00 GB/7.45 GiB) [2324315.213144] sd 6:0:0:0: [sdc] Write Protect is off [2324315.213148] sd 6:0:0:0: [sdc] Mode Sense: 43 00 00 00 [2324315.213398] sd 6:0:0:0: [sdc] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA [2324315.229150] sdc: sdc1 [2324315.230905] sd 6:0:0:0: [sdc] Attached SCSI removable disk ... # dd if=/home/user/debian-10.iso of=/dev/sdc 395313152 bytes (395 MB, 377 MiB) copied, 102.029 s, 3.9 MB/s
処理中に進捗状況を確認したくなったら、別ターミナルの管理者から「pkill -USR1 dd」とするとコピー処理中のターミナルに進捗状況が表示されます。
コピーが終わったら、USBメモリをインストールしたいマシンに挿入して、USBメモリから起動します。
筆者は土台となるマシンが非力なので、土台のOSはCUIにしますが、GUIにすればこの後の初期設定や管理が楽になります。
GUI版での操作方法はカゴヤ「Linux KVMの仕組みとは?」を参考にするといいと思います。KVMや関連する、QEMUについての関係性を理解したい場合にもおすすめです。
余談:使ったUSBメモリを元に戻す
Debianのインストール用にUSBメモリを作成した後で、通常のUSBメモリに戻す場合は作成されたパーテーションを削除してやる必要があります。その操作はfdiskで行います。
# fdisk /dev/sdc Command (m for help): p # パーテーション表示 Device Boot Start End Sectors Size Id Type /dev/sdc1 * 0 772095 772096 377M 0 Empty /dev/sdc2 4060 9243 5184 2.5M ef EFI (FAT-12/16/32) Command (m for help): d # パーテーション削除 Partition number (1,2, default 2): 2 Partition 2 has been deleted. Command (m for help): d Partition number (1,2, default 2): 1 Partition 1 has been deleted. Command (m for help): n # パーテーションを作成 Partition type p primary (0 primary, 0 extended, 4 free) e extended (container for logical partitions) Select (default p): p Partition number (1-4, default 1): 1 First sector (2048-15633407, default 2048): Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-15633407, default 15633407): Created a new partition 1 of type 'Linux' and of size 7.5 GiB. Command (m for help): p # 再度確認 Disk /dev/sdc: 7.5 GiB, 8004304896 bytes, 15633408 sectors Disk model: Cruzer Blade Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x5b39b025 Device Boot Start End Sectors Size Id Type /dev/sdc1 2048 15633407 15631360 7.5G 83 Linux Command (m for help): t #typeが LinuxになっているのでFAT32に変更 Selected partition 1 Hex code (type L to list all codes): 0c Changed type of partition 'W95 FAT32' to 'W95 FAT32 (LBA)'. Command (m for help): w # 反映、wを実行する前ならqで元に戻せます。 The partition table has been altered.
かえでのWebログ:「LinuxにおけるFAT32フォーマットの方法」によれば、8Gまでの場合は、0b(W95 FAT32)、それを超える場合は0c(W95 FAT32(LBA))を指定するそうです。
ここではパーテーションを作っただけで、フォーマットしていませんので再利用時にはフォーマットが必要です。
KVMインストールの事前準備
まず、カーネルモジュールである、vhost_netを利用してネットワークのオーバーヘッドを減らします。/etc/modulesに記述して置くことで、起動時に読み込まれます。
スペルミス等防止のため、再起動後「管理者権限で lsmod | vhost_net」を実行してみて、意図したようにカーネルモジュールが読み込まれている確認します。
手動で読み込む場合は「modprobe vhost_net」とします。
/etc/modules
... vhost_net ...
次に、ゲストOSがネットワークを使用する際に使うブリッジを作成します。
ブリッジに必要なツールであるbrige-utilsをインストールしたのち/etc/network/interfacesの記述を変更します。
# apt install bridge-utils
後述する設定では、br0というブリッジインターフェースを作って、既存のネットワークインターフェースに割り当てています。
addressやgateway等は通常のインターフェースと同じ値で設定します。brige_portsに設定したインターフェース名を記述します。
bridge_stpのoffはスパニングツリープロトコルをOFFにしています(複数ブリッジ間で冗長構成する際にループを防ぐために使います)。
auto br0でブリッジインターフェースがPC起動時にアクティブになるようにしています。
/etc/network/intefaces
iface br0 inet static address 172.16.1.247/24 gateway 172.16.1.254 dns-nameservers 8.8.8.8 bridge_ports enp2s0 bridge_stp off auto br0
auto br0の部分の補足説明をすると、これでシステムが「ifup -a」を実行する際にインターフェースが自動起動するようになります。
autoとallow-hotplugとの違いはインターフェースを起動するタイミングです。
autoは前述の通り、システムが「ifup -a」を実行した際に起動されますが、allow-hotplugではudev(デバイス管理ツール)がデバイス検知した際に起動する設定です。
「br0」はそれでは検知されないのでallow-hotplugでは自動起動しません。
もう少し踏み込んで説明すると、「man intefaces」によれば、この「allow-」の部分はOSや他のサブシステムから自動起動するものにつける識別子で、それに「hotplug」が続くとudevが装置を検知した際に起動するものとなります。この識別子全体を「allow-auto」とすると、autoと同じように処理されます。
KVMのインストール
KVM関連パッケージのインストールをします。
一緒にインストールするLibvirtは、仮想マシンの制御用のインターフェースを提供するライブラリでKVMやQEMUだけでなく、VirtualBoxやVMawareなどにも対応しています。
QEMUは装置のエミュレータです。KVMと連携することにより高速化を実現しています。
エミュレータと仮想化の違いについての詳細はリンク先を参考にしていただければと思いますが、ホストOSでの命令をゲストOSの命令に都度変換して装置に伝えるのがエミュレータ、ゲストOSの命令を直接装置に伝えるのが仮想化だそうです。単純に比較すれば仮想化の方が処理は早いのですが、ここでは両方使うことで高速化を実現しているという話です。
--no-install-recommendsオプションで、推奨されるGUIパッケージのインストールを防ぐことができます。オーバーヘッドを減らすためにCUIで管理する場合はこのオプションを付ける意味がありますが、GUIで管理する場合はこのオプションを外した方が以降の管理や設定がスムーズになると思います。
KVMのインストールが終わったら、ゲストOSインストールに必要なvirtinstと、インストールの前に利用可能なOSをリスト出力するlibosinfo-binもインストールします。
$ su - ... # apt update ... # apt install --no-install-recommends qemu-system libvirt-clients libvirt-daemon-system ... # apt install virtinst libosinfo-bin ...
インストール可能なOSの一覧はosinfo-query osとして確認できます。テーブル式に表示され「Short ID」、「Name」、「Version」、「ID」の順に表示されています。
... # osinfo-query os ... Short ID | Name | Ver | ID ... debian10 | Debian 10 | 10 | http://debian.org/debian/10 ... winxp | Microsoft Windows XP | 5.1 | http://microsoft.com/win/xp ...
この後OSを指定する際は、このShort IDを使います。
ゲストOSのインストール
先の対象リストに最新版であるDebian11が含まれていませんでしたので、安定性を考慮してDebian10(buster)をインストールします。後で試してみましたが、os-variantをdebian10にした状態で11(bullseye)をインストールすることもできるようでした。
先にCUI版でインストールしておき、あとからGUI版に変更します。
virt-install ¥ --virt-type kvm ¥ --name debian10 ¥ --location http://ftp.jp.debian.org/debian/dists/buster/main/installer-amd64/ ¥ --os-variant debian10 ¥ --disk path=/var/kvm/disks/debian10.img,size=10 ¥ --memory 1000 ¥ --graphics none ¥ --console pty,target_type=serial ¥ --extra-args "console=ttyS0"
書式がなんとなくわかりづらいですが、オプションに対しての値には=をつけずに、オプションの値に対してのサブ値には=をつけ、ひとつのオプションで複数値がある際は,で区切るようです。
筆者も経験しましたが、インストールが始まらない場合は起動パラメータの「"console=ttyS0"」を「"console=ttyS0,9600n8"」にしてみてください。
ここで使われているオプションの説明です。
- virt-type
ハイパバイザの種類を指定します。kvmを指定しています。
- name
識別のための名前を付けます。
- location
アーカイブミラーを指定することで、isoファイルをダウンロードせずに作業できます。
これにはローカルにダウンロードしたイメージファイルへのパスを指定することもできます。
- disk
pathにはデータ保存先、sizeにはディスク容量をG単位で指定します。
- memory
使用するメモリをM単位で指定します。
- graphics
ゲストにアクセスする際のデイスプレイの設定です。仮想ディスプレイを設定するものではありません。noneは無しです。
「spice,listen=0.0.0.0,password=password」とするとspiceの設定、spiceの部分をvncにするとvncになります。
spiceやVNCは遠隔操作の手法です。仮想化されたゲストOSをリモートで操作できるようになります。VNCは以前このブログでもUltraVNCやTigerVNCを紹介しています。後で設定方法を紹介します。
- video
ビデオドライバを指定します一般的な値は「vga」だと思いますが、spiceを利用する時「qxl」としてビデオドライバーにQLXを指定するとハイパフォーマンスが望めます。
- console
ゲストホスト間のテキストコンソールの設定です。
- os-variant
インストールするOSです。前述のようにosinfo-query osで出力されるOSでなければいけません。
- extra-args
インストール時に渡す拡張オプションを指定しています。「console=ttyS0」という文字列を渡したいので"で囲んでいます。
- network
ゲストのネットワーク環境の設定をします。ブリッジを指定するには「network bridge=br0」とします。
- cdrom
ローカルにあるディスクイメージを指定する場合は「cdrom /var/kvm/windows10.iso」等パスを指定します。イメージを指定する場合はlocationでも指定可能ですが、locationと違い、こちらを指定すると--extra-argsが利用できません。
インストールに失敗すると、そのままでは同じ名前で再度インストールができません。その際はlist --allで対象を確認して、undefine 名前 で削除予約します。これは、シャットダウン後に反映されます。
# virsh list --all Id 名前 状態 ----------------------------------- - buster-amd64 シャットオフ - debian10 シャットオフ - debian11 シャットオフ # virsh undefine buster-amd64 Domain 'buster-amd64' has been undefined
インストール後の基本操作
virsh list --allで表示される仮想OSは、startで開始、shutdownで停止、destoryで強制終了させることができます。
開始させたあとコンソールに入るには、consoleとします。
... # virsh list --all Id 名前 状態 ------------------------------- - debian10 シャットオフ ... # virsh start debian10 ... # virsh console debian10 ... Ctrl+]で仮想OSから抜けて元のコンソールになります。 ... # virsh shutdown debian10 ...
GUI化
locationを指定してDebian10をインストールしてみたところ日本語が指定できませんでした。また、アーカイブも地理的に離れていそうです。日本語が選択できないのは、最初はアーカイブが英語圏だからかと思ったのですが、日本圏のものにしても同じでした。(よく考えたらミラーなので当たり前なのですが)
そこで、インストールが終わったら、/etc/apt/sources.listを適切な値に編集して、apt updateをかけ、日本語化した後、GUI化します。ここではXfceデスクトップを採用しました。
日本語環境にする際、dpkg-reconfigureで指定するlocaleの候補はいくつかあると思いますが、標準的なものは「ja_JP.UTF-8」です。
# apt install task-japanese ... # dpkg-reconfigure locales ... # systemctl reboot ... # apt install apt install task-xface-desktop
タイムゾーンも修正しておきます。
spiceサーバ
他のGUI環境からゲストOSへのアクセス手段を設定します。
先のvirt-installで作成された設定ファイルを修正することになります。このファイルはXMLで書かれています。
「virsh edit 名前」で、そのファイルを編集可能です。viエディタ等を使って編集します。
保存後編集した値に論理的な間違いがあると、次のように警告してくれます。
yでやり直し、nで編集を破棄、iでそのままの状態で再登録を実行(修正されないのでたいてい同じエラーになります)、fで強制書き込み、?はヘルプを表示です。
GUI周りの設定をvirs-installで行っていなければ、<metadata>の下に次のような記述を追加します。
<graphics type='spice' port='5900' autoport='no' listen='0.0.0.0' passwd='password'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<video>
<model type='qxl' ram='65536' vram='32768' heads='1'/>
</video>
grephicsでは、リモート接続の環境について定義しています。タイプ(spiceやvnc)と、待ち受けポート、パスワードを設定、待ち受けるIPアドレスを設定します。パスワードは省略することもできます。待ち受けるIPアドレスは通常サーバーのアドレスと同じになると思いますが、0.0.0.0とするとワイルドカードになります。内側のlistenにおいても同じアドレスを設定しておく必要があります。
videoでは、文字通り画面の設定をします。modelのタイプ(vgaやqxl)と、vramにビデオメモリの容量を割り当てます。ramはqxl時のみ設定します。
通常videoの内側には<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>といった記述がありますが、省略すると自動的に補完してくれるようです。
このaddressでは仮想のハードウェアのIOドメイン、PCIバス、スロット、ファンクション番号等を設定しているようです。teratailにはこれらについてOracle: デバイスドライバの記述 を引用した、次のような投稿がありました。
Busのあとの数字は、バス番号を表しています。PCIの仕様では、一つのシステムに256までバスを持てるようになっています。 次のdeviceの続くの数値は、バスに接続されているデバイスの番号になります。一つのバスに32個まで接続可能です。最後のfunctionに続く数値は、 ファンクション番号になります。PCIデバイスは、一つのデバイス中に8つまでの機能を持たせることが可能です。複数のファンクション持つものとして、 モデムとネットワークカードが一つのなったデバイスや、ISA,IDE,USBなどをまとめて処理するブリッジなどが挙げられます。
クライアントはWindowsから接続してみます。VIRTUAL MACHINE MANAGERのページから、Vert-viewerのWindows版をダウンロードしてインストールします。
インストールしたRemote Viewer(virt-viewer)を立ち上げ、アドレスの欄に「spice://サーバーのアドレス:設定したポート」として実行します。
VNCサーバ
筆者にはspiceサーバよりVNCの方がなじみがあるのですが、こちらの設定にするには先の設定で「spice」という文字列の部分を「vnc」に置換するだけです。
クライアントはUltraVNC試してみましたが、問題なく接続できました。
spiceとVNCの違いですが、spiceはホスト管理のなのに対し、VNCはゲスト管理になるようです。(接続先のIPアドレスはどちらもホストのものを指定します)
また、VNCはパスワードの文字数の上限が8文字までとなります(8文字目以降は無視されます)。
Windows10のインストール
Windowsの場合も基本はLinuxと同じですが、Windows10ではインストールにGUI環境が必要なのでspiceまたはvncを設定してインストールする必要があります。
virt-install ¥ --name windows10 ¥ --os-variant=win10 ¥ --memory 2048 ¥ --disk path=/var/kvm/disks/win10.img,size=100 ¥ --network bridge=br0 ¥ --graphics vnc,listen=0.0.0.0,password=password,keymap=ja ¥ --video vga ¥ --cdrom /var/kvm/windows10.iso ... WARNING グラフィックスが要求されていますが DISPLAY 変数が設定されていません。virt-viewer を起動できません。 WARNING ゲストのコンソールがないため、デフォルト値 --wait -1 を適用します。 インストールの開始中... Domain is still running. Installation may be in progress. Waiting for the installation to complete.
上記のようなWARNINGが出ますが、無視してかまいません。
この後、GUI環境を持つ別のマシンからVert-viewer(Remote Viewer)やVNCクライアントからリモート接続すると(アドレスはKVMサーバのIP、ポートやパスワードはgraphicsオプションで指定したものになります)、Windowsのインストール画面になっていますので、そちらを使ってインストールを進めます。
環境のクローン
作成した環境を他のマシンへ持っていきたい場合の対応を
KVMの仮想イメージをバックアップ・リストアする方法を参考に、実施してみます。
まず、仮想化したの設定ファイルとディスクイメージを、移行先の環境へコピーします。
設定ファイルは前述にもありました「virsh dumpxml 名前」で読みだすことができますので、リダイレクトでファイル化します。
ディスクイメージは、設定ファイル中で指定したimgファイルをそのままコピーするだけです。
イメージの出力先を指定していない場合は、/var/lib/libvirt/images/ディレクトリにあるようです。この際、イメージファイルはQEMUの「Copy On Write Ver2」を示す、qcow2という拡張子になっていると思います。
コピーを終えたら、「virsh define 設定ファイル」コマンドを実行します。イメージファイルの場所やメモリ割り当ての設定等は必要に応じて、もとのXMLファイル上か、それを取り込んだ後virsh editで修正します。
# virsh dumpxml debian10 >debian10.xml ... # scp ./debian10.xml user@192.168.100.1:~/ ... # scp /var/kvm/disks/debian10.img user@192.168.100.1:~/ ...
コピーした先の環境で実行します。
# virsh define debian10.xml ...
Debian10の環境に移そうとしたところ次のようなエラーが出てました。マシンタイプがサポートされていないとのことです。仮に移動先のマシンで新規で仮想環境で作成してみるとxmlのmachine属性にはpc-q35-3.1の値が入っていました。移動させようとしたxmlの設定はpc-q35-5.2となっているので対応できないのだろうと、pc-q35-3.1としたところ、起動できました。
また、VNC用のパスワードのエントリーはxmldumpの際に削除されるようなので、パスワードの再設定も必要でした。
L1TF
後日気づいたのですが、とある環境で作成したKVMサーバーのdmesgに次のような警告が出ていました。
L1TFという仮想マシンに関連したハードウェアの脆弱性が存在するそうです。これはレベル1データキャッシュへの非特権アクセスを許してしまうということで、メモリ上に保存してあるデータを読まれてしまう危険なものです。
仮想化をしていなければ問題ありません。また仮想化している場合でもゲストOSが信頼できるソースで、カーネルがL1TF緩和策を講じていれば問題ないそうです。
Gihyo.jpによれば、Linuxはカーネル4.19-rc1からそれに対応しているということです。カーネルのバージョンは「uname -a」コマンドで確認することができますが、Debianの10(buster)の最終版は4.19.194でしたので問題なさそうです。
またカーネルが対応していなくてもBIOSかカーネルでSMTを使用できないようにすれば回避可能だということです。
ディスクイメージの拡張
ダンプしたデーターベースを取り込もうと思ったら、テスト稼働でディスクを小さく設定したため、保存できませんでした。
root@debianVM:~# df /dev/vda1 9232860 7220240 1522024 83%
仮想ディスクは/dev/vdaとして認識されているようです。これをKVMのゲストOSのディスク容量を増設・拡張する方法を参考に拡張します。
まず、仮想マシンをシャットダウンします。そのあと、qemu-img resizeコマンドでディスクを拡張します。
# virsh shutdown debian11 # qemu-img resize /var/kvm/disks/debian11.img +40G
このままだとディスクの空き容量が増えるだけで、パーテーションサイズは変更されないので、変更します。パーテーションの変更はGUIの方が楽なので、GUIのDebian環境を作ってそこから仮想ディスクを操作します。
新しく作成した仮想環境に(xml設定ファイルに)、vdbとして元のディスクを追加します。
<disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/kvm/disks/debian11.img'/> <target dev='vdb'/> </disk>
GUI Debianを立ち上げ、パーテーション変更ツールのGPartedをインストール、起動します。
その作業は、対象のディスクをvdbにし、まずvdb2をディスクの終わりまで拡張します。次にsdb5をディスクの終わりに移動させます。さらに、sdb2の始まりを後ろ側へ最小になるように寄せます。最後にsdb1を最大まで拡張させます。
なぜか隙間ができてしまいましたが、変更できました。
GUIをシャットダウンして、元の環境を立ち上げて確認してたところ、うまくいったようです。
root@debianVM:~# fdisk /dev/vda Command (m for help): p ... /dev/vda1 * 2048 102854655 102852608 49G 83 Linux /dev/vda2 102856704 104857599 2000896 977M 5 Extended /dev/vda5 102860800 104855551 1994752 974M 82 Linux swap / Solaris
vdb5はスワップ領域で、拡張パーテーションのvdb2はそれを覆っているだけなので、ディスクの拡張が想定されるケースではインストール時のパーテーションの仕切り方をマニュアルにして先頭にスワップ領域を持っていく方が管理は楽になると思います。仮想OSでLVMを使うという方法もありますが、オーバーヘッドが気になりますし、何だか冗長なような気もします。
その際のパーテーションの設定例は次のようになります。スワップ領域のサイズは「ガイドによるパーテーション」を一度実行してみてその値にすればいいと思いますが、詳しい話はAll about Linux swap spaceに載っています。
パーテーション1.スワップ 利用方法:スワップ領域 起動フラグ:オフ
パーテーション2.ルート 利用方法:ext4 マウントポイント:/ マウントオプション:default ラベル:なし 予約ブロック:5% 典型的な利用方法:標準 起動フラグ:オフ
ディスクイメージの縮小
先ほどのコマンドで、マイナスの値を指定して、--shrinkオプションを付与して実行すれば、ディスクイメージを縮小することもできます。ただし、ディスクの使用状況を考慮せずに切り捨てるだけなので、危険を伴います。
代替手段としてディスイメージのフォーマットがqcowかqcow2(デフォルト)なら、圧縮が可能です。仮想化されたマシンのディスクサイズはそのままでディスクイメージのサイズだけ減らすことができます。
その場合は、convertオプションで、次のようにします。-fは変換前のフォーマット、-Oは返還後のフォーマット、-cは圧縮を意味します。フォーマットは明示的に指定しないと圧縮できないようでした。
ディスクイメージの圧縮に関しては、CUBE SUGAR STORAGE:「QCOW2 形式で作った KVM のディスクイメージファイルを圧縮する」を参考にさせていただきました。
UUIDの重複
xmlをコピーして利用しようと思ったら、UUIDの重複エラーが出ました。
yuu_nkjm blog:「KVM仮想マシンの名前変更と移動」によると、xmlのuuidの部分を、uuidgenを使って生成した別の値にすればいいということでした。
virsh define debian-test.xml エラー: debian-test.xml からのドメイン定義に失敗しました エラー: 操作は失敗しました: ドメイン 'debian11' がすでに UUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx を用いて定義されています
uuid-runtimeをaptでインストールし、UUIDを生成して利用します。
ついでに標準状態で圧縮したディスクイメージとxmlを利用し、別の名前とuuidで再配置して、defineするシェルスクリプトを組んでみました。
make_vm.sh
#!/bin/bash
# 初期のディスクイメージ(ディスクは1つだけの前提です)
SOURCE_IMG=/home/user/debian11plain.img
# 初期ディスクイメージの設定ファイル
SOURCE_XML=/home/user/debian11plain.xml
# ディスクイメージの保存ディレクトリ
IMG_DIR=/var/kvm/disks
# 仮想マシンの名前
VIRT_NAME=debian11-new
# イメージのコピー
cp $SOURCE_IMG $IMG_DIR/$VIRT_NAME.img
# XMLのコピー
cp $SOURCE_XML $VIRT_NAME.xml
# XML中のuuid置換
sed "s/<uuid>.*<¥/uuid>/<uuid>`uuidgen`<¥/uuid>/g" $VIRT_NAME.xml>$VIRT_NAME.wk1
# XML中のname置換
sed "s/<name>.*<¥/name>/<name>$VIRT_NAME<¥/name>/g" $VIRT_NAME.wk1>$VIRT_NAME.wk2
# XML中のディスクイメージの場所を置換
# /がパスに含まれるため区切り文字を@にしています
sed s@$IMG_DIR/.*¥.img@$IMG_DIR/$VIRT_NAME.img@g $VIRT_NAME.wk2>$VIRT_NAME.xml
# sedワークファイル削除
rm $VIRT_NAME.wk*
# virshでdefine
virsh define $VIRT_NAME.xml
# xml ファイル削除
rm $VIRT_NAME.xml
参考にさせていただきましたサイトの皆様、ありがとうございました。