KVM&Libvirt基本概念及開發雜談

大雄45發表於2022-08-23
導讀 大家好,本次肖力分享的主題是KVM&Libvirt基本概念及開發雜談,內容有些凌亂鬆散,主要基於自己早期整理的筆記內容和實踐感悟,有些內容難免有失偏頗,望見諒。前面先介紹下需要了解的基本知識,大部分內容在肖力著作中都有更詳細的解釋,可閱讀參考。
KVM包含:
1.核心模組kvm.ko,用於核心虛擬框架。
2.包含與處理器相關的模組kvm-intel.ko,kvm-amd.ko
3.kvm需要使用經過修改定製的qemu軟體提供使用者空間工具
*核心元件已經包含在Linux核心2.6.20中了
*部分作業系統在kvm中執行仍然存在某些問題,可以檢視KVM官網提供的作業系統執行相容性狀態列表
使用KVM的前提條件:
1.qemu-kvm-release.tar.gz
2.kvm-kmod-release.tar.bz2,自己編譯核心模組的需要這個東東
3.支援VT技術的Intel處理器或支援SVM技術的AMD處理器
使用qemu前提條件:
1.zlib庫及標頭檔案
2.sdl庫及標頭檔案
3.alsa庫及標頭檔案,這個是用來提供虛擬化音訊相關功能,預設是禁用的,現在不知道什麼狀態了,可以使用--enable-alsa來啟用
4.gnutls庫及標頭檔案,可選的VNC TLS支援,預設此功能是開啟的,可以用--disable-vnc-tls關閉
5.kernel標頭檔案
*建立,安裝,執行KVM虛機,需要使用QEMU提供的使用者空間工具,以前是分開發布的,現在分支已經合併,成為qemu-kvm。
*libvirt為使用者提供了同不同虛擬化技術互動的抽象介面。
libvirt基本理念:
1.同linux虛擬化技術進行互動
2.免費,自由
3.穩定的C語言API
4.其他通用語言的繫結開發介面(java,python,perl,php。。。)
5.針對DMTF虛擬風格
6.QMF代理,用於AMQP、QPID資訊系統
libivrt支援度:

虛擬技術:kvm/qemu,  XEN, LXC, OpenVZ, UserModeLinux, VB, ESX, HyperV, PowerVM, Parallels, Bhyre

虛擬網路:橋接,NAT,VEPA,VNLINK

儲存:IDE、SCSI,USB,FC,LVM,ISCSI,NFS,FS

