【KVM系列03】KVM的I/O 全虚拟化和准虚拟化
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??第三章 I/O 全虛擬化和準虛擬化
? ? ? ?1. 全虛擬化 I/O 設備
1.1 原理
1.2 QEMU 模擬網卡的實現
?1.3 RedHat Linux 6 中提供的模擬設備
1.4 qemu-kvm 關于磁盤設備和網絡的主要選項
2. 準虛擬化 (Para-virtualizaiton) I/O 驅動 virtio
2.1 virtio 的架構
2.2 Virtio 在 Linux 中的實現
2.3 使用 virtio 設備 (以 virtio-net 為例)
2.4 vhost-net (kernel-level virtio server)
2.6 virtio-balloon
?2.7 RedHat 的 多隊列 Virtio (multi-queue)
2.8 Windows 客戶機的 virtio 前端驅動
【KVM系列文章】https://blog.csdn.net/baidu_37107022/article/details/88812463
?
在 QEMU/KVM 中,客戶機可以使用的設備大致可分為三類:
1. 模擬設備:完全由 QEMU 純軟件模擬的設備。
2. Virtio 設備:實現 VIRTIO API 的半虛擬化設備。
3. PCI 設備直接分配?(PCI device assignment) 。
1. 全虛擬化 I/O 設備
KVM 在 IO 虛擬化方面,傳統或者默認的方式是使用 QEMU 純軟件的方式來模擬 I/O 設備,包括鍵盤、鼠標、顯示器,硬盤 和 網卡 等。模擬設備可能會使用物理的設備,或者使用純軟件來模擬。模擬設備只存在于軟件中。?
1.1 原理
過程:
注意:當客戶機通過DMA (Direct Memory Access)訪問大塊I/O時,QEMU 模擬程序將不會把結果放進共享頁中,而是通過內存映射的方式將結果直接寫到客戶機的內存中共,然后通知KVM模塊告訴客戶機DMA操作已經完成。
這種方式的優點是可以模擬出各種各樣的硬件設備;其缺點是每次 I/O 操作的路徑比較長,需要多次上下文切換,也需要多次數據復制,所以性能較差。?
1.2 QEMU 模擬網卡的實現
Qemu 純軟件的方式來模擬I/O設備,其中包括經常使用的網卡設備。Guest OS啟動命令中沒有傳入的網絡配置時,QEMU默認分配 rtl8139 類型的虛擬網卡類型,使用的是默認用戶配置模式,這時候由于沒有具體的網絡模式的配置,Guest的網絡功能是有限的。 全虛擬化情況下,KVM虛機可以選擇的網絡模式包括:
分別使用的 qemu-kvm 參數為:
- -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的收發包的流程。
如圖中所示,紅色箭頭表示數據報文的入方向,步驟:
(引用自?http://luoye.me/2014/07/17/netdev-virtual-1/)
?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 Linxu 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 的 vitio 實現采用在 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 的原理:
它使得:
(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驅動,使用默認內核配置即可。
原理:
優勢和不足:
| 優勢 | 不足 |
| | |
在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 隊列。
它在以下情況下具有明顯優勢:
注意:對隊列 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 驅動的方法。
參考文檔:
- http://linux.web.cern.ch/linux/centos7/docs/rhel/Red_Hat_Enterprise_Linux-7-Virtualization_Tuning_and_Optimization_Guide-en-US.pdf
- http://toast.djw.org.uk/qemu.html
- KVM 官方文檔
- KVM 虛擬化技術實戰與解析 任永杰、單海濤 著
- RedHat Linux 6 官方文檔
- http://www.slideshare.net?中關于 KVM 的一些文檔
- http://www.linux-kvm.org/page/Multiqueue
- 以及部分來自于網絡,比如?http://smilejay.com/2012/11/use-ballooning-in-kvm/
總結
以上是生活随笔為你收集整理的【KVM系列03】KVM的I/O 全虚拟化和准虚拟化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【KVM系列02】KVM的CPU 和内存
- 下一篇: 【KVM系列04】KVM的I/O 设备直