導讀 | 你們好,本次肖力分享的主題是KVM&Libvirt基本概念及開發雜談,內容有些凌亂鬆散,主要基於本身早期整理的筆記內容和實踐感悟,有些內容不免有失偏頗,望見諒。前面先介紹下須要瞭解的基本知識,大部份內容在肖力著做中都有更詳細的解釋,可閱讀參考。 |
KVM包含:php
1.內核模塊kvm.ko,用於核心虛擬框架。 2.包含與處理器相關的模塊kvm-intel.ko,kvm-amd.ko 3.kvm須要使用通過修改定製的qemu軟件提供用戶空間工具 *內核組件已經包含在Linux內核2.6.20中了 *部分操做系統在kvm中運行仍然存在某些問題,能夠查看KVM官網提供的操做系統運行兼容性狀態列表
使用KVM的前提條件:java
1.qemu-kvm-release.tar.gz 2.kvm-kmod-release.tar.bz2,本身編譯內核模塊的須要這個東東 3.支持VT技術的Intel處理器或支持SVM技術的AMD處理器
使用qemu前提條件:node
1.zlib庫及頭文件 2.sdl庫及頭文件 3.alsa庫及頭文件,這個是用來提供虛擬化音頻相關功能,默認是禁用的,如今不知道什麼狀態了,可使用--enable-alsa來啓用 4.gnutls庫及頭文件,可選的VNC TLS支持,默認此功能是開啓的,能夠用--disable-vnc-tls關閉 5.kernel頭文件 *建立,安裝,運行KVM虛機,須要使用QEMU提供的用戶空間工具,之前是分開發布的,如今分支已經合併,成爲qemu-kvm。 *libvirt爲用戶提供了同不一樣虛擬化技術交互的抽象接口。
libvirt基本理念:python
1.同linux虛擬化技術進行交互 2.免費,自由 3.穩定的C語言API 4.其餘通用語言的綁定開發接口(java,python,perl,php。。。) 5.針對DMTF虛擬風格 6.QMF代理,用於AMQP、QPID信息系統
libivrt支持度:linux
虛擬技術:kvm/qemu, XEN, LXC, OpenVZ, UserModeLinux, VB, ESX, HyperV, PowerVM, Parallels, Bhyreios
虛擬網絡:橋接,NAT,VEPA,VNLINKc++
存儲: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虛擬環境,相似數據庫的鏈接字符串ubuntu
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配置的問題。