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


導讀 大家好,本次肖力分享的主題是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@www.xxx.com.cn/system", "wangwang=xxx://xxx@www.xxx.com/system" ] 別名由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配置的問題。

免費提供最新Linux技術教程書籍,為開源技術愛好者努力做得更多更好:https://www.linuxprobe.com/


免責聲明!

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



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