KVM,QEMU,libvirt入門學習筆記【轉】


轉自:http://blog.csdn.net/julykobe/article/details/27571387

注:本文內容均來自網絡,我只是在此做了一些摘抄和整理的工作,來源均有注明。

0、虛擬化

虛擬化簡介

我們首先簡要介紹一下虛擬化,闡述 QEMU 的搭建背景。

本文中介紹的虛擬化實際上指的是平台虛擬化。在物理硬件上,控制程序可能是主機操作系統或管理程序(見圖 1)。在某些情況下,主機操作系統就是管理程序。來賓操作系統位於管理程序中。在某些情況下,來賓操作系統與控制程序使用相同的 CPU,而在另外一些情況下,則可能不同(比如 PowerPC 來賓操作系統在 x86 硬件上運行)。

圖 1. 平台虛擬化的基本架構
圖 1. 平台虛擬化的基本架構

您可以通過多種方法實現虛擬化,但是最常見的有三種。第一種稱為本地虛擬化(或全虛擬化)。在這種虛擬化中,管理程序實現基本的隔離元素,將物理硬件與來賓操作系統相分離。這種技術首次出現於 1966 年 IBM® CP-40 虛擬機/虛擬內存操作系統中,另外 VMware ESX Server 也使用了此技術。

另一種流行的虛擬化技術稱為半虛擬化。在半虛擬化中,控制程序實現了管理程序的應用程序接口(API),它將由來賓操作系統使用。Xen 和 Linux Kernel-based Virtual Machine (KVM) 都使用了半虛擬化技術。

第三種有用的技術稱為仿真。仿真,顧名思義,通過模擬完整的硬件環境來虛擬化來賓平台。仿真可通過多種方法實現,即使在同一個解決方案中也是如此。通過仿真實現虛擬化的技術有 QEMU 和 Bochs。


 

1、KVM

概念:

     KVM是Kernel-based Virtual Machine的縮寫。從Linux kernel 2.6.20開始就包含在Linux內核代碼之中,使用這個或者更高版本內核的Linux發行版,就直接可以使用KVM。KVM依賴於host CPU的虛擬化功能的支持(Intel-VT & AMD-V),類似於Xen的HVM,對於guest OS的內核沒有任何的要求,可以直接支持創建Linux和Windows的虛擬機。

     下圖解釋了KVM的運行原理:

     KVM支持用戶態(Userspace)進程通過KVM內核(Kernel)模塊利用CPU的虛擬化技術創建虛擬機。 虛擬機的vCPU映射到進程中的線程,虛擬機的RAM映射到進程的內存地址空間,IO和外圍設備通過進程進行虛擬化,也就是通過QEMU。所以我們看到在OpenStack中創建一個虛擬機就對應一個計算節點的QEMU進程。
 
     剛才說到guest OS RAM的地址空間映射到qemu-kvm進程的內存地址空間,這樣進程就可以很容易的對於guest OS的RAM進行控制,當guest需要使用RAM時,qemu-kvm就在自己的進程內存空間中划分一段給guest用。對於guest OS設置了MaxMemory和CurrentMemory之后,guest OS的RAM上限也就有了,就是MaxMemory,如果當前的guest實際使用不了那么多RAM,就可以將CurrentMemory調小,將多余的內存還給host,guest中看到的內存大小就是CurrentMemory,這就是Memory Balloon特性。
 
架構:
     KVM由兩部分組成,一部分稱為KVM Driver。已經成為Linux內核的一個模塊,負責虛擬機的創建、虛擬機內存的分配、虛擬CPU寄存器的讀寫以及虛擬CPU的運行等;另一部分是稍微修過的Qemu,用於模擬PC硬件的用戶空間組件、提供I/O設備模型以及訪問外設的途徑。
     
      圖1揭示了KVM的基本結構(Libkvm是KvM提供給Qemu的應用程序接口)。KVM Driver加入到標准的Linux內核中,被組織成Linux中的標准字符設備(/dev/kvm),用戶模式的Qemu可以通過一系列的ioctl系統調用訪問這個字符設備從而創建和運行虛擬機。KVMDriver的加入使得整個Linux內核成為一個虛擬機監控器(Virtual Machine Monitor),並且在原有Linux操作系統兩種執行模式(用戶模式和內核模式)的基礎上,增加了一種客戶模式(擁有自己的內核模式和用戶模式),這三種模式不同的分工分別是:
