第一部分 SR-IOV簡介html
https://cloud.tencent.com/developer/article/1087112前端
1.1 SR-IOV簡介node
SR-IOV(PCI-SIG Single Root I/O Virtualization and Sharing)是PCI-SIG組織發佈的規範。linux
設計PCI-SIG SR-IOV 規範的目的是:經過爲虛擬機提供獨立的內存地址、中斷和DMA流而避免VMM的介入。SR-IOV容許一個PCI設備提供多個VFs。VMM將一個或者多個 VF 分配給一個虛機。一個VF同時只能被分配一個虛機。而虛擬機感知不到這個網卡是被VF的仍是普通的物理網卡。後端
1.2 SR-IOV引入了兩個PCIe的function types安全
PFs:包括管理SR-IOV功能在內的全部PCIe function。服務器
VFs:一部分輕量級的PCIe function,只能進行必要的數據操做和配置。網絡
1.3 R-IOV工做流程中有三個角色架構
1.PCIe的SR-IOV機制:提供獨立可配置的多個VFs,每個VFs具備獨立的PCIe配置空間。app
2.VMM:則把VFs分配給虛擬機。
3.VT-x和VT-d:經過硬件輔助技術提供和虛擬機之間的直接DMA數據映射傳輸,跳過VMM的干預。
1.4 SR-IOV原理
下面一幅圖描述了SR-IOV的原理(來自intel《PCI-SIG SR-IOV Prime》):
1.5 SR-IOV的優缺點
SR-IOV相對與軟件模擬IO虛擬化的優勢:
1.下降了IO延遲和對CPU的佔用,得到了接近原生的IO性能,由於虛擬機直接使用VFs,沒有了VMM的陷入處理。
2.數據更加安全,由於每一個VF屬於一個IOMMU Group,共享IOMMU Group的設備不能分配給不一樣的虛擬機,而每一個IOMMU Group又有獨立的內存。
SR-IOV相對與Device assignment的優勢:
沒有了一個PCI設備只能給一個虛擬機的尷尬,SR-IOV下多個虛擬機可經過獨佔VFs的方式共享一個PCI設備。
SR-IOV的缺點:
使用了VFs的虛擬機不能在線遷移。
第二部分 KVM熱遷移原理
https://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm1/index.html 介紹原理
https://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm2/index.html 實驗(操做qemu執行熱遷移)
https://developers.redhat.com/blog/2015/03/24/live-migrating-qemu-kvm-virtual-machines/
2.1 概述
遷移的前面階段,服務在源主機運行,當遷移進行到必定階段,目的主機已經具有了運行系統的必須資源,通過一個很是短暫的切換,源主機將控制權轉移到目的主機,服務在目的主機上繼續運行。
對於 VM 的內存狀態的遷移,XEN 和 KVM 都採用了主流的的預拷貝(pre-copy)的策略。遷移開始以後,源主機 VM 仍在運行,目的主機 VM 還沒有啓動。遷移經過一個循環,將源主機 VM 的內存數據發送至目的主機 VM。循環第一輪發送全部內存頁數據,接下來的每一輪循環發送上一輪預拷貝過程當中被 VM 寫過的髒頁內存 dirty pages。直到時機成熟,預拷貝循環結束,進入停機拷貝階段,源主機被掛起,再也不有內存更新。最後一輪循環中的髒頁被傳輸至目的主機 VM。
預拷貝機制極大的減小了停機拷貝階段須要傳輸的內存數據量,從而將停機時間大大縮小。【意思是預拷貝不影響vm的在線運行,減小了停機時間】
最右邊部分的圖表是QEMU狀態,整個狀態不涉及遷移過程。可是在遷移開始以前將這個狀態設置正確很重要。在源主機和目的主機上的QEMU設置必須相同,這是經過在兩個主機上使用一條類似的QEMU命令行來實現的。因爲QEMU命令行的多種選擇很是難以搞定,咱們使用Libvirt替咱們選擇正確的。Libvirt能夠確保QEMU兩邊程序的遷移設置正確性。
在線遷移分3個階段:
第一個階段:將全部RAM都標記髒
第二個階段:持續不斷髮送髒RAM,當達到一些低水印或者條件時中止
第三個階段:中止運行客戶機,將剩餘髒RAM,設備狀態轉移過去,在目標主機QEMU上啓動虛擬機
在第二階段代碼,咱們會在每一個迭代來檢查有多少頁面被客戶機標記髒。會檢查花費多長時間來轉換一個頁面,以便來設定一個預估的網絡帶寬。在這個預估帶寬和當前迭代的髒頁面數量,咱們能夠計算出花費多久來轉化剩餘頁面。若是在可接受或者設置的停機時間限制內,咱們過渡到第三階段是沒有問題的。不然咱們會繼續停留在第二階段。
QEMU中還有更多的與遷移有關的代碼:有些代碼是用來發送/接受遷移數據:TCP或者UNIX包,本地文件說明符,或者RDMA。也有exec功能,來自QEMU的數據,在被髮送到目的地前,會被傳輸到其餘進程。這對於傳出數據壓縮,加密都頗有用。在目的端,也須要進行解壓縮或者解加密進程。對於UNIX包,fd或者exec-based協議,須要更高層的程序來管理兩端的遷移。Libvirt就是這個程序,咱們能夠依賴libvirt的能力來控制這個遷移。
2.2 如何判斷」時機成熟「
對於更新速度很是快的內存部分,每次循環過程都會變髒,須要重複 pre-copy,同時也致使循環次數很是多,遷移的時間變長。針對這種狀況,KVM 虛擬機創建了三個原則:集中原則,一個循環內的 dirty pages 小於等於 50;不擴散原則, 一個循環內傳輸的 dirty pages 少於新產生的;有限循環原則,循環次數必須少於 30。在實現上,就是採起了如下措施:
2.3 遷移過程詳解
(1)系統驗證目標服務器的存儲器和網絡設置是否正確,並預保留目標服務器虛擬機的資源。
圖 1. 源服務器和目標服務器簡圖
(2)當虛擬機還在源服務器上運轉時,第一個循環內將所有內存鏡像複製到目標服務器上。在這個過程當中,KVM 依然會監視內存的任何變化。
圖 2. 內存鏡像複製示意圖
(3)之後的循環中,檢查上一個循環中內存是否發生了變化。 假如發生了變化,那麼 VMM 會將發生變化的內存頁即 dirty pages 從新複製到目標服務器中,並覆蓋掉先前的內存頁。在這個階段,VMM 依然會繼續監視內存的變化狀況。
圖 3. 進行有變化的內存複製
(4)VMM 會持續這樣的內存複製循環。隨着循環次數的增長,所須要複製的 dirty pages 就會明顯減小,而複製所耗費的時間就會逐漸變短,那麼內存就有可能沒有足夠的時間發生變化。最後,當源服務器與目標服務器之間的差別達到必定標準時,內存複製操做纔會結束,同時暫停源系統。
圖 4. 所需複製的數據在減小
(5)在源系統和目標系統都停機的狀況下,將最後一個循環的 dirty-pages 和源系統設備的工做狀態複製到目標服務器。
圖 5. 狀態信息的複製
(6)而後,將存儲從源系統上解鎖,並鎖定在目標系統上。啓動目標服務器,並與存儲資源和網絡資源相鏈接。
圖 6. 中止源服務器,啓動目標服務器
第三部分 passthrough與SR-IOV區別、vhost和vhost-user等
https://www.cnblogs.com/sammyliu/p/4548194.html
http://virtual.51cto.com/art/201801/563894.htm
https://blog.csdn.net/qq_15437629/article/details/77899905
http://blog.vmsplice.net/2011/09/qemu-internals-vhost-architecture.html
https://spdk.io/doc/vhost_processing.html
3.1 Passthrough
設備直接分配 (Device assignment)也稱爲 Device Pass-Through。
先簡單看看PCI 和 PCI-E 的區別(AMD CPU):
(簡單點看,PCI 卡的性能沒有 PCI-E 高,由於 PCI-E 是直接連在 IOMMU 上,而 PCI 卡是連在一個 IO Hub 上。)
IOMMU = Input/Output Memory Management Unit
主要的 PCI 設備類型:
硬盤直接分配:
3.2 Passthrough分配示例:
準備工做:
(1)在 BIOS 中打開 Intel VT-d
(2)在 Linux 內核中啓用 PCI Pass-through
添加 intel_iommu=on 到 /boot/grub/grub.conf 文件中。(在個人 RedHat Linux 6上,該文件是 /boot/grub.conf)
(3)重啓系統,使得配置生效
實際分配:
(1)使用 lspci -nn 命令找到待分配的 PCI 設備。這裏以一個 FC 卡爲例:
使用 lspci 命令獲得的 PCI 數字的含義,之後使用 libvirt API 分配設備時會用到:
(2)使用 virsh nodedev-list 命令找到該設備的 PCI 編號
(3)將設備從主機上解除
(4)使用 virt-manager 將設備直接分配給一個啓動了的虛擬機
3.3 各類設備虛擬化方式的比較【注意:什麼是vhost???】
3.4 IO設備的虛擬化方式
3.4.1 全虛擬化下vm的IO路徑
(1)當虛擬機進行I/O操做時,根據《也談Intel的cpu虛擬化》咱們知道,虛擬機經過VM exit將cpu控制權返回給VMM,從而陷入到root模式下的ring0內的VMM,進行」陷入模擬「。
(2)將本次I/O請求的信息存放到IO共享頁,QEMU從IO共享頁讀取信息後由硬件模擬代碼來模擬出本次的IO操做,並調用內核中的硬件驅動把IO請求發送到物理硬件,完成以後將結果放回到IO共享頁。
(3)KVM模塊中的捕獲代碼讀取IO共享頁中的結果,把結果返回到guest。
(4)經過VM entry,guest再次得到cpu控制權,根據IO返回的結果進行處理。
說明:VMM和guest的IO信息共享不光IO共享頁一種,還可使用DMA。QEMU不把IO結果放到IO共享頁中,而是經過DMA將結果直接寫到guest的內存中去,而後經過KVM模塊告訴客戶機DMA操做已經完成。
3.4.2 半虛擬化virtio
guest和host使用使用virtio先後端的技術減小了guest IO時的VM Exit(guest和host的上下文切換)而且使guest和host能並行處理IO來提升throughput和減小latency。可是IO的路徑並無比全虛擬化技術減小。下面是virtio的IO路徑:
guest在IO請求時,首先guest須要切換到host kernel,而後host kernel會切換到hyperisor來處理guest的請求,hypervisor經過系統調用將數據包發送到外部網絡後切換回host kernel,而後再切換回guest。這個長IO路徑和全虛擬化時相同的,只是減小了VM exit和VM entry。
IBM在2005年提出了virtio, 虛擬機中的半虛擬化前端驅動和主機上的後端服務簡單的使用virtqueue共享隊列交換數據,大幅的減小了e1000模擬時複雜的io操做,從而能夠較大程度的提高虛擬網絡性能。
guest使用virtio driver將請求發送給virtio-backend。
圖中描述了virtio的io路徑: guest發出中斷信號退出kvm,從kvm退出到用戶空間的qemu進程。而後由qemu開始對tap設備進行讀寫。 能夠看到這裏從用戶態進入內核,再從內核切換到用戶態,進行了2次切換。
virtio的io路徑:guest設置好tx→kick host→guest陷出到kvm→kvm從內核切換到用戶態的qemu進程→qemu將tx數據投遞到tap設備
3.4.3 vhost和vhost-user
爲了解決virio的IO路徑太長的問題,vhost產生了。它是位於host kernel的一個模塊,用於和guest直接通訊,因此數據交換就在guest和host kernel間進行,減小了上下文的切換。
vhost相對與virto架構,把virtio驅動後端驅動從用戶態放到了內核態中(vhost的內核模塊充當virtiO後端驅動),在內核中加入了vhost-net.ko模塊,使得對網絡數據能夠在內核態獲得處理。
guest發出中斷信號退出kvm,kvm直接和vhost-net.ko通訊,而後由vhost-net.ko訪問tap設備。 這樣網絡數據只須要通過從用戶態到內核態的一次切換,就能夠完成數據的傳輸。大大提升了虛擬網卡的性能。
路徑:guest設置好tx→kick host→guest陷出到kvm→vhost-net將tx數據投遞到tap設備
vhost-user和vhost相似,只是使用一個用戶態進程vhost-user代替了內核中的vhost模塊。
vhost-user進程和Guset之間時經過共享內存的方式進行數據操做。vhost-user相對與vhost架構,把virtio驅動後端驅動從內核態又放回到了用戶態中(vhost-user進程充當virtiO後端驅動)。
它將網絡數據放入用戶態處理將能夠獲得更靈活的形式:
路徑:guest設置好tx→kick host→guest陷出到kvm→kvm將通知vhost-backend→vhost-backend將tx數據直接發送到nic設備
vhost-backend從原來kernel中的vhost-net 變成了用戶空間的snabbswitch,snabbswitch直接接管物理網卡的驅動,從而直接控制網絡信息的輸入輸出。snabbswitch主要使用了下面的技術來提升性能:
值得一提的是使用snabbswitch後,不用再使用原來的tap設備模擬的網卡。
使用vhost-user技術,從虛擬機到host上實現了數據的zero copy(經過大頁共享),host到nic的zero copy(snabbswitch實現的驅動),能進一步加快數據的傳輸。
DPDK即是一個在用戶態能夠直接操做物理網卡的庫函數,它和vhost-user結合即可以實現相似於snabb switch同樣性能強勁的用戶態交換機了。
【有了vhost-user,DPDK和SPDK(storage performance xx)等加速框架就得以實現了】