kvm熱遷移


第一部分 SR-IOV簡介

https://cloud.tencent.com/developer/article/1087112

1.1 SR-IOV簡介

SR-IOV(PCI-SIG Single Root I/O Virtualization and Sharing)是PCI-SIG組織發布的規范。

設計PCI-SIG SR-IOV 規范的目的是:通過為虛擬機提供獨立的內存地址、中斷和DMA流而避免VMM的介入。SR-IOV允許一個PCI設備提供多個VFs。VMM將一個或者多個 VF 分配給一個虛機。一個VF同時只能被分配一個虛機。而虛擬機感知不到這個網卡是被VF的還是普通的物理網卡。

1.2 SR-IOV引入了兩個PCIefunction types

PFs:包括管理SR-IOV功能在內的所有PCIe function。

VFs:一部分輕量級的PCIe function,只能進行必要的數據操作和配置。

1.3 R-IOV工作流程中有三個角色

1.PCIe的SR-IOV機制:提供獨立可配置的多個VFs,每一個VFs具有獨立的PCIe配置空間。

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/

KVM熱遷移大體流程和內存降速問題

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。在實現上,就是采取了以下措施:

  • 有限循環:循環次數和效果受到控制,對每輪 pre-copy 的效果進行計算,若 pre-copy 對於減少不一致內存數量的效果不顯著,或者循環次數超過了上限,循環將中止,進入停機拷貝階段。
  • 在被遷移 VM 的內核設置一個內存訪問的監控模塊。在內存 pre-copy 過程中,VM 的一個進程在一個被調度運行的期間,被限制最多執行 40 次內存寫操作。這個措施直接限制了 pre-copy 過程中內存變臟的速度,其代價是對 VM 上的進程運行進行了一定的限制。【這個模塊是要改guest OS嗎?】

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 設備類型:

  • Network cards (wired or wireless)
  • SCSI adapters
  • Bus controllers: USB, PCMCIA, I2C, FireWire, IDE
  • Graphics and video cards
  • Sound cards
這種方式,允許將宿主機中的物理 PCI 設備直接分配給客戶機使用。較新的x86平台已經支持這種類型,Intel 定義的 I/O 虛擬化技術成為 VT-d,AMD 的稱為 AMD-V。KVM 支持客戶機以獨占方式訪問這個宿主機的 PCI/PCI-E 設備。通過硬件支持的 VT-d 技術將設備分給客戶機后,在客戶機看來,設備是物理上連接在PCI或者PCI-E總線上的,客戶機對該設備的I/O交互操作和實際的物理設備操作完全一樣,不需要或者很少需要 KVM 的參與。運行在 VT-d 平台上的 QEMU/KVM,可以分配網卡、磁盤控制器、USB控制器、VGA 顯卡等設備供客戶機直接使用。
  • 好處:在執行 I/O 操作時大量減少甚至避免 VM-Exit 陷入到 Hypervisor 中,極大地提高了性能,可以達到幾乎和原生系統一樣的性能。VT-d 克服了 virtio 兼容性不好和 CPU 使用頻率較高的問題。
  • 不足:(1)一台服務器主板上的空間比較有限,因此允許添加的 PCI 和 PCI-E 設備是有限的。大量使用 VT-d 獨立分配設備給客戶機,讓硬件設備數量增加,這會增加硬件投資成本。(2)對於使用 VT-d 直接分配了設備的客戶機,其動態遷移功能將受限,不過也可以使用熱插拔或者libvirt 工具等方式來緩解這個問題。
  • 不足的解決方案:(1)在一台物理宿主機上,僅少數 I/O 如網絡性能要求較高的客戶機使用 VT-d直接分配設備,其他的使用純模擬或者 virtio 已達到多個客戶機共享同一個設備的目的 (2)對於網絡I/O的解決辦法,可以選擇 SR-IOV 是一個網卡產生多個獨立的虛擬網卡,將每個虛擬網卡分配個一個客戶機使用。
幾乎所有的 PCI 和 PCI-E 設備都支持直接分配,除了顯卡以外(顯卡的特殊性 在這里)。PCI Pass-through 需要硬件平台 Intel VT-d 或者 AMD IOMMU 的支持。這些特性必須在 BIOS 中被啟用。Red Hat Enterprise Linux 6.0 及以上版本支持熱插拔的 PCI 設備直接分配到虛擬機。
網卡直接分配:

硬盤直接分配:

  • 一般 SATA 或者 SAS 等類型的硬盤的控制器都是直接接入到 PCI 或者  PCI-E 總線的,所以也可以將硬盤作為普通的PCI設備直接分配個客戶機。需要注意的是,當分配硬盤時,實際上將其控制器作為一個整體分配到客戶機中,因此需要在硬件平台上至少有另兩個或者多個SATA或者 SAS控制器。 

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

The purpose of virtio and [virtio] specification is that virtual environments
and guests should have a straightforward, efficient, standard and extensible
mechanism for virtual devices, rather than boutique per-environment or per-OS
mechanisms.

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 protocol] is aiming to complement the ioctl interface used to
control the vhost implementation in the Linux kernel. It implements the control
plane needed to establish virtqueue sharing with a user space process on the
same host. It uses communication over a Unix domain socket to share file
descriptors in the ancillary data of the message.
The protocol defines 2 sides of the communication, master and slave. Master is
the application that shares its virtqueues, in our case QEMU. Slave is the
consumer of the virtqueues.
In the current implementation QEMU is the Master, and the Slave is intended to
be a software Ethernet switch running in user space, such as Snabbswitch.
Master and slave can be either a client (i.e. connecting) or server (listening)
in the socket communication.

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主要使用了下面的技術來提高性能:

  1. 采用了大頁來作為host和vm之間通信的內存空間
  2. 用戶態操作網卡,使用類似於netmap的zero copy技術來加速對物理設備的訪問
  3. 使用numa技術,加快中斷響應速率

值得一提的是使用snabbswitch后,不用再使用原來的tap設備模擬的網卡。

使用vhost-user技術,從虛擬機到host上實現了數據的zero copy(通過大頁共享),host到nic的zero copy(snabbswitch實現的驅動),能進一步加快數據的傳輸。

DPDK便是一個在用戶態可以直接操作物理網卡的庫函數,它和vhost-user結合便可以實現類似於snabb switch一樣性能強勁的用戶態交換機了

【有了vhost-user,DPDK和SPDK(storage performance xx)等加速框架就得以實現了】


免責聲明!

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



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