客戶模式:執行非I/0的客戶代碼。虛擬機就運行在客戶模式下。
內核模式:實現到客戶模式的切換,處理由於I/O或其他指令引起的從客戶模式的退出。KVM Driver工作在這種模式下。
用戶模式:代表客戶執行I/0指令。Qemu運行在這種模式下。
我們把運行於虛擬機內的操作系統稱為Guest OS,把底層的Linux操作系統稱為Host OS。在KVM模型中,每一個Guest OS對Linux來說是一個標准的進程,可以使用Linux的進程管理指令管理,例如用taskset指定運行於某個特定的CPU,也可以用kill終止虛擬機的運行。
 
    
 
     從圖2中我們可以清楚的看到KVM的基本工作原理。首先在用戶模式的Qemu通過ioctl系統調用,進入內核模式。KVM Driver為虛擬機創建虛擬內存和虛擬CPU之后執行VMI.AUNCH指令進入客戶模式,裝載GuestOS,而后執行客戶代碼。如果Guest OS發生外部中斷或者影子頁表缺頁之類的事件,暫停Guest OS的運行,退出客戶模式進入內核做一些必要的處理,而后重新進入客戶模式。繼續執行客戶代碼;如果發生I/0事件或者信號隊列中有信號到達,就會進入用戶模式處理。
     KVM采用全虛擬化技術(可以通過給當前內核打kvm-paravirt-patches補丁來支持半虛擬化),Guest OS不需要修改就可以直接在在其上運行,彌補了半虛擬化技術的不足。
 

 

2、QEMU

概念:
     剛才講KVM的時候一直說進程可以通過KVM模塊創建虛擬機,那個所謂的進程其實就是QEMU。KVM團隊維護了一個QEMU的分支版本(qemu-kvm),使QEMU可以利用KVM在x86架構上加速,提供更好的性能。qeum-kvm版本的目標是將所有的特性都合入上游的QEMU版本,之后這個版本會廢棄,直接使用QEMU主干版本。
     其實,之前還有Xen維護的QEMU版本,叫做qemu-xen,由於所有的特性都已經合入QEMU1.0,所以Xen現在直接使用了QEMU。
     #"之前在安裝OpenStack的時候,都需要安裝一個包kvm,我個人認為這個包其實就是QEMU,KVM是已經包含在Linux Kernel里了,所以不需要再安裝。包名稱使用kvm有點混淆概念。這點在Ubuntu的包描述上可以看出來。"
     在Nova的配置文件中有一個virt_type配置項,可以配置成kvm也可以是qemu,這里的kvm其實指的也是qemu-kvm。如果要配置成kvm,需要host的CPU支持Intel-VT和AMD-V技術,並且要載入kvm內核模塊,由於有硬件加速,創建的guest OS的性能要優於qemu;qemu配置項指的就是完全的QEMU虛擬化,沒有硬件加速,主要用於比較老式的CPU和操作系統環境,或者是在虛擬機中創建虛擬機的情況,當然完全的QEMU虛擬化性能要比qemu-kvm差一些
     QEMU的功能大致分為兩類:
  • 模擬(emulator)
  • 虛擬化(virtualizer)

      模擬:就是在一種CPU架構上模擬另一種CPU架構,運行程序。例如:在x86環境上模擬ARM的運行環境,執行ARM程序,或者在PowerPC環境上模擬x86指令集。
     虛擬化:就是在host OS上運行guest OS的指令,並為guest OS提供虛擬的CPU、RAM、IO和外圍設備。

     我們在OpenStack中使用的就是QEMU的虛擬化功能。
     QEMU進程直接使用了KVM的接口/dev/kvm,向KVM發送創建虛擬機和運行虛擬機的命令。框架代碼如下:
open("/dev/kvm")
ioctl(KVM_CREATE_VM)
ioctl(KVM_CREATE_VCPU)
for (;;) {
ioctl(KVM_RUN)
switch (exit_reason) {
case KVM_EXIT_IO:  /* ... */
case KVM_EXIT_HLT: /* ... */
}
}
     虛擬機運行起來之后,當guest OS發出硬件中斷或者其它的特殊操作時,KVM退出,QEMU可以繼續執行,這時QEMU根據KVM的退出類型進行模擬IO操作響應guest OS。
     由於QEMU是一個普通的用戶態進程,而guest OS的運行又在QEMU當中,所以host不能繞過QEMU直接觀察guest OS。但是QEMU提供了一系列的接口可以導出guest OS的運行情況,內存狀態和IO狀態等。
     以下就是一個QEMU進程:
109       1673     1  1 May04 ?        00:26:24 /usr/bin/qemu-system-x86_64 -name instance-00000002 -S -machine pc-i440fx-trusty,accel=tcg,usb=off -m 2048 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid f3fdf038-ffad-4d66-a1a9-4cd2b83021c8 -smbios type=1,manufacturer=OpenStack Foundation,product=OpenStack Nova,version=2014.2,serial=564d2353-c165-6238-8f82-bfdb977e31fe,uuid=f3fdf038-ffad-4d66-a1a9-4cd2b83021c8 -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/instance-00000002.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -boot strict=on -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/opt/stack/data/nova/instances/f3fdf038-ffad-4d66-a1a9-4cd2b83021c8/disk,if=none,id=drive-virtio-disk0,format=qcow2,cache=none -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -drive file=/opt/stack/data/nova/instances/f3fdf038-ffad-4d66-a1a9-4cd2b83021c8/disk.config,if=none,id=drive-ide0-1-1,readonly=on,format=raw,cache=none -device ide-cd,bus=ide.1,unit=1,drive=drive-ide0-1-1,id=ide0-1-1 -netdev tap,fd=26,id=hostnet0 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=fa:16:3e:db:86:d4,bus=pci.0,addr=0x3 -chardev file,id=charserial0,path=/opt/stack/data/nova/instances/f3fdf038-ffad-4d66-a1a9-4cd2b83021c8/console.log -device isa-serial,chardev=charserial0,id=serial0 -chardev pty,id=charserial1 -device isa-serial,chardev=charserial1,id=serial1 -vnc 127.0.0.1:1 -k en-us -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
 
架構:
 

     QEMU 支持兩種操作模式:用戶模式仿真和系統模式仿真用戶模式仿真 允許一個 CPU 構建的進程在另一個 CPU 上執行(執行主機 CPU 指令的動態翻譯並相應地轉換 Linux 系統調用)。系統模式仿真 允許對整個系統進行仿真,包括處理器和配套的外圍設備。

     在 x86 主機系統上仿真 x86 代碼時,使用 QEMU 加速器 可以實現近似本地的性能。這讓我們能夠直接在主機 CPU 上執行仿真代碼(在 Linux 上通過 kernel 模塊執行)。

     但是從技術角度看,QEMU 的有趣之處在於其快速、可移植的動態翻譯程序動態翻譯程序 允許在運行時將用於目標(來賓)CPU 的指令轉換為用於主機 CPU,從而實現仿真。這可以通過一種強制方法實現(將指令從一個 CPU 映射到另一個 CPU),但是情況並非總是這樣簡單,在某些情況下,根據所翻譯的架構,可能需要使用多個指令或行為更改。

     QEMU 實現動態翻譯的方法是,首先將目標指令轉換為微操作。這些微操作是一些編譯成對象的 C 代碼。然后構建核心翻譯程序。它將目標指令映射到微操作以進行動態翻譯。這不僅可產生高效率,而且還可以移植。

     QEMU 的動態翻譯程序還緩存了翻譯后的代碼塊,使翻譯程序的內存開銷最小化。當初次使用目標代碼塊時,翻譯該塊並將其存儲為翻譯后的代碼塊。 QEMU 將最近使用的翻譯后的代碼塊緩存在一個 16 MB 的塊中。 QEMU 甚至可以通過在緩存中將翻譯后的代碼塊變為無效來支持代碼的自我修改。

 

3、libvirt

Libvirt 庫是一種實現 Linux 虛擬化功能的 Linux® API,它支持各種虛擬機監控程序。
 
libvirt是一個統一的虛擬化管理接口,當前支持的虛擬化實現如下:
  • The KVM/QEMU Linux hypervisor
  • The Xen hypervisor on Linux and Solaris hosts.
  • The LXC Linux container system
  • The OpenVZ Linux container system
  • The User Mode Linux paravirtualized kernel
  • The VirtualBox hypervisor
  • The VMware ESX and GSX hypervisors
  • The VMware Workstation and Player hypervisors
  • The Microsoft Hyper-V hypervisor
  • The IBM PowerVM hypervisor
  • The Parallels hypervisor
  • The Bhyve hypervisor
第一個就是QEMU,libvirt的virsh是可以傳遞QEMU的監控命令的,我希望實現的那個blueprint就是用libvirt去傳遞QEMU的監控命令,開啟QEMU的內存使用統計,然后再通過libvirt獲取虛擬機的內存使用情況。[by 參考1原文作者]
架構:
      libvirt 比較和用例模型
libvirt 比較和用例模型
     圖中還顯示了 libvirt 所用術語對照。這些術語很重要,因為在對 API 命名時會用到它們。兩個根本區別在於,libvirt 將物理主機稱作節點,將來賓操作系統稱作域。這里需要注意的是,libvirt(及其應用程序)在宿主 Linux 操作系統(域 0)中運行。
 
控制方式:
     使用 libvirt,我們有兩種不同的控制方式。第一種如 圖 1 所示,其中管理應用程序和域位於同一節點上。 在本例中,管理應用程序通過 libvirt 工作,以控制本地域。當管理應用程序和域位於不同節點上時,便產生了另一種控制方式。在本例中需要進行遠程通信(參見 圖 2)。該模式使用一種運行於遠程節點上、名為 libvirtd 的特殊守護進程。當在新節點上安裝 libvirt 時該程序會自動啟動,且可自動確定本地虛擬機監控程序並為其安裝驅動程序(稍后討論)。該管理應用程序通過一種通用協議從本地 libvirt 連接到遠程 libvirtd。對於 QEMU,協議在 QEMU 監視器處結束。QEMU 包含一個監測控制台,它允許檢查運行中的來賓操作系統並控制虛擬機(VM)各部分。
     
使用 libvirtd 控制遠程虛擬機監控程序
圖 使用 libvirtd 控制遠程虛擬機監控程序
 
虛擬機監控程序支持:
 
     為支持各種虛擬機監控程序的可擴展性,libvirt 實施一種基於驅動程序的架構,該架構允許一種通用的 API 以通用方式為大量潛在的虛擬機監控程序提供服務。這意味着,一些虛擬機監控程序的某些專業功能在 API 中不可見。另外,有些虛擬機監控程序可能不能實施所有 API 功能,因而在特定驅動程序內被定義為不受支持。圖 3 展示了 libvirt API 與相關驅動程序的層次結構。這里也需要注意,libvirtd 提供從遠程應用程序訪問本地域的方式。
 
表 1. libvirt 支持的虛擬機監控程序
虛擬機監控程序 描述
Xen 面向 IA-32,IA-64 和 PowerPC 970 架構的虛擬機監控程序
QEMU 面向各種架構的平台仿真器
Kernel-based Virtual Machine (KVM) Linux 平台仿真器
Linux Containers(LXC) 用於操作系統虛擬化的 Linux(輕量級)容器
OpenVZ 基於 Linux 內核的操作系統級虛擬化
VirtualBox x86 虛擬化虛擬機監控程序
User Mode Linux 面向各種架構的 Linux 平台仿真器
Test 面向偽虛擬機監控程序的測試驅動器
Storage 存儲池驅動器(本地磁盤,網絡磁盤,iSCSI 卷)
 
 

參考:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM