KVM學習-3

KVM 介紹(3):I/O 全虛擬化和準虛擬化

[KVM I/O QEMU Full-Virtualizaiton Para-virtualization]

在 QEMU/KVM 中,客戶機可使用的設備大體可分爲三類:
1. 模擬設備:徹底由 QEMU 純軟件模擬的設備。
2. Virtio 設備:實現 VIRTIO API 的半虛擬化設備。
3. PCI 設備直接分配 (PCI device assignment)。

1. 全虛擬化 I/O 設備

KVM 在 IO 虛擬化方面,傳統或者默認的方式是使用 QEMU 純軟件的方式來模擬 I/O 設備,包括鍵盤、鼠標、顯示器,硬盤 和 網卡 等。模擬設備可能會使用物理的設備,或者使用純軟件來模擬。模擬設備只存在於軟件中。 

1.1 原理

過程:
  1. 客戶機的設備驅動程序發起 I/O 請求操做請求
  2. KVM 模塊中的 I/O 操做捕獲代碼攔截此次 I/O 請求
  3. 通過處理後將本次 I/O 請求的信息放到 I/O 共享頁 (sharing page),並通知用戶空間的 QEMU 程序。
  4. QEMU 程序得到 I/O 操做的具體信息以後,交由硬件模擬代碼來模擬出本次 I/O 操做。
  5. 完成以後,QEMU 將結果放回 I/O 共享頁,並通知 KMV 模塊中的 I/O 操做捕獲代碼。
  6. KVM 模塊的捕獲代碼讀取 I/O 共享頁中的操做結果,並把結果放回客戶機。 

注意:當客戶機經過DMA (Direct Memory Access)訪問大塊I/O時,QEMU 模擬程序將不會把結果放進共享頁中,而是經過內存映射的方式將結果直接寫到客戶機的內存中共,而後通知KVM模塊告訴客戶機DMA操做已經完成。前端

 
這種方式的優勢是能夠模擬出各類各樣的硬件設備;其缺點是每次 I/O 操做的路徑比較長,須要屢次上下文切換,也須要屢次數據複製,因此性能較差。 

1.2 QEMU 模擬網卡的實現

Qemu 純軟件的方式來模擬I/O設備,其中包括常用的網卡設備。Guest OS啓動命令中沒有傳入的網絡配置時,QEMU默認分配 rtl8139 類型的虛擬網卡類型,使用的是默認用戶配置模式,這時候因爲沒有具體的網絡模式的配置,Guest的網絡功能是有限的。 全虛擬化狀況下,KVM虛機能夠選擇的網絡模式包括:linux

  1. 默認用戶模式(User);
  2. 基於網橋(Bridge)的模式;
  3. 基於NAT(Network Address Translation)的模式;

分別使用的 qemu-kvm 參數爲:web

  • -net user[,vlan=n]:使用用戶模式網絡堆棧,這樣就不須要管理員權限來運行.若是沒有指 定-net選項,這將是默認的狀況.-net tap[,vlan=n][,fd=h]
  • -net nic[,vlan=n][,macaddr=addr]:建立一個新的網卡並與VLAN n(在默認的狀況下n=0)進行鏈接。做爲可選項的項目,MAC地址能夠進行改變.若是 沒有指定-net選項,則會建立一個單一的NIC.
  • -net tap[,vlan=n][,fd=h][,ifname=name][,script=file]:將TAP網絡接口 name 與 VLAN n 進行鏈接,並使用網絡配置腳本文件進行 配置。默認的網絡配置腳本爲/etc/qemu-ifup。若是沒有指定name,OS 將會自動指定一個。fd=h能夠用來指定一個已經打開的TAP主機接口的句柄。

網橋模式是目前比較簡單,也是用的比較多的模式,下圖是網橋模式下的 VM的收發包的流程。編程

如圖中所示,紅色箭頭表示數據報文的入方向,步驟:後端

  1. 網絡數據從 Host 上的物理網卡接收,到達網橋;
  2. 因爲 eth0 與 tap1 均加入網橋中,根據二層轉發原則,br0 將數據從 tap1 口轉發出去,即數據由 Tap設備接收;
  3. Tap 設備通知對應的 fd 數據可讀;
  4. fd 的讀動做經過 tap 設備的字符設備驅動將數據拷貝到用戶空間,完成數據報文的前端接收。

