更改CloudStack中KVM平臺的Windows虛擬機默認磁盤類型爲VirtIO

前言

本文的目的是爲了解決在使用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。

wKioL1Pbm3Xxs9MKAACusWfkZhk877.jpg

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。從根本上解決該問題。


帶來的弊端:

每次升級,都需要編譯替換該文件,除非使用自己編譯的安裝包進行安裝。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章