標籤:windows kvm ide virtio cloudstack
前言
本文的目的是為瞭解決在使用CloudStack(CloudPlatform)時,基於KVM虛擬化平台,Windows虛擬機器的效能低下的問題。
此效能,主要指磁碟IO和網卡效能。
相關文檔
由於CS文檔中,只強調了PV這個概念,根據PV模式區分使用不同的硬體介面類型。所以收集部分連結給大家掃盲。
關於PV(Paravirtualization-半虛擬化)模式的概念,請參閱:
http://www.rackspace.com/knowledge_center/article/choosing-a-virtualization-mode-pv-versus-pvhvm
http://wiki.xenproject.org/wiki/Paravirtualization_%28PV%29
http://zh.wikipedia.org/wiki/%E8%99%9A%E6%8B%9F%E5%8C%96
http://www.ibm.com/developerworks/cn/cloud/library/cl-hypervisorcompare-kvm/
另外,關於virtio,可以查看如下連結:
http://www.linux-kvm.org/page/Virtio
http://smilejay.com/2012/11/virtio-overview/ (這個值得不懂kvm的兄弟一看)
背景
在兩個項目匯總(CS+KVM),客戶均提到Windows效能不足,但至於哪方面效能,不細說,太多。使用者反饋就一句話:虛擬機器運行太慢。
十幾台刀片伺服器,30T SAN儲存,將近萬G記憶體。才跑了100來個虛擬機器,還慢,像話嘛。
得了,慢,咱就得找原因。
初步分析
我這人比較膚淺,首先想到的就是磁碟IO不行,這個是最直接讓客戶覺得系統慢的原因(排除記憶體不足的問題)。
經過檢查,發現:
1.使用CS建立的Windows虛擬機器,系統硬碟的磁碟類型為IDE(你拿IDE介面跑Windows 2008R2,還要求效能,這像話嘛)。除系統硬碟之外所建立的所有資料盤,介面類型全部為VirtIO。
至於如何查看硬碟介面類型,可以在系統中,開啟裝置管理員-查看磁碟機類型。或者在kvm主機中,使用 ”virsh edit 虛擬機器名稱“ 尋找Disk相關配置。直接使用virt-manager也可以。
2.使用CS建立的Linux(常見發行版)虛擬機器,系統硬碟和資料盤硬碟介面類型全部為VirtIO。
到這裡,我將問題歸結為:在CS中,基於KVM平台,所建立的Windows虛擬機器,系統硬碟磁碟介面類型為IDE,這是導致效能慢的主要原因。最優磁碟介面類型應該為VirtIO。
註:
有人會說你這太武斷了,嗯,我上家公司基於KVM做案頭虛擬化產品,當時跟VMware View,XenDesktop做效能對比也不相上下(均是預設配置),跑Win7和Win2008,在負載一般的情況下,很少出現運行慢的問題。所以,基於KVM平台,跑Windows系統,效果並不會太差。當然了,除了硬碟介面使用了VirtIO,也做了其他調優。
但,瞭解KVM的朋友,應該知道KVM+VirtIO是一對好基友。至於IDE和VirtIO的效能測試對比,稍後有機會我再拿出具體測試資料。
問題視乎變得簡單了,將系統硬碟的IDE介面,換成VirtIO介面即可。
再來看下官方文檔中指出,哪些系統類別型,預設的系統硬碟介面類型為VirtIO:
(僅KVM) If you choose an OS that is PV-enabled, the VMs created from this ISO will have a SCSI (virtio) root disk. If the OS is not PV-enabled, the VMs will have an IDE root disk. The PV-enabled types are:
Fedora 13
Fedora 12
Fedora 11
Fedora 10
Fedora 9
Other PV
Debian GNU/Linux
CentOS 5.3
CentOS 5.4
CentOS 5.5
Red Hat Enterprise Linux 5.3
Red Hat Enterprise Linux 5.4
Red Hat Enterprise Linux 5.5
Red Hat Enterprise Linux 6
由上面的資訊得知:啟用了PV模式的作業系統,根磁碟,也就是系統磁碟,預設會使用VirtIO模式,而沒用啟用PV模式的作業系統,將會預設使用IDE模式。
細心的你也會發現,上面的列表中,幾乎全部是Linux系統,除了"Other PV"這個怪胎(其實還有"Windows PV"啦,至於為啥,也許是寫文檔的人懶,也許是,稍後再說)。
為啥幾乎都是Linux系統,官方說了這樣一句話:
(僅KVM)All VMs are required to support the virtio drivers. These drivers are installed in all Linux kernel versions 2.6.25 and greater. The administrator must set CONFIG_VIRTIO_BALLOON=y in the virtio configuration.
所有的虛擬機器都要求支援virtio驅動,而Linux平台的virtio驅動已經整合到2.6.25或更高版本的核心中。也就是說Linux可以直接識別virtio介面裝置。而virtio是一個在hypervisor之上的抽象API介面,是一個半虛擬化驅動,virtio與hypervisor協作工作,用於提供出色的效能。也就是說,virtio不是標準介面類型。你買硬碟的時候有看到過virtio硬碟嘛。所以,Windows中不整合此驅動,也在情理之中。這也是為啥沒有啟用PV模式的虛擬機器的系統磁碟介面類型為IDE。
那是不是Windows就不能使用VirtIO了?當然不是。人家說了嘛,只要啟用了PV模式的作業系統,系統磁碟就會是VirtIO。所以CS中提供了2中PV模式的作業系統類型Other PV 和 Windows PV。 其實只有Other PV這一種。因為代碼中,Windows PV最終也是歸類為Other PV。
當然了,Windows 系統中的VirtIO驅動,就需要自己安裝了。
初步解決
到這裡,問題初步已經可以解決了,就是在CS中,將Windows相關的虛擬機器和模版中的作業系統類型,定義為:Windows PV或Other PV。
只要選擇了PV模式的作業系統類型,系統磁碟類型即可使用VirtIO。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/43/A3/wKioL1Pbm3Xxs9MKAACusWfkZhk877.jpg" style="float:none;" title="pv-mode-1.png" alt="wKioL1Pbm3Xxs9MKAACusWfkZhk877.jpg" />
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/43/A3/wKiom1PbmlywrOqBAAEBRUxMzOI423.jpg" style="float:none;" title="pv-mode-2.png" alt="wKiom1PbmlywrOqBAAEBRUxMzOI423.jpg" />
如果這樣你以為就該高興了,那我就要呵呵了。
本著 no zuo no die , why you try的原則,我還是要找到根本解決方案。
深入分析
首先想想為啥CS中定義了啟用PV和不啟用PV模式的作業系統,為啥CS中基於KVM平台的windows虛擬機器系統磁碟不直接使用virtio介面類型。而除系統磁碟以外的第二塊,第三塊磁碟卻使用virtio介面類型?難道CS的開發人員不知道這樣效能會有質的提升嗎?
我認為:
1.啟用PV和不啟用PV,在CS代碼層面,最根本要解決的還是區分根磁碟介面類型使用IDE或VirtIO(針對KVM平台)
2.KVM平台中windows虛擬機器系統磁碟不直接使用virtio介面而是使用IDE,實際上是為了方便使用CS部署KVM虛擬機器的人員。為啥,如果windows虛擬機器預設也使用virtio介面類型的磁碟機,那你會碰到什麼問題?你會發現虛擬機器啟動失敗。或者當你在從ISO安裝一台windows虛擬機器時發現到磁碟機那一步,windows找不到磁碟機。這個時候你會怎麼辦?
安裝 vista,win7,2008.win8 等高版本windows時,在硬碟那一步驟中,允許你通過ISO載入磁碟機驅動。確實也提供了virtio的iso格式驅動安裝包,這個時候你可以彈出安裝iso,然後附加virtio的驅動iso,安裝完驅動以後再彈出該iso,再次附件系統iso。好了,系統可以識別到磁碟機了。那2003呢,xp呢,必須要插入磁碟片安裝驅動,你咋辦?CS提供軟碟機了不?
3.系統硬碟為IDE介面,其他盤均為virtio,如上面所說。先保證你可以把系統安裝好,再來裝virtio驅動。不管xp,2003,還是win7,2008,windows系統都能識別到IDE介面的硬碟吧,等你安裝好系統,再為資料盤安裝virtio驅動。
4.開發人員正是基於如上考慮,才這麼設計的吧。當然你可以在安裝完virtio的磁碟和網卡驅動後,關機,把虛擬機器作業系統類型改為Windows PV模式,再開機,那虛擬機器就會使用virtio作為系統磁碟介面類型。或者你可以把安裝好virtio驅動的虛擬機器轉化為模版,並設定作業系統類別型為windows pv,那麼以後使用該模版建立的虛擬機器,都不用再擔心驅動問題。
5.當然,如果你在CS之外,已經做好了KVM平台的windows虛擬機器模版,並直接加入了virtio的驅動,然後匯入CS。然後這個模版的作業系統類型,你也需要設定為Windows PV模式。
但,我目前所在的項目中,不太方便使用將虛擬機器或模版的作業系統類型修改為Windows PV的方式。
一來虛擬機器多了,統計不方便,所有的windows虛擬機器都是windows pv模式。。。二來,本著打破沙鍋的精神,從代碼層面,直接找到根源,並修改之。這樣就不用設定煩人的Windows PV了。
當然,前提是,我的模版中,已經加入了VirtIO的所有驅動(磁碟機+網卡)
解析代碼:
在CS官方的github https://github.com/apache/cloudstack
搜尋如下關鍵字: vritio,windows pv,other pv,ide 等等,自由發揮。
經過一番研究,找到如下兩個檔案:
https://github.com/apache/cloudstack/blob/afc188cb5c72e316975799c95529e8692ddcb94b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java
https://github.com/apache/cloudstack/blob/7542ffc48282ff703fdb586ce447091260ae3c02/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
1.首先來看KVMGuestOsMapper.java , 定義了kvm平台中,支援的作業系統列表:
public class KVMGuestOsMapper { private static final Logger s_logger = Logger.getLogger(KVMGuestOsMapper.class); private static Map<String, String> s_mapper = new HashMap<String, String>(); static { ...... s_mapper.put("Windows Server 2008 (64-bit)", "Windows Server 2008"); s_mapper.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008"); s_mapper.put("Windows XP (64-bit)", "Windows XP"); s_mapper.put("Windows NT 4", "Windows NT"); s_mapper.put("Windows 3.1", "Windows 3.1"); s_mapper.put("Windows PV", "Other PV"); s_mapper.put("FreeBSD 10 (32-bit)", "FreeBSD 10"); s_mapper.put("FreeBSD 10 (64-bits", "FreeBSD 10"); s_mapper.put("Other PV (32-bit)", "Other PV"); s_mapper.put("Other PV (64-bit)", "Other PV"); ...... }
可以看到,此表為作業系統類型對應關係,s_mapper.put中,有兩個欄位: s_mapper.put(作業系統版本,作業系統類型);
一個作業系統類型中,包括多個作業系統版本,注意我們說過的Windows PV,也被歸類為Other PV。
2.再來查看LibvirtComputingResource.java檔案。
尋找virtio看到如下資訊:
做了一個判斷,如果作業系統類型屬於GuestPVEnabled,則返回磁碟bus為VIRTIO,如果不屬於,則使用IDE。
private DiskDef.diskBus getGuestDiskModel(String platformEmulator) { if (isGuestPVEnabled(platformEmulator)) { return DiskDef.diskBus.VIRTIO; } else { return DiskDef.diskBus.IDE; } }
然後再尋找GuestPVEnabled,尋找到一個類,該類型中,定義了,那些系統類別型屬於GuestPVEnabled,可以看到大部分linux系統和Other PV被歸類為GuestPVEnabled:
boolean isGuestPVEnabled(String guestOSName) { if (guestOSName == null) { return false; } if (guestOSName.startsWith("Ubuntu") || guestOSName.startsWith("Fedora 13") || guestOSName.startsWith("Fedora 12") || guestOSName.startsWith("Fedora 11") || guestOSName.startsWith("Fedora 10") || guestOSName.startsWith("Fedora 9") || guestOSName.startsWith("CentOS 5.3") || guestOSName.startsWith("CentOS 5.4") || guestOSName.startsWith("CentOS 5.5") || guestOSName.startsWith("CentOS") || guestOSName.startsWith("Fedora") || guestOSName.startsWith("Red Hat Enterprise Linux 5.3") || guestOSName.startsWith("Red Hat Enterprise Linux 5.4") || guestOSName.startsWith("Red Hat Enterprise Linux 5.5") || guestOSName.startsWith("Red Hat Enterprise Linux 6") || guestOSName.startsWith("Debian GNU/Linux") || guestOSName.startsWith("FreeBSD 10") || guestOSName.startsWith("Other PV")) { return true; } else { return false; }
徹底解決:
由此,我們有思路了,修改isGuestPVEnabled類(LibvirtComputingResource.java),或修改作業系統對應關係(KVMGuestOsMapper.java )。
但,修改這兩個檔案,效果不一樣:
1.如果修改LibvirtComputingResource.java檔案中的isGuestPVEnabled類,在該類中,添加作業系統類型。注意,是作業系統類型,而並非作業系統版本。比如添加windows 2008 作業系統所有版本均為PV模式,要加入guestOSName.startsWith("Windows Server 2008"),這樣的話,2008下面的所有版本,均應用PV設定。
2.如果修改KVMGuestOsMapper.java ,可以將其中一個作業系統版本,定義為PV模式。例如,將2008 R2定義為PV模式,
將:
s_mapper.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008");
修改為:
s_mapper.put("Windows Server 2008 R2 (64-bit)", "Other PV");
這樣,不會影響Windows Server 2008 (32-bit)和Windows Server 2008 (64-bit)版本。
修改完畢後,需要將該檔案編譯(貌似需要將CS代碼全部編譯一遍,編譯單個檔案失敗)。會得到LibvirtComputingResource.class或KVMGuestOsMapper.class檔案。
然後使用winrar 等工具開啟KVM節點中:/usr/share/cloudstack-agent/lib/cloud-plugin-hypervisor-kvm-4.2.1.jar 檔案,將得到的class檔案替換至\com\cloud\hypervisor\kvm\resource目錄中的舊檔案。儲存。
然後再將修改後的jar檔案替換回KVM主機,重啟cloudstack-agent服務。然後建立新的Windows Server 2008 R2 (64-bit)虛擬機器,會發現預設使用virtio磁碟機和網卡適配器。
已經存在的Windows Server 2008 R2 (64-bit)虛擬機器,需要關機,再開機。才會應用virtio配置。注意在KVM虛擬化中,虛擬機器的關閉,再啟動和重啟是有區別的。
此方法由於直接修改代碼,將需要的作業系統類型或具體版本加入GuestPVEnabled類中,所以無需在CS中指定作業系統類型為Windows PV。從根本上解決該問題。
帶來的弊端:
每次升級,都需要編譯替換該檔案,除非使用自己編譯的安裝包進行安裝。
本文出自 “systems” 部落格,請務必保留此出處http://systems.blog.51cto.com/2500547/1533981