使用 KVM 執行巢狀訪客¶
巢狀訪客是指在一個訪客中執行另一個訪客(可以是基於 KVM 或不同的管理程式)。一個直接的例子是 KVM 訪客反過來在一個 KVM 訪客上執行(本文件的其餘部分都基於此示例)
.----------------. .----------------.
| | | |
| L2 | | L2 |
| (Nested Guest) | | (Nested Guest) |
| | | |
|----------------'--'----------------|
| |
| L1 (Guest Hypervisor) |
| KVM (/dev/kvm) |
| |
.------------------------------------------------------.
| L0 (Host Hypervisor) |
| KVM (/dev/kvm) |
|------------------------------------------------------|
| Hardware (with virtualization extensions) |
'------------------------------------------------------'
術語
L0 – 0 級;裸機主機,執行 KVM
L1 – 1 級訪客;在 L0 上執行的 VM;也稱為“訪客管理程式”,因為它本身能夠執行 KVM。
L2 – 2 級訪客;在 L1 上執行的 VM,這是“巢狀訪客”
注意
上述圖表是根據 x86 架構建模的;s390x、ppc64 和其他架構的巢狀設計可能不同。
例如,s390x 始終在裸機上執行 LPAR(邏輯分割槽)管理程式,這又增加了一個層,導致巢狀設定中至少有四個級別——L0(裸機,執行 LPAR 管理程式)、L1(主機管理程式)、L2(訪客管理程式)、L3(巢狀訪客)。
本文件將對所有架構沿用三級術語(L0、L1 和 L2);並將主要關注 x86。
用例¶
巢狀 KVM 在多種場景中都非常有用,舉例如下:
作為開發人員,您希望在不同的作業系統 (OS) 上測試您的軟體。使用巢狀 KVM 可以讓您租用足夠大的“訪客管理程式”(1 級訪客),而不是從雲提供商那裡租用多個 VM。這反過來又允許您建立多個執行不同作業系統的巢狀訪客(2 級訪客),您可以在這些訪客上開發和測試您的軟體。
“訪客管理程式”及其巢狀訪客的即時遷移,用於負載均衡、災難恢復等。
VM 映象建立工具(例如
virt-install等)通常執行自己的 VM,使用者希望這些工具能在 VM 內部工作。某些作業系統在內部使用虛擬化來實現安全性(例如,讓應用程式安全地隔離執行)。
啟用“巢狀” (x86)¶
從 Linux 核心 v4.20 起,Intel 和 AMD 的 nested KVM 引數預設啟用。(儘管您的 Linux 發行版可能會覆蓋此預設設定。)
如果您執行的是 v4.19 之前的 Linux 核心,要啟用巢狀,請將 nested KVM 模組引數設定為 Y 或 1。要使此設定在重啟後仍然有效,您可以將其新增到配置檔案中,如下所示:
在裸機主機 (L0) 上,列出核心模組並確保 KVM 模組
$ lsmod | grep -i kvm kvm_intel 133627 0 kvm 435079 1 kvm_intel
顯示
kvm_intel模組的資訊$ modinfo kvm_intel | grep -i nested parm: nested:bool
為了使巢狀 KVM 配置在重啟後仍然有效,請將以下內容放置在
/etc/modprobed/kvm_intel.conf中(如果檔案不存在則建立)$ cat /etc/modprobe.d/kvm_intel.conf options kvm-intel nested=y
解除安裝並重新載入 KVM Intel 模組
$ sudo rmmod kvm-intel $ sudo modprobe kvm-intel
驗證 KVM 的
nested引數是否已啟用$ cat /sys/module/kvm_intel/parameters/nested Y
對於 AMD 主機,過程與上述相同,只是模組名稱是 kvm-amd。
啟動巢狀訪客 (x86)¶
一旦您的裸機主機 (L0) 配置好巢狀功能,您應該能夠使用以下命令啟動 L1 訪客:
$ qemu-kvm -cpu host [...]
上述命令會將主機 CPU 的能力原樣傳遞給訪客,或者為了更好的即時遷移相容性,使用 QEMU 支援的命名 CPU 模型。例如:
$ qemu-kvm -cpu Haswell-noTSX-IBRS,vmx=on
然後,訪客管理程式將隨後能夠以加速 KVM 的方式執行巢狀訪客。
啟用“巢狀” (s390x)¶
在主機管理程式 (L0) 上,在 s390x 上啟用
nested引數$ rmmod kvm $ modprobe kvm nested=1
注意
在 s390x 上,核心引數 hpage 與 nested 引數互斥——即,要啟用 nested,hpage 引數必須停用。
訪客管理程式 (L1) 必須提供
sieCPU 功能——使用 QEMU,這可以透過使用“主機直通”(透過命令列-cpu host)來完成。現在 KVM 模組可以載入到 L1(訪客管理程式)中
$ modprobe kvm
使用巢狀 KVM 進行即時遷移¶
在 Linux 核心 5.3 和 QEMU 4.2.0 for Intel x86 系統中,以及更早版本的 s390x 系統中,將 L1 訪客(其中包含一個即時巢狀訪客)遷移到另一臺裸機主機是可行的。
在 AMD 系統上,一旦 L1 訪客啟動了 L2 訪客,L1 訪客在 L2 訪客關閉之前不應再進行遷移或儲存(請參閱 QEMU 文件中的“savevm”/“loadvm”)。嘗試在 L2 訪客執行時遷移或儲存-載入 L1 訪客將導致未定義行為。您可能會在 dmesg 中看到 kernel BUG! 條目、核心“oops”或直接的核心崩潰。此類已遷移或載入的 L1 訪客不再被視為穩定或安全,必須重新啟動。僅配置為支援巢狀但未實際執行 L2 訪客的 L1 訪客遷移,即使在 AMD 系統上也應正常執行,但一旦訪客啟動,可能會失敗。
遷移 L2 訪客始終有望成功,因此以下所有場景即使在 AMD 系統上也應該有效:
將巢狀訪客 (L2) 遷移到同一裸機主機上的另一個 L1 訪客。
將巢狀訪客 (L2) 遷移到不同裸機主機上的另一個 L1 訪客。
將巢狀訪客 (L2) 遷移到裸機主機。
報告巢狀設定中的錯誤¶
除錯“巢狀”問題可能涉及篩選 L0、L1 和 L2 中的日誌檔案;這可能導致錯誤報告者和錯誤修復者之間繁瑣的來回溝通。
說明您處於“巢狀”設定中。如果您正在執行任何型別的“巢狀”,請務必提及。不幸的是,這一點需要強調,因為在報告錯誤時,人們往往會忘記甚至提及他們正在使用巢狀虛擬化。
確保您實際正在 KVM 上執行 KVM。有時人們沒有為他們的訪客管理程式 (L1) 啟用 KVM,這導致他們使用純模擬或 QEMU 稱之為“TCG”的方式執行,但他們認為他們正在執行巢狀 KVM。因此,這混淆了“巢狀虛擬化”(也可能意味著 KVM 上的 QEMU)和“巢狀 KVM”(KVM 上的 KVM)。
要收集的資訊(通用)¶
以下不是詳盡的列表,但是一個很好的起點
L0 中的核心、libvirt 和 QEMU 版本
L1 中的核心、libvirt 和 QEMU 版本
L1 的 QEMU 命令列 -- 使用 libvirt 時,您會在此處找到它:
/var/log/libvirt/qemu/instance.logL2 的 QEMU 命令列 -- 如上所述,使用 libvirt 時,獲取完整的 libvirt 生成的 QEMU 命令列
L0 中的
cat /sys/cpuinfoL1 中的
cat /sys/cpuinfoL0 中的
lscpuL1 中的
lscpuL0 中的完整
dmesg輸出L1 中的完整
dmesg輸出
x86 特定資訊收集¶
以下兩個命令 x86info 和 dmidecode 在大多數 Linux 發行版中都應該以相同的名稱可用
L0 中
x86info -a的輸出L1 中
x86info -a的輸出L0 中
dmidecode的輸出L1 中
dmidecode的輸出
s390x 特定資訊收集¶
除了前面提到的通用詳情,還建議收集以下資訊
L1 中的
/proc/sysinfo;這還將包括 L0 中的資訊