设为首页 收藏本站
查看: 1639|回复: 0

[经验分享] 更改CloudStack中KVM平台的Windows虚拟机默认磁盘类型为VirtIO

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-10-10 09:24:14 | 显示全部楼层 |阅读模式

前言


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


DSC0000.jpg


DSC0001.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(&quot;Windows Server 2008 (64-bit)&quot;, &quot;Windows Server 2008&quot;);
s_mapper.put(&quot;Windows Server 2008 R2 (64-bit)&quot;, &quot;Windows Server 2008&quot;);
s_mapper.put(&quot;Windows XP (64-bit)&quot;, &quot;Windows XP&quot;);
s_mapper.put(&quot;Windows NT 4&quot;, &quot;Windows NT&quot;);
s_mapper.put(&quot;Windows 3.1&quot;, &quot;Windows 3.1&quot;);
s_mapper.put(&quot;Windows PV&quot;, &quot;Other PV&quot;);
s_mapper.put(&quot;FreeBSD 10 (32-bit)&quot;, &quot;FreeBSD 10&quot;);
s_mapper.put(&quot;FreeBSD 10 (64-bits&quot;, &quot;FreeBSD 10&quot;);
s_mapper.put(&quot;Other PV (32-bit)&quot;, &quot;Other PV&quot;);
s_mapper.put(&quot;Other PV (64-bit)&quot;, &quot;Other PV&quot;);
......
}
  

可以看到,此表为操作系统类型对应关系,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(&quot;Ubuntu&quot;) || guestOSName.startsWith(&quot;Fedora 13&quot;) ||
guestOSName.startsWith(&quot;Fedora 12&quot;)|| guestOSName.startsWith(&quot;Fedora 11&quot;) ||
guestOSName.startsWith(&quot;Fedora 10&quot;) || guestOSName.startsWith(&quot;Fedora 9&quot;) ||
guestOSName.startsWith(&quot;CentOS 5.3&quot;) || guestOSName.startsWith(&quot;CentOS 5.4&quot;) ||
guestOSName.startsWith(&quot;CentOS 5.5&quot;) || guestOSName.startsWith(&quot;CentOS&quot;) ||
guestOSName.startsWith(&quot;Fedora&quot;) ||
guestOSName.startsWith(&quot;Red Hat Enterprise Linux 5.3&quot;) ||
guestOSName.startsWith(&quot;Red Hat Enterprise Linux 5.4&quot;) ||
guestOSName.startsWith(&quot;Red Hat Enterprise Linux 5.5&quot;) ||
guestOSName.startsWith(&quot;Red Hat Enterprise Linux 6&quot;) ||
guestOSName.startsWith(&quot;Debian GNU/Linux&quot;) ||
guestOSName.startsWith(&quot;FreeBSD 10&quot;) ||
guestOSName.startsWith(&quot;Other PV&quot;))
{
return true;
} else {
return false;
}
}

彻底解决:


由此,我们有思路了,修改isGuestPVEnabled类(LibvirtComputingResource.java),或修改操作系统对应关系(KVMGuestOsMapper.java )。


但,修改这两个文件,效果不一样:


1.如果修改LibvirtComputingResource.java文件中的isGuestPVEnabled类,在该类中,添加操作系统类型。注意,是操作系统类型,而并非操作系统版本。比如添加windows 2008 操作系统所有版本均为PV模式,要加入guestOSName.startsWith(&quot;Windows
Server 2008&quot;),这样的话,2008下面的所有版本,均应用PV设置。


2.如果修改KVMGuestOsMapper.java ,可以将其中一个操作系统版本,定义为PV模式。例如,将2008 R2定义为PV模式,


将:      



1

s_mapper.put(&quot;Windows Server 2008 R2 (64-bit)&quot;, &quot;Windows Server 2008&quot;);


修改为:



1

s_mapper.put(&quot;Windows Server 2008 R2 (64-bit)&quot;, &quot;Other PV&quot;);






这样,不会影响Windows Server 2008 (32-bit)和Windows Server 2008 (64-bit)版本。






修改完毕后,需要将该文件编译(貌&#20284;需要将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。从根本上解决该问题。






带来的弊端:


每次升级,都需要编译替换该文件,除非使用自己编译的安装包进行安装。






转自:http://systems.blog.iyunv.com/2500547/1533981

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-124943-1-1.html 上篇帖子: virtio基本原理(kvm半虚拟化驱动) 下篇帖子: kvm: does not work properly. Using workaround
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表