libvirt對各種開發語言的支援:
1.直接支援c和c++,其他透過繫結支援 
2.C#,JAVA,OCAML,Perl,PHP,Python 
3.libvirt直接支援python,如果是透過安裝包安裝而不是原始碼編譯的,需要確保安裝合適的包,在RHEL中,叫libvirt-python,在ubuntu中叫python-libvirt,其他平臺可能有不同的名字。
URI:用於連線或遠端連線到宿主機的libvirt虛擬環境,類似資料庫的連線字串
1.指定URI連線到libvirt:透過把name引數傳遞到virConnectOpen或virConnectOpenReadOnly方法: virConnectPtr conn = virConnectOpenReadOnly("xxx:///default"); 
2.為節省管理員時間,可以在libvirt客戶端配置檔案中配置URI別名,
配置檔案位置/etc/libvirt/libvirt.conf(針對root使用者)或$XDG_CONFIG_HOME/libvirt/libvirt.conf(針對非特權使用者),可用下面語法設定別名 uri_aliases = [ "miaomiao=xxx://xxx@] 別名由a-z,0-9,_等字元組成,URI別名會應用到任何開啟libvirt連線的應用中,除非把引數VIR_CONNECT_NO_ALIASES傳給virConnectOpenAuth,
如果別名中包含非法字元,則不做任何別名查詢。 
如果URI傳遞給virConnectOpen引數為NULL,則libvirt會用下面規則確定URI: 
  1.環境變數:LIBVIRT_DEFAULT_URI 
  2.客戶端配置檔案:uri_default引數
  3.探測每個虛機管理器知道找到一個可用的
libvirt基本概念:

node:節點,宿主機,一個node是一個單獨的物理機,用於執行虛機

hypervisor:一個軟體層,可以把一個物理機用不同的配置虛擬化為多個虛機的集合

domain:虛擬機器,在容器級虛擬化情況中,是一個子系統,執行在由hypervisor提供的機器上

libvirt:提供一個通用的軟體層,安全高效的管理node上的domain,同時實現遠端管理功能。

*在windows系統中使用libvirt java繫結,需要使用libvirt java庫,jna.jar庫及對應平臺的dll檔案,如果報錯:找不到dll或找不到相關模組時,需要安裝virtviewer 在java程式碼中加入: System.setProperty("jna.library.path", "c:\\program files\\VirtViewer\\bin"); 並需要在上面路徑放置一份virt-0.dll檔案副本,命名為virt.dll

SPICE:

SPICE服務端是一個用libspice實現的VDI庫,VDI定義了一系列介面來發布虛擬裝置。(如:顯示裝置,鍵盤,滑鼠)並且能讓不同的spice元件和這些裝置互動,從一方面來說,服務端使用spice協議同客戶端通訊,從另一方面來說,服務端同VDI主機應用進行互動如QEMU。 SPICE客戶端是終端使用者所面對的介面。

QXL裝置和驅動

當libspice與qemu結合使用時,QEMU QXL PCI裝置可以用來提升遠端顯示效能,增強客戶機的圖形系統。QXL裝置需要客戶機QXL驅動支援。 SPICE協議支援一種通訊通道,此通道連線客戶和服務端的代理,當使用QEMU時,SPICE代理位於客戶機,VDI埠是一個QEMUPCI裝置,可以與此代理進行通訊。

SPICE有六大通道:

主通道:控制與配置

顯示通道:圖形 ,圖形,影片流

輸入通道:鍵盤和滑鼠輸入

游標通道:定位裝置的位置與游標形狀

回放通道:服務端的聲音在客戶端播放

錄製通道:從客戶端進行音訊捕獲

SPICE影像壓縮功能:

SPICE本身提供了多種影像壓縮演算法,可以在伺服器初始化時進行選擇,也可以在執行期動態選擇. QUIC是SPICE專有的影像壓縮演算法,此技術基於SFALIC演算法,Lempel_zip(LZ)演算法同樣也是SPICE支援的演算法。QUIC和LZ都是本地演算法,獨立編碼每一個影像。全域性LZ(GLZ)是另一個SPICE專有演算法,與LZ同基於歷史的全域性字典表共同使用,GLZ可以在大量影像之間使用重複表示式來降低流量消耗,從而儲存頻寬。特別適合在低頻寬的廣域網環境中使用。 SPICE同樣提供了一個針對每一個影像自動選擇壓縮演算法的工作模式,透過影像屬性啟發式的選擇LZ,GLZ,QUIC演算法。 從理論上講,LZ、GLZ更適合壓縮合成影像,QUIC更適合壓縮真實影像.

影片壓縮:

SPICE使用低損壓縮演算法壓縮傳送到客戶端的影像,但是影片流卻是使用不同的方法來處理。SPICE服務端使用自啟發方式標記動態影片區域並把他們作為影片流傳送出去,編碼使用mjpeg,這種處理方法在某種程度上節約了流量,提高了spice效能,尤其在廣域網環境中。可是在某些情況下,這種啟發行為可能會導致低質量的影像效果,比如把不斷更新的文字區域識別為影片區域,從而導致部分割槽域影像效果質量低下。

從原始碼編譯,需要以下元件:

*qpixman:一個控制畫素區域的通用庫,包括低階別畫素控制程式,同時也被cairo庫使用,cairo是一個用於支援多輸出裝置的2D圖形庫,qpixman是pixman的輕量級修改版

*qcairo:cairo是一個向量圖形裝置無關庫,qcairo是cairo的輕量級修改版 *celt:CELT是一種音訊壓縮演算法,以高質量傳輸音樂,訊號會有非常小的延遲 *ffmpeg:是一個用於音訊和影片重編碼,轉換,流傳輸的庫。包括libarcodec音訊影片編碼庫 *log4cpp是一個靈活的日誌記錄庫,可以針對檔案,syslog等,繼log4j之後成型

*關於windows虛機安裝virtio硬碟驅動的問題,一種方式是在安裝系統的過程中加在virtio驅動光碟或軟盤(winxp),如果系統已經裝完,可以先建立一個小磁碟映象, qemu-img create -f qcow2 xxx.img 1G 編輯虛機配置檔案,加入此硬碟映象,設定引數dev='vdc' bus='virtio'啟動系統後會發現新硬體,選ISO映象中對應的virtiosto驅動選virtioscsi驅動關閉vm,修改虛機配置,刪除小硬碟映象,把原磁碟改為dev='vda' bus='virtio'並刪除地址部分,啟動系統檢視驅動情況。

*關於已有libvirt時自己編譯libvirt時導致libvirt-sock不存在情況,該位置在/run/user/1000/libvirt/libvirt-sock或/usr/local/var/run/libvirt/libvirt-sock,編譯後加在libvirtd守護程式,用netstat檢視libvirt-sock是否在配置檔案制定位置偵聽。

使用java的libvirt開發API時注意:

* 在使用java程式編寫libvirt應用時,當虛機處於pmsuspended狀態時是無法獲取domainInfo資訊,會出現陣列越界的錯誤提示。

* 使用attachDevice方法新增裝置時要注意,flag=0時,表示執行結果影響當前狀態,當前狀態為執行狀態,則只有執行時存在,當前狀態為關閉狀態則影響關機配置檔案。flag=1時,表示影響執行時狀態,執行此方法時,虛機必須處於Active狀態。flag=2時,表示影響虛機持久配置檔案,但是在qemu環境中flag=1會不支援,程式會爆出不支援熱插拔,可以使用domainUpdateDeviceFlags進行換盤操作。 更新持久配置檔案後,需要關機重新啟動以使新配置生效。domain.getXMLDesc()方法獲取的是虛機的執行時配置,而不是持久化配置,所以會看到被刪除的裝置仍然還在。

* 使用DomainUpdateDeviceFlags()方法更新虛機配置時,使用updateFlags 0或1都會更新處於Active狀態的虛機執行時配置,在虛機重啟後會保持這種更新,因為重啟虛機不會重新載入持久化配置,關機之後重新開機,配置會還原為原先配置。 當使用updateFlags為2時,會出現無法更新的情況,雖然方法會執行成功,但無法更新持久配置檔案。在關機狀態下,使用updateFlags=1時,會報錯,因為更新Live狀態只能在domain的active狀態下執行。

* 需要注意的是Libvirt不支援cdrom、floppydisk驅動器的熱插拔,使用attachDevice()方法時,制定flags為0或1時,某些裝置型別如CDROM對執行時修改可能會返回失敗,原因是hypervisor底層驅動不支援。如果對正在進行塊複製的裝置進行detach()方法操作,hypervisor可能會阻止detach()的操作,在這種情況下,需要先使用domainBlockJobAbort()方法先停止該複製操作即可。

* 根據hypervisor和裝置型別的不同,在一個處於active狀態的domain中去除一個裝置的操作可能是非同步執行的,也就是說,當你執行detach()方法時,僅僅是請求去除一個裝置,實際去掉此裝置的時間可能是之後的一段時間,這是根據虛擬層與客戶os配合完成的。這往往容易被忽略,因為有時會看到在配置檔案中此裝置已經被刪除了,但hypervisor可能還沒有真正刪除這個裝置,這可能會導致某些後續操作的失敗。想要檢查裝置是否真的被成功刪除了,要麼重新使用domainGetXMLDesc()方法,要麼為DOMAIN_EVENT_ID_DEVICE_REMOVED增加一個事件處理器,如果當detachDeviceFlags()方法返回時,裝置已經被刪除,事件會在API CALL結束之前觸發。為了幫助現有的客戶端在大多數情況下更好的工作,這個API會嘗試把在請求之後過了一段時間才完成的非同步刪除操作轉變為同步刪除操作,換句話說,API在非同步操作的情況下會等待一會兒來讓刪除操作得以完成。 注意,熱插拔裝置不會保持,一旦domain進入S4狀態即hibernation狀態,除非同樣修改了domain的持久配置檔案。

* 使用setMaxMemory()方法設定虛機最大記憶體時,預設使用的是AFFECT_CURRENT,也就是說當domain關閉時,修改持久化配置檔案,當domain處於active狀態時,修改執行時配置或執行時持久化配置都修改,這個要看hypervisor的行為而定。例如,在libvirt中當domain處於active狀態時,修改最大記憶體時會報錯,必須關閉domain再修改持久化配置。

在使用API開發虛機快照功能時,需要注意如下幾點:

如果某虛機建立快照時使用的是內部快照或系統檢查點,則該虛機所有硬碟都必須建立內部快照,qemu不支援建立混合快照,即一部分硬碟建立內部快照,一部分建立外部快照,當然只讀盤如光碟機預設是不建立快照的。
系統檢查點預設所有可讀寫硬碟使用內部快照(關機狀態下,會忽略disks標籤內容)。

如果在建立快照方法中指定了flags為16(disk-only),則沒有明確指定快照方式的硬碟預設使用外部快照,qemu目前不支援內外部混合快照。
使用系統檢查點快照時,對cpu特性集有要求,當domain配置中cpu特性集有invtsc特性時,在domain執行時執行系統檢查點快照會報錯,解決辦法,去掉invtsc特性或將cpu model改為custom。
當執行系統級快照時(開機狀態下),如果配置檔案標籤制定snapshot=internal則硬碟快照預設也會使用internal方式執行,反之如果標籤制定為external則硬碟預設也會使用external方式執行。這是因為qemu快照機制目前不支援內外部快照混合模式,libvirt內部機制會自動把硬碟快照方式調整為與記憶體相同方式。
使用外部快照要注意,執行外部快照檔案是指向原硬碟快照(base 盤)的從映象,執行完外部快照後,libvirt會將domain配置檔案中的硬碟映象改為新建立的外部快照檔案,這樣此檔案可以用來儲存執行快照後所有差異化內容,所以,libvirt不允許直接刪除外部快照。 外部快照會與之前建立的外部快照形成一個差異儲存鏈,內部快照不會與外部快照形成一個差異儲存連。建立快照之後,快照配置檔案會包含虛機配置檔案的全部內容用於還原。

外部快照                               內部快照

win7------------------------->win7_snap-------------------->win7_snap2(包含在win7_snap檔案內部)

vm                                     外部                          vm

                                 |--------------------->win7_snap3

                                                                     vm

win7是win7_snap的backingstore,win7_snap2快照存在於win7_snap檔案中,win7_snap是win7_snap3的backingstore,記憶體外部快照可重複覆蓋。 * 在關機狀態下,執行任何快照,不能包含有記憶體狀態,需要把記憶體snapshot設定為no,因為關機狀態下沒有記憶體執行狀態,記憶體都清空了。 *建立系統檢查點時,在關機狀態下,預設建立內部快照,而且必須使用內部快照,建立外部快照會報錯,但是使用disk-only模式快照,則在關機狀態下允許建立外部快照同時也允許建立內部快照。外部快照聲稱的預設檔名稱為原始硬碟映象.快照名稱 * 使用disk-only方式針對正在執行的虛機建立快照,必須使用external方式,並且標籤的snapshot必須為no,使用內部快照會報錯,內部快照和系統檢查點快照要求所有硬碟都必須參與執行快照,使用disk-only和external方式並用執行快照才能針對不同硬碟單獨執行快照策略。 * 使用系統檢查點快照方式對處於active狀態的虛機執行快照,快照生成的是內部還是外部取決於memory標籤的snapshot值。 * 使用diskonly模式或關機狀態下建立快照,標籤snapshot必須為no,因為以上兩種快照都無法儲存記憶體狀態。

各種快照模式及虛機狀態的匹配情況:
1.虛機關機狀態,diskonly模式:memory=no(必須),disk可以使用內部或外部快照,並且外部快照可以對每個盤分別定製建立策略,預設建立external快照。
2.虛機執行狀態,diskonly模式:memory=no(必須),disk快照只能使用external模式建立,不支援建立內部快照。
3.系統檢查點,虛機關閉狀態:memory=no(必須),disk快照只能使用內部快照,而且是真對所有硬碟,無法針對每個盤定製快照建立策略。
4.系統檢查點,虛機執行狀態:memory=internal或external,disk快照的建立模式根據記憶體快照建立方式而定,不管內部還是外部快照都只能對所有硬碟建立快照,不支援對每個硬碟定製建立策略。
為什麼快照機制這麼混亂,因為libvirt和qemu對快照機制持有不同觀點,但是那種觀點更好,這是見仁見智的,我們可以根據情況選擇使用。
ps:內部快照優點:不單獨聲稱額外檔案,沒有儲存連(其實是內部後設資料,機制類似),降低了檔案管理複雜度,libvirt對內部快照有良好支援。
ps:內部快照缺點:建立速度較慢,qemu上游較少維護,必須使用qcow2之類支援級聯快照功能的檔案格式。執行時建立快照虛機有明顯停頓感。
ps:外部快照優點:建立速度較快,支援各種原始檔格式(後續快照需使用qcow2之類),在執行時建立客戶機幾乎沒有停頓時間,上游qemu在外部快照開發方面較積極
ps:外部快照缺點:快照多了後會形成大量儲存檔案及儲存連,每一層級都使用cow方式讀寫,嚴重影響效能,檔案管理複雜,libvirt對外部快照支援不太積極。
問答
記憶體快照,互斥特性很多,怎麼在各階段進行特性間的互斥?快照失敗會回退嗎?記憶體複用場景可以做快照嗎?大規格記憶體快照時間規格大約多久?

答:快照建議根據我列出的特性進行選擇,不建議把快照功能做得太多太複雜,快照多了會影響效能,如果必須要做外部快照,因為檔案使用backingstore方式儲存,最好對不用的快照進行commit,記憶體複用可以做快照,大規格記憶體做快照需要定製原始碼做最佳化,其實kvm虛擬化只是給我們一個基本功能,很多功能如果要滿足客戶需求需要對qemu和kvm原始碼進行定製開發。

SPICE有探測識別USB裝置的功能嗎?就是在宿主機的USB介面上插上USB裝置之後,KVM虛擬機器能夠探測到嗎?

答:spice的usb裝置識別指的是將終端機上連線的裝置識別為虛機上裝置的功能,這是有spice的一個子功能usb redirect實現,至於宿主機外設,這是對qemu配置的問題。

原文來自:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2911538/,如需轉載,請註明出處,否則將追究法律責任。

相關文章