(引用自 http://luoye.me/2014/07/17/netdev-virtual-1/centos

1.3 RedHat Linux 6 中提供的模擬設備

  • 模擬顯卡:提供2塊模擬顯卡。
  • 系統組件:
    • ntel i440FX host PCI bridge
    • PIIX3 PCI to ISA bridge
    • PS/2 mouse and keyboard
    • EvTouch USB Graphics Tablet
    • PCI UHCI USB controller and a virtualized USB hub
    • Emulated serial ports
    • EHCI controller, virtualized USB storage and a USB mouse
  • 模擬的聲卡:intel-hda
  • 模擬網卡:e1000,模擬 Intel E1000 網卡;rtl8139,模擬 RealTeck 8139 網卡。
  • 模擬存儲卡:兩塊模擬 PCI IDE 接口卡。KVM  限制每一個虛擬機最多隻能有4塊虛擬存儲卡。還有模擬軟驅。

注意:RedHat Linux KVM 不支持 SCSI 模擬。服務器

在不顯式指定使用其它類型設備的狀況下,KVM 虛機將使用這些默認的虛擬設備。好比上面描述的默認狀況下 KVM 虛機默認使用rtl8139網卡。好比,在 RedHat Linux 6.5 主機上啓動KVM RedHat Linux 6.4 虛機後,登陸虛機,查看 pci 設備,能夠看到這些模擬設備:
當使用 「-net nic,model=e1000」 指定網卡model 爲 e1000 時,

1.4 qemu-kvm 關於磁盤設備和網絡的主要選項

類型 選項
磁盤設備(軟盤、硬盤、CDROM等)
-drive option[,option[,option[,...]]]:定義一個硬盤設備;可用子選項有不少。
    file=/path/to/somefile:硬件映像文件路徑;
    if=interface:指定硬盤設備所鏈接的接口類型,即控制器類型,如ide、scsi、sd、mtd、floppy、pflash及virtio等;
    index=index:設定同一種控制器類型中不一樣設備的索引號,即標識號;
    media=media:定義介質類型爲硬盤(disk)仍是光盤(cdrom);  format=format:指定映像文件的格式,具體格式可參見qemu-img命令;
-boot [order=drives][,once=drives][,menu=on|off]:定義啓動設備的引導次序,每種設備使用一個字符表示;
不一樣的架構所支持的設備及其表示字符不盡相同,在x86 PC架構上,a、b表示軟驅、c表示第一塊硬盤,d表示第一個光驅設備,n-p表示網絡適配器;
默認爲硬盤設備(-boot order=dc,once=d)
網絡
-net nic[,vlan=n][,macaddr=mac][,model=type][,name=name][,addr=addr][,vectors=v]:建立一個新的網卡設備並鏈接至vlan n中;
PC架構上默認的NIC爲e1000,macaddr用於爲其指定MAC地址,name用於指定一個在監控時顯示的網上設備名稱;emu能夠模擬多個類型的網卡設備;
可使用「qemu-kvm -net nic,model=?」來獲取當前平臺支持的類型;
-net tap[,vlan=n][,name=name][,fd=h][,ifname=name][,script=file][,downscript=dfile]:
經過物理機的TAP網絡接口鏈接至vlan n中,使用script=file指定的腳本(默認爲/etc/qemu-ifup)來配置當前網絡接口,
並使用downscript=file指定的腳本(默認爲/etc/qemu-ifdown)來撤消接口配置;使用script=no和downscript=no可分別用來禁止執行腳本;
-net user[,option][,option][,...]:在用戶模式配置網絡棧,其不依賴於管理權限;有效選項有:
    vlan=n:鏈接至vlan n,默認n=0;
    name=name:指定接口的顯示名稱,經常使用於監控模式中;
    net=addr[/mask]:設定GuestOS可見的IP網絡,掩碼可選,默認爲10.0.2.0/8;
    host=addr:指定GuestOS中看到的物理機的IP地址,默認爲指定網絡中的第二個,即x.x.x.2;
    dhcpstart=addr:指定DHCP服務地址池中16個地址的起始IP,默認爲第16個至第31個,即x.x.x.16-x.x.x.31;
    dns=addr:指定GuestOS可見的dns服務器地址;默認爲GuestOS網絡中的第三個地址,即x.x.x.3;
    tftp=dir:激活內置的tftp服務器,並使用指定的dir做爲tftp服務器的默認根目錄;
    bootfile=file:BOOTP文件名稱,用於實現網絡引導GuestOS;
        如:qemu -hda linux.img -boot n -net user,tftp=/tftpserver/pub,bootfile=/pxelinux.0
 
 對於網卡來講,你可使用 modle 參數指定虛擬網絡的類型。 RedHat Linux 6 所支持的虛擬網絡類型有:
[root@rh65 isoimages]# kvm -net nic,model=? qemu: Supported NIC models: 
ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio 

2. 準虛擬化 (Para-virtualizaiton) I/O 驅動 virtio

在 KVM 中可使用準虛擬化驅動來提供客戶機的I/O 性能。目前 KVM 採用的的是 virtio 這個 Linux 上的設備驅動標準框架,它提供了一種 Host 與 Guest 交互的 IO 框架。

2.1 virtio 的架構

 KVM/QEMU 的 virtio 實現採用在 Guest OS 內核中安裝前端驅動 (Front-end driver)和在 QEMU 中實現後端驅動(Back-end)的方式。先後端驅動經過 vring 直接通訊,這就繞過了通過 KVM 內核模塊的過程,達到提升 I/O 性能的目的。
純軟件模擬的設備和 Virtio 設備的區別:virtio 省去了純模擬模式下的異常捕獲環節,Guest OS 能夠和 QEMU 的 I/O 模塊直接通訊。
使用 Virtio 的完整虛機 I/O流程:
Host 數據發到 Guest:
1. KVM 經過中斷的方式通知 QEMU 去獲取數據,放到 virtio queue 中
2. KVM 再通知 Guest 去 virtio queue 中取數據。

2.2 Virtio 在 Linux 中的實現

 Virtio 是在半虛擬化管理程序中的一組通用模擬設備的抽象。這種設計容許管理程序經過一個應用編程接口 (API)對外提供一組通用模擬設備。經過使用半虛擬化管理程序,客戶機實現一套通用的接口,來配合後面的一套後端設備模擬。後端驅動沒必要是通用的,只要它們實現了前端所需的行爲。所以,Virtio 是一個在 Hypervisor 之上的抽象API接口,讓客戶機知道本身運行在虛擬化環境中,進而根據 virtio 標準與 Hypervisor 協做,從而客戶機達到更好的性能。
  • 前端驅動:客戶機中安裝的驅動程序模塊
  • 後端驅動:在 QEMU 中實現,調用主機上的物理設備,或者徹底由軟件實現。
  • virtio 層:虛擬隊列接口,從概念上鍊接前端驅動和後端驅動。驅動能夠根據須要使用不一樣數目的隊列。好比 virtio-net 使用兩個隊列,virtio-block只使用一個隊列。該隊列是虛擬的,其實是使用 virtio-ring 來實現的。
  • virtio-ring:實現虛擬隊列的環形緩衝區
Linux 內核中實現的五個前端驅動程序:
  • 塊設備(如磁盤)
  • 網絡設備
  • PCI 設備
  • 氣球驅動程序(動態管理客戶機內存使用狀況)
  • 控制檯驅動程序
Guest OS 中,在不使用 virtio 設備的時候,這些驅動不會被加載。只有在使用某個 virtio 設備的時候,對應的驅動纔會被加載。每一個前端驅動器具備在管理程序中的相應的後端的驅動程序。
 
以 virtio-net 爲例,解釋其原理:

(1)virtio-net 的原理:網絡

它使得:
  1. 多個虛機共享主機網卡 eth0
  2. QEMU 使用標準的 tun/tap 將虛機的網絡橋接到主機網卡上
  3. 每一個虛機看起來有一個直接鏈接到主機PCI總線上的私有 virtio 網絡設備
  4. 須要在虛機裏面安裝 virtio驅動
 
(2)virtio-net 的流程
總結 Virtio 的優缺點:
  • 優勢:更高的IO性能,幾乎能夠和原生系統差很少。
  • 缺點:客戶機必須安裝特定的 virtio 驅動。一些老的 Linux 尚未驅動支持,一些 Windows 須要安裝特定的驅動。不過,較新的和主流的OS都有驅動能夠下載了。Linux 2.6.24+ 都默認支持 virtio。可使用 lsmod | grep virtio 查看是否已經加載。 

2.3 使用 virtio 設備 (以 virtio-net 爲例)

使用 virtio 類型的設備比較簡單。較新的 Linux 版本上都已經安裝好了 virtio 驅動,而 Windows 的驅動須要本身下載安裝。
 
(1)檢查主機上是否支持 virtio 類型的網卡設備
[root@rh65 isoimages]# kvm -net nic,model=? qemu: Supported NIC models: 
ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio
 
(2)指定網卡設備model 爲 virtio,啓動虛機
(3)經過 vncviewer 登陸虛機,能看到被加載了的 virtio-net 須要的內核模塊
 
(4)查看 pci 設備
其它 virtio 類型的設備的使用方式相似 virtio-net。

2.4 vhost-net (kernel-level virtio server)

  前面提到 virtio 在宿主機中的後端處理程序(backend)通常是由用戶空間的QEMU提供的,然而若是對於網絡 I/O 請求的後端處理可以在在內核空間來完成,則效率會更高,會提升網絡吞吐量和減小網絡延遲。在比較新的內核中有一個叫作 「vhost-net」 的驅動模塊,它是做爲一個內核級別的後端處理程序,將virtio-net的後端處理任務放到內核空間中執行,減小內核空間到用戶空間的切換,從而提升效率。
 
根據 KVM 官網的 這篇文章,vhost-net 能提供更低的延遲(latency)(比 e1000 虛擬網卡低 10%),和更高的吞吐量(throughput)(8倍於普通 virtio,大概  7~8 Gigabits/sec )。
 
vhost-net 與 virtio-net 的比較:

vhost-net 的要求:架構

  • qemu-kvm-0.13.0 或者以上
  • 主機內核中設置 CONFIG_VHOST_NET=y 和在虛機操做系統內核中設置 CONFIG_PCI_MSI=y (Red Hat Enterprise Linux 6.1 開始支持該特性)
  • 在客戶機內使用 virtion-net 前段驅動
  • 在主機內使用網橋模式,而且啓動 vhost_net

qemu-kvm 命令的 -net tap 有幾個選項和 vhost-net 相關的: -net tap,[,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]

  • vnet_hdr =on|off:設置是否打開TAP設備的「IFF_VNET_HDR」標識。「vnet_hdr=off」表示關閉這個標識;「vnet_hdr=on」則強制開啓這個標識,若是沒有這個標識的支持,則會觸發錯誤。IFF_VNET_HDR是tun/tap的一個標識,打開它則容許發送或接受大數據包時僅僅作部分的校驗和檢查。打開這個標識,能夠提升virtio_net驅動的吞吐量。
  • vhost=on|off:設置是否開啓vhost-net這個內核空間的後端處理驅動,它只對使用MIS-X中斷方式的virtio客戶機有效。
  • vhostforce=on|off:設置是否強制使用 vhost 做爲非MSI-X中斷方式的Virtio客戶機的後端處理程序。
  • vhostfs=h:設置爲去鏈接一個已經打開的vhost網絡設備。 
vhost-net 的使用實例:
 
(1)確保主機上 vhost-net 內核模塊被加載了
 
(2)啓動一個虛擬機,在客戶機中使用 -net 定義一個 virtio-net 網卡,在主機端使用 -netdev 啓動 vhost
 
(3)在虛擬機端,看到 virtio 網卡使用的 TAP 設備爲 tap0。
 
(4)在宿主機中看 vhost-net 被加載和使用了,以及 Linux 橋 br0,它鏈接物理網卡 eth1 和 客戶機使用的 TAP 設備 tap0
 
通常來講,使用 vhost-net 做爲後端處理驅動能夠提升網絡的性能。不過,對於一些網絡負載類型使用 vhost-net 做爲後端,卻可能使其性能不升反降。特別是從宿主機到其中的客戶機之間的UDP流量,若是客戶機處理接受數據的速度比宿主機發送的速度要慢,這時就容易出現性能降低。在這種狀況下,使用vhost-net將會是UDP socket的接受緩衝區更快地溢出,從而致使更多的數據包丟失。故這種狀況下,不使用vhost-net,讓傳輸速度稍微慢一點,反而會提升總體的性能。
 
使用 qemu-kvm 命令行,加上「vhost=off」(或沒有vhost選項)就會不使用vhost-net,而在使用libvirt時,須要對客戶機的配置的XML文件中的網絡配置部分進行以下的配置,指定後端驅動的名稱爲「qemu」(而不是「vhost」)。

2.6 virtio-balloon

另外一個比較特殊的 virtio 設備是 virtio-balloon。一般來講,要改變客戶機所佔用的宿主機內存,要先關閉客戶機,修改啓動時的內存配置,而後重啓客戶機才能夠實現。而 內存的 ballooning (氣球)技術能夠在客戶機運行時動態地調整它所佔用的宿主機內存資源,而不須要關閉客戶機。該技術可以:

  • 當宿主機內存緊張時,能夠請求客戶機回收利用已分配給客戶機的部份內存,客戶機就會釋放部分空閒內存。若其內存空間不足,可能還會回收部分使用中的內存,可能會將部份內存換到交換分區中。
  • 當客戶機內存不足時,也可讓客戶機的內存氣球壓縮,釋放出內存氣球中的部份內存,讓客戶機使用更多的內存。
目前不少的VMM,包括 KVM, Xen,VMware 等都對 ballooning 技術提供支持。其中,KVM 中的 Ballooning 是經過宿主機和客戶機協同來實現的,在宿主機中應該使用 2.6.27 及以上版本的 Linux內核(包括KVM模塊),使用較新的 qemu-kvm(如0.13版本以上),在客戶機中也使用 2.6.27 及以上內核且將「CONFIG_VIRTIO_BALLOON」配置爲模塊或編譯到內核。在不少Linux發行版中都已經配置有「CONFIG_VIRTIO_BALLOON=m」,因此用較新的Linux做爲客戶機系統,通常不須要額外配置virtio_balloon驅動,使用默認內核配置便可。
 
原理:
  1. KVM 發送請求給 VM 讓其歸還必定數量的內存給KVM。
  2. VM 的 virtio_balloon 驅動接到該請求。
  3. VM 的驅動是客戶機的內存氣球膨脹,氣球中的內存就不能被客戶機使用。
  4. VM 的操做系統歸還氣球中的內存給VMM
  5. KVM 能夠將獲得的內存分配到任何須要的地方。
  6. KM 也能夠將內存返還到客戶機中。 
優點和不足: 
優點 不足
  1. ballooning 能夠被控制和監控
  2. 對內存的調節很靈活,可多可少。
  3. KVM 能夠歸還內存給客戶機,從而緩解其內存壓力。
  1. 須要客戶機安裝驅動
  2. 大量內存被回收時,會下降客戶機的性能。
  3. 目前沒有方便的自動化的機制來管理 ballooning,通常都在 QEMU 的 monitor 中執行命令來實現。
  4. 內存的動態增長或者減小,多是內存被過分碎片化,從而下降內存使用性能。

在QEMU monitor中,提供了兩個命令查看和設置客戶機內存的大小。

  • (qemu) info balloon    #查看客戶機內存佔用量(Balloon信息)
  • (qemu) balloon num   #設置客戶機內存佔用量爲numMB
使用實例:
 
 (1)啓動一個虛機,內存爲 2048M,啓用 virtio-balloon
 
(2)經過 vncviewer 進入虛機,查看 pci 設備
 
(3)看看內存狀況,共 2G 內存
 
(4)進入 QEMU Monitor,調整 balloon 內存爲 500M
 
(5)回到虛機,查看內存,變爲 500 M

2.7 RedHat 的 多隊列 Virtio (multi-queue)

    目前的高端服務器都有多個處理器,虛擬使用的虛擬CPU數目也不斷增長。默認的 virtio-net 不能並行地傳送或者接收網絡包,由於 virtio_net 只有一個TX 和 RX 隊列。而多隊列 virtio-net 提供了一個隨着虛機的虛擬CPU增長而加強網絡性能的方法,經過使得 virtio 能夠同時使用多個 virt-queue 隊列。
 
它在如下狀況下具備明顯優點:
  1. 網絡流量很是大
  2. 虛機同時有很是多的網絡鏈接,包括虛擬機之間的、虛機到主機的、虛機到外部系統的等
  3. virtio 隊列的數目和虛機的虛擬CPU數目相同。這是由於多隊列可以使得一個隊列獨佔一個虛擬CPU。
注意:對隊列 virtio-net 對流入的網絡流工做得很是好,可是對外發的數據流偶爾會下降性能。打開對隊列 virtio 會增長中的吞吐量,這相應地會增長CPU的負擔。 在實際的生產環境中須要作必須的測試後才肯定是否使用。
 
在 RedHat 中,要使用多隊列 virtio-net,在虛機的 XML 文件中增長以下配置:
 
而後在主機上運行下面的命令:
ethtool -L eth0 combined M ( 1 <= M <= N)

2.8 Windows 客戶機的 virtio 前端驅動

Windows 客戶機下的 virtio 前端驅動必須下載後手工安裝。 RedHat Linux  這篇文章 說明了在 Windows 客戶機內安裝virtio 驅動的方法。
 
參考文檔:
相關文章
相關標籤/搜索