淺談Linux設(shè)備虛擬化技術(shù)的演進之路
序言
設(shè)備虛擬化技術(shù),一直是云計算領(lǐng)域最重要的基礎(chǔ)技術(shù)之一。我們在虛擬機里面看到的形形色色的設(shè)備,比如:網(wǎng)卡,磁盤,鍵盤,鼠標等,都離不開這項技術(shù)的幫助。這篇文章,我們將從技術(shù)演進的角度來談一談 Linux 現(xiàn)有的以及即將到來的設(shè)備虛擬化技術(shù)。
Trap-and-emulate
在最早期階段,設(shè)備虛擬化常常和機器模擬器技術(shù),比如:QEMU,綁定在一起。我們可以通過 QEMU 模擬真實設(shè)備的所有寄存器布局和操作流程,當 QEMU 虛擬機里面設(shè)備驅(qū)動需要訪問該虛擬設(shè)備的寄存器時,這條訪問指令會被 trap 到 QEMU,由 QEMU 來進行處理。這樣,虛擬機里面的設(shè)備驅(qū)動在操作該虛擬設(shè)備時就像在訪問真實的硬件設(shè)備一樣,設(shè)備驅(qū)動也不需要任何變更。
Virtio
通過上述這種 trap-and-emulate 的方式來模擬設(shè)備,雖然不需要對真實設(shè)備驅(qū)動進行變更,但是設(shè)備訪問過程中,頻繁的陷入&陷出帶來了嚴重的性能問題,因此,virtio 這類半虛擬化技術(shù)應(yīng)運而生,并于 2008 年合入 Linux 內(nèi)核主線。
相較于 trap-and-emulate 這種方式,Virtio 不再拘泥于依賴已有的設(shè)備驅(qū)動,而是定義了一套全新的專用于虛擬設(shè)備的驅(qū)動框架。設(shè)備驅(qū)動清楚自己是在操作虛擬設(shè)備,因此,在真正的 I/O 路徑上規(guī)避了大量可能導致陷入&陷出的 mmio/pio 操作,從而提高了性能。虛機里面的 Virtio 驅(qū)動和 QEMU 模擬的 Virtio 設(shè)備的數(shù)據(jù)交互,本質(zhì)上是一套基于共享內(nèi)存 + 環(huán)形隊列的通信機制。核心數(shù)據(jù)結(jié)構(gòu)(split virtqueue)包括:兩個 ringbuffer (avail ring, used ring) 和一個 descriptor table。工作機制類似 DMA,虛機內(nèi) virtio 驅(qū)動首先會將一個請求在內(nèi)存中需要傳輸?shù)纳⒘?buffer 的地址、長度組成一個個描述符寫入到 descriptor table 中,然后將這些描述符對應(yīng)的 descriptor table 上的 index 寫入到 avail ring 中,并通過 eventfd 機制通知到宿主機上的 virtio backend。由于這些 ringbuffer、descriptor table 以及散列 buffer 都在共享內(nèi)存中(虛機本質(zhì)上是一個用戶態(tài)進程,因此虛機內(nèi)存是由用戶態(tài)申請和分配,并可以 share 給其他進程,如:SPDK,DPDK 等),因此,Virtio Backend 可以直接訪問并獲取到散列 buffer 的地址、長度,進而直接存取這些散列 buffer。當處理完請求之后,Virtio Backend 將數(shù)據(jù)填充到相應(yīng)的 buffer,并將對應(yīng)的 descriptor table index 寫入 used ring 中,并通過 eventfd 機制注入中斷通知虛機內(nèi) virtio 驅(qū)動。
Vhost
Virtio 技術(shù)提出之后,Virtio 設(shè)備通常是在 QEMU 里面來進行模擬,數(shù)據(jù)收發(fā)都需要經(jīng)過 QEMU,再到虛機內(nèi)部。但逐漸地,開發(fā)者們發(fā)現(xiàn),當模擬網(wǎng)卡時,在 QEMU 里面進行數(shù)據(jù)收發(fā),最終都需要通過系統(tǒng)調(diào)用的方式,陷入內(nèi)核來操作網(wǎng)卡硬件進行實際的數(shù)據(jù)收發(fā)。那么,QEMU 到內(nèi)核的這次上下文切換以及帶來的額外拷貝開銷,有沒有辦法優(yōu)化呢?
Linux 內(nèi)核社區(qū)最終在 2010 年合入了 vhost 這個技術(shù)來進行優(yōu)化,通過將 virtio 的數(shù)據(jù)面 offload 到一個內(nèi)核線程來進行處理,這樣 virtio 通信機制從原本的 QEMU 用戶態(tài) I/O 線程和虛機驅(qū)動(QEMU 用戶態(tài) vcpu 線程)通信變成了 vhost 內(nèi)核 I/O 線程和虛機驅(qū)動(QEMU 用戶態(tài) vcpu 線程)通信。vhost 內(nèi)核 I/O 線程拿到數(shù)據(jù)包之后,直接走內(nèi)核協(xié)議棧和網(wǎng)卡驅(qū)動進行處理,從而優(yōu)化掉了 QEMU 到內(nèi)核態(tài)的額外開銷。
VFIO
隨著云計算規(guī)模的不斷擴大,用戶一方面不再滿足于 Virtio 這類半虛擬化設(shè)備帶來的性能體驗,另一方面 GPU 這類很難進行 virtio 化的設(shè)備應(yīng)用場景與日俱增。在這種背景下,VFIO 這項技術(shù)被提出并在 2012 年合入 Linux 內(nèi)核主線。VFIO 全稱是 Virtual Function I/O,它實際是一個用戶態(tài)設(shè)備驅(qū)動框架,相較于更早的 uio 這個用戶態(tài)設(shè)備驅(qū)動框架,VFIO 能夠有效利用硬件 IOMMU 機制進行安全隔離,從而能夠廣泛地應(yīng)用在云計算這類有多租戶需求的場景中。
如上圖所示,通過 VFIO,QEMU 能夠直接將自己虛擬出的一個 PCI 設(shè)備和一個物理 PCI 設(shè)備的數(shù)據(jù)鏈路直接打通,當虛擬機里面的設(shè)備驅(qū)動訪問虛擬 PCI 設(shè)備的 bar 空間時,通過 EPT 機制,這次 mmio 訪問會被重定向到真實物理設(shè)備相應(yīng)的 bar 空間位置,而不再需要 trap 到 QEMU。這樣,虛機驅(qū)動就相當于可以以接近零消耗的方式直接訪問真實物理設(shè)備,性能可以達到最佳。同時,VFIO 驅(qū)動利用 IOMMU 實現(xiàn)了設(shè)備 DMA 和中斷的重映射,一方面起到隔離作用,即某個虛機無法操作 VFIO 直通設(shè)備向同一宿主機上的其他虛機發(fā)起 DMA 和中斷,一方面也保證了設(shè)備進行 DMA 時通過給定的虛機物理地址能夠直接訪問到正確的物理內(nèi)存。
Vhost-user
雖然,VFIO 能夠給虛機帶來接近物理機的 I/O 性能體驗,但該技術(shù)仍存在一個缺陷,即不支持熱遷移,帶 VFIO 設(shè)備的虛機將沒法像傳統(tǒng)帶 virtio 設(shè)備的虛機那樣進行熱遷移。這就使得開發(fā)者們,又開始探尋新的既能滿足性能需求又具備運維靈活性的設(shè)備虛擬化技術(shù)。2014 年 QEMU 社區(qū)合入的 vhost-user 技術(shù)就是其中之一,由于 QEMU 和 vhost 的線程模型對 I/O 性能的優(yōu)化并不友好,而且由每個虛機單獨分出線程來處理 I/O 這種方式從系統(tǒng)全局角度來看可能也并不是最優(yōu)的,因此,vhost-user 提出了一種新的方式,即將 virtio 設(shè)備的數(shù)據(jù)面 offload 到另一個專用進程來處理。這樣,由于是專用進程,線程模型不再受傳統(tǒng) QEMU 和 vhost 線程模型制約,可以任意優(yōu)化,同時,還可以以 1:M 的方式同時處理多個虛機的 I/O 請求,而且相較于 vhost 這種內(nèi)核線程方式,用戶進程在運維方面更加具備靈活性,vhost-user 框架在提出之初,就受到廣泛關(guān)注,并引申出了 SPDK 和 OVS-DPDK 這類以 polling + 用戶態(tài)驅(qū)動為核心的新的虛機 I/O 服務(wù)模型。
VFIO-mdev
VFIO 技術(shù)在實際應(yīng)用場景,除了之前提到的不支持熱遷移的問題外,還有一個限制就是一個設(shè)備只能透傳給一個虛機,無法做到資源共享。SR-IOV 技術(shù)從某種程度上能夠解決這個問題,即將一個物理 PCI 設(shè)備從硬件層面進行資源劃分,劃分成多個 VF,透傳給多個虛機進行使用,但是有很多設(shè)備可能并不具備 SR-IOV 能力,因此,Linux 內(nèi)核社區(qū)在 2016 年合入了 VFIO-mdev 這個技術(shù)框架,希望提供一個標準的接口來幫助設(shè)備驅(qū)動實現(xiàn)軟件層面的資源切分并能夠利用 VFIO 技術(shù)透傳給虛機。
該技術(shù)本質(zhì)上是在內(nèi)核實現(xiàn)了一個虛擬設(shè)備(Mediated device)總線驅(qū)動模型,并在 VFIO 內(nèi)核框架上進行了擴展,增加了對 mdev 這類虛擬設(shè)備的支持(mdev bus driver),從原來只支持從標準的硬件 PCI 設(shè)備和硬件 platform 設(shè)備獲取透傳信息,比如:PCI bar 空間,變成了既支持直接從硬件設(shè)備獲取又可以從 mdev 設(shè)備驅(qū)動定義的虛擬設(shè)備接口來獲取。這樣,比如,當需要將一個 PCI 設(shè)備的 bar 空間作為資源切分的話,通過實現(xiàn)合適的 mdev 設(shè)備驅(qū)動,就可以將 bar 空間以 4KB(頁面大小)為粒度,分別透傳給不同虛機使用。
vDPA
VFIO 和 virtio 這兩類技術(shù)一直是最主流的設(shè)備虛擬化技術(shù)。VFIO 能夠直接將硬件資源透傳給虛機使用,性能最佳,virtio 性能稍遜,但勝在更加靈活。那有沒有可能將兩者的優(yōu)勢結(jié)合起來呢?2020 年被合入 Linux 內(nèi)核主線的 vDPA 技術(shù)框架,就是為了實現(xiàn)這一目標。
vDPA 的全稱是 Virtio Data Path Acceleration,它表示一類設(shè)備:這類設(shè)備的數(shù)據(jù)面處理是嚴格遵循 Virtio 協(xié)議規(guī)范的,即驅(qū)動和設(shè)備會按照第三節(jié)提到的 Virtio 通信流程來進行通信,但控制路徑,比如:通信流程里面提到的 ring buffer 和 descriptor table 的內(nèi)存地址,驅(qū)動如何告知設(shè)備,設(shè)備支持的特性,驅(qū)動如何感知,這些都是廠商自定義的,不一定會遵循 Virtio 協(xié)議。這樣做的好處是,可以降低廠商在實現(xiàn)這類設(shè)備時的復雜度。
Linux 內(nèi)核為了將這類設(shè)備應(yīng)用起來,就提出了 vDPA 這樣一個技術(shù)框架。這個技術(shù)框架本質(zhì)上和 VFIO-mdev 類似,也實現(xiàn)了一個虛擬設(shè)備(vDPA device)總線驅(qū)動模型,和 VFIO-mdev 不同的是,通過 vDPA 框架虛擬出來的設(shè)備,既可以給虛機使用,又可以直接從宿主機(比如:容器)進行訪問。這一切都歸功于,vDPA 設(shè)備的數(shù)據(jù)路徑是遵循 Virtio 協(xié)議規(guī)范的,因此,可以直接被宿主機上的 virtio 驅(qū)動直接訪問。同時,該技術(shù)框架對 vhost 內(nèi)核子系統(tǒng)進行了擴展,賦予了類似 VFIO 技術(shù)框架的功能,允許將 vDPA 設(shè)備用來進行數(shù)據(jù)通信的硬件資源(ring buffer, descriptor table,doorbell 寄存器等)透傳給虛機使用,這樣,虛擬機的 virtio 驅(qū)動進行數(shù)據(jù)通信時,也是直接訪問硬件資源,而不再需要通過 vhost、vhost-user 等方式進行處理了。更重要的一點是,由于虛機驅(qū)動是原本的 virtio 驅(qū)動,因此,當需要支持熱遷移時,QEMU 可以靈活切換會軟件模擬的方式,來保證熱遷移的順利進行。這樣,vDPA 這個設(shè)備虛擬化技術(shù)框架既保證了最佳性能又保留了 virtio 設(shè)備的靈活性,而且還統(tǒng)一了虛機和容器的 I/O 技術(shù)棧。
VDUSE
通過上述 vDPA 技術(shù)框架,我們基本解決了長期以來設(shè)備虛擬化技術(shù)在虛機場景下暴露的一些問題,而更重要的是,它將 virtio 技術(shù)也帶到了容器領(lǐng)域。但這個技術(shù)框架還存在一個問題,就是需要硬件設(shè)備的支持?;叵胫疤岬降? virtio、vhost、vhost-user,本質(zhì)上都是軟件定義的虛擬設(shè)備。那 vDPA 這個技術(shù)框架有沒有可能也能夠使用軟件定義的設(shè)備呢?VDUSE 這項技術(shù)就是用來實現(xiàn)這個目標的,通過 VDUSE,我們可以在一個用戶進程實現(xiàn)一個軟件定義的 vDPA 設(shè)備,并可以通過上述 vDPA 框架接入 virtio 或者 vhost 子系統(tǒng),供容器或者虛機使用。
該項技術(shù)是由我們自主研發(fā)并在去年 10 月向 Linux 內(nèi)核社區(qū)正式開源的?,F(xiàn)階段我們的方案已經(jīng)被合入 Linux 內(nèi)核主線,將在 Linux 5.15 版本與大家見面。同時,我們也會在 9 月 15 日舉辦的 KVM Forum 這個虛擬化領(lǐng)域的高端技術(shù)論壇會議上進行線上分享。
結(jié)束語
從服務(wù)虛擬機到支持容器,從純軟件模擬到硬件直通再到軟硬件結(jié)合,Linux 設(shè)備虛擬化技術(shù)這幾十年里一直在朝著極致性能、應(yīng)用靈活等方向不斷演進。隨著云原生的浪潮,各大硬件廠商的入局,全新的軟硬件結(jié)合方式不斷涌現(xiàn),我們相信后續(xù)也會有更多精彩技術(shù)在等待著我們。