1.spice介绍

1.1 spice简介

spice是由Qumranet开发的开源网络协议,2008年红帽收购了Qumranet获得了这个协议。SPICE是红帽在虚拟化领域除了KVM的又一“新兴技术”,它提供与虚拟桌面设备的远程交互实现.

目前,spice主要目标是为qemu虚拟机提供高质量的远程桌面访问,它致力于克服传统虚拟桌面的一些弊端,并且强调用户体验

spice包含有3个组件:

SPICE Driver:SPICE驱动器 存在于每个虚拟桌面内的组件

SPICE server:SPICE服务器 存在于红帽企业虚拟化Hypervisor内的组件

SPICE Client: SPICE客户端 存在于终端设备上的组件,可以是瘦客户机或专用的PC,用于接入每个虚拟桌面。

这三个组件协作运行,确定处理图形的最高效位置,以能够最大程度改善用户体验并降低系统负荷。如果客户机足够强大,SPICE向客户机发送图形命 令,并在客户机中对图形进行处理,显著减轻服务器的负荷。另一方面,如果客户机不够强大,SPICE在主机处理图形,从CPU的角度讲,图形处理并不需要 太多费用

以上简介参考http://os.51cto.com/art/201201/311464.htm

1.2 spice架构

Spice agent运行在客户机(虚拟机)操作系统中。Spice server和Spice client利用spice agent来执行一些需要在虚拟机里执行的任务,如配置分辨率,另外还有通过剪贴板来拷贝文件等。从上图可以看出,Spice client与server与Spice Agent的通信需要借助一些其他的软件模块,如在客户机里面,Spice Agent需要通过VDIPort Driver与主机上 QEMU的VDIPort Device进行交互,他们的交互通过一种叫做输入/输出的环进行。Spice Client和Server产生的消息被写入到设备的输出环中,由VDI Port Driver读取;而Spice Agent发出的消息则通过VDI Port Driver先写入到VDI Port Device输入环中,被QEMU读入到Spice server的缓冲区中,然后再根据消息决定由Spice Server直接处理,还是被发往Spice Client中。

以上参考http://blog.csdn.net/hbsong75/article/details/9465683

1.3 spice的不足

  • spice目标是提供一个高性能,高用户体验的远程桌面连接,就像本地桌面一样展现给用户. 其目前实现的功能有usb重定向,音视频传输,剪贴板,鼠标同步,2D图形支持,任意调整分辨率(qxl驱动)等

  • spice目前不支持虚拟机中的3D效果,对于windows7系统虚拟机,其aero桌面特效也无法启用,因为spice使用远程连接,所以其高度依赖网络,如果网络环境不好,使用起来将会是一间很痛苦的事情

2 spice安装配置

2.1 系统准备

系统版本

  • RHEL6

  • IP:192.168.11.166

安装KVM软件

#安装kvm/qemu工具,以及virt-manager,libvirtdyum install qemu-kvm qemu-kvm-tools virt-manager libvirt libvirt-devel libvirt-client virt-manager virt-viewer

系统环境检查

  • 运行命令 lsmod | grep kvm 检查 KVM 模块是否成功安装。如果有输出结果,那么 KVM 模块已成功安装

  • 需要服务器硬件支持虚拟化技术(Intel VT-d,AMD-V)。可以使用如下命令检查,有输出信息表示支持

egrep "(vmx|svm)" --color /proc/cpuinfo

2.2 服务器上安装spice-server

yum -y install spice-protocol spice-server xorg-x11-drv-qxl spice-glib

2.3 客户端安装spice client

centos客户端安装virt-viewer

yum -y install virt-viewer

windows7客户端安装virt-viewer

下载链接: http://virt-manager.org/download/sources/virt-viewer/virt-viewer-x64-1.0.msi

2.4 新建centos6.4虚拟机

关于virt-manager工具

virt-manager是一个图形化的虚拟机管理工具,它可以方便地创建虚拟机,修改虚拟机配置,添加新设备等. 但是由于其是图形界面管理,所以效率不是很高,而且对网络也有要求. libvirt提供了一个xml文件用来定义虚拟机的配置细节,并且可以通过virsh命令对虚拟机进行管理

编写一个虚拟机的xml文件

如下是一个centos6.4桌面版的xml文件,默认配置

<domain type=‘kvm‘>
  <name>cdesk1</name>
  <uuid>56f6c45d-aa4d-8b23-85d9-87500199f089</uuid>
  <memory unit=‘KiB‘>2097152</memory>
  <currentMemory unit=‘KiB‘>2097152</currentMemory>
  <vcpu placement=‘static‘>2</vcpu>
  <os>
    <type arch=‘x86_64‘ machine=‘rhel6.5.0‘>hvm</type>
    <boot dev=‘hd‘/>
    <bootmenu enable=‘yes‘/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset=‘utc‘/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type=‘file‘ device=‘disk‘>
      <driver name=‘qemu‘ type=‘qcow2‘ cache=‘none‘/>
      <source file=‘/data_lij/vhosts/cdesk1.qcow2‘/>
      <target dev=‘vda‘ bus=‘virtio‘/>
      <address type=‘pci‘ domain=‘0x0000‘ bus=‘0x00‘ slot=‘0x04‘ function=‘0x0‘/>
    </disk>
    <controller type=‘usb‘ index=‘0‘>
      <address type=‘pci‘ domain=‘0x0000‘ bus=‘0x00‘ slot=‘0x01‘ function=‘0x2‘/>
    </controller>
    <interface type=‘network‘>
      <mac address=‘52:54:00:92:32:a9‘/>
      <source network=‘default‘/>
      <model type=‘virtio‘/>
      <address type=‘pci‘ domain=‘0x0000‘ bus=‘0x00‘ slot=‘0x03‘ function=‘0x0‘/>
    </interface>
    <serial type=‘pty‘>
      <target port=‘0‘/>
    </serial>
    <console type=‘pty‘>
      <target type=‘serial‘ port=‘0‘/>
    </console>
    <input type=‘mouse‘ bus=‘ps2‘/>
    <graphics type=‘vnc‘ port=‘-1‘ autoport=‘yes‘ listen=‘0.0.0.0‘>
      <listen type=‘address‘ address=‘0.0.0.0‘/>
    </graphics>
    <video>
      <model type=‘cirrus‘ vram=‘9216‘ heads=‘1‘/>
      <address type=‘pci‘ domain=‘0x0000‘ bus=‘0x00‘ slot=‘0x02‘ function=‘0x0‘/>
    </video>
    <memballoon model=‘virtio‘>
      <address type=‘pci‘ domain=‘0x0000‘ bus=‘0x00‘ slot=‘0x05‘ function=‘0x0‘/>
    </memballoon>
  </devices></domain>

通过xml文件启动虚拟机

#加入virsh管理
virsh define cdesk1.xml
#启动虚拟机
virsh start cdesk1
#查看端口
netstat -ntpl | grep qemu

查看进程

[root@controller2 qemu]# ps -ef | grep qemu
qemu     21866     1 10 19:26 ?        00:00:00 /usr/libexec/qemu-kvm -name cdesk1 -S -M rhel6.5.0 -enable-kvm -m 2048 -realtime mlock=off -smp 2,sockets=2,cores=1,threads=1 -uuid 56f6c45d-aa4d-8b23-85d9-87500199f089 -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/cdesk1.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -boot order=c,menu=on -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/data_lij/vhosts/cdesk1.qcow2,if=none,id=drive-virtio-disk0,format=qcow2,cache=none -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0 -netdev tap,fd=25,id=hostnet0,vhost=on,vhostfd=26 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:92:32:a9,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -vnc 0.0.0.0:0 -vga cirrus -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5

默认情况下,qemu使用vnc建立远程连接,监听地址为0.0.0.0,其端口为自动分配(xml文件中定义graphics type=‘vnc‘ port=‘-1‘, -1表示端口自动分配5900+N)

客户端使用TightVNC工具远程连接

3 启用spice进行远程连接

3.1 修改xml文件,使用spice进行远程连接

首先virsh命令关闭虚拟机

<!--  添加 -->  
 <channel type=‘spicevmc‘>
      <target type=‘virtio‘ name=‘com.redhat.spice.0‘/>
      <alias name=‘channel0‘/>
      <address type=‘virtio-serial‘ controller=‘0‘ bus=‘0‘ port=‘1‘/>
    </channel><!--  修改 -->
    <graphics type=‘spice‘ port=‘5902‘ tlsPort=‘5903‘ autoport=‘yes‘ listen=‘0.0.0.0‘>
      <listen type=‘address‘ address=‘0.0.0.0‘/>
    </graphics>
    <video>
      <model type=‘qxl‘ ram=‘65536‘ vram=‘65536‘ heads=‘1‘/>
      <alias name=‘video0‘/>
      <address type=‘pci‘ domain=‘0x0000‘ bus=‘0x00‘ slot=‘0x02‘ function=‘0x0‘/>
    </video>

3.2 修改xml文件支持音频传输

<sound model=‘ich6‘>
   <alias name=‘sound0‘/>
 </sound>

Linux下model=‘ich6‘,windows下model=‘ac97‘

3.3 使用windows7客户端远程连接

首先启动虚拟机

virsh start cdesk1

使用virt-viewer工具,其支持vnc和spice两种协议,所以这里需要指定使用spice。

3.4 使用virt-manager图形工具配置spice

以上步骤3.1-3.3中是修改xml文件配置spice连接的,也可以使用virt-manager图形界面操作

  • 首先关闭虚拟机

  • 服务器上运行virt-manager命令,打开图形界面(需要开启服务器上的X11转发)

  • 如下图Display中更改Type为spice

  • video中更改Model为qxl,修改完成之后,启动虚拟机

4 提高虚拟机性能(鼠标同步,共享剪贴板,音视频传输等)

我们在客户端使用spice client远程连接虚拟机,如果想要虚拟机中播放的音视频传输到本地客户端,或者在虚拟机和客户机之间共享剪贴板,则需要在虚拟机中安装相应增强工具,对于windows系统和Linux系统,需要安装的增强工具不太一样

 4.1 windows虚拟机配置

windows虚拟机需要安装增强工具spice-guest-tools(类似vmware中的vmtool工具)

下载地址: http://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-0.74.exe

这个软件包包含了一个qxl视频卡驱动,还包括SPICE guest agent,可以实现同步剪贴板,鼠标,任意调整虚拟机分辨率等功能

4.2 Linux虚拟机配置

centos gnome桌面版虚拟机,需要安装以下软件包

yum install xorg-x11-drv-qxl spice-vdagent
#设置开机启动/etc/init.d/spice-vdagentd start
chkconfig spice-vdagentd on

4.3 把虚拟机中的音视频传输到客户端

修改xml文件实现音视频传输

前面是通过在虚拟机xml文件中添加sound标签,实现虚拟机和客户机的音视频传输,也可以使用virt-manager工具

用virt-manager工具添加音频设备

选择Sound的Model(ac97或者ich6)

5.spice的USB重定向

5.1 介绍

使用usb重定向,在client上插入的U盘会被重定向到虚拟机中. 其有两种实现方式,自动重定向(所有插入client中的U盘都被重定向),或者手动选择需要重定向的U盘

USB重定向需要为虚拟机添加USB2 EHCI驱动,以及若干个Spice channels,Spice channels的个数决定了客户端一次可以有多少个USB设备被重定向到guest

更多参考:

http://people.freedesktop.org/~teuf/spice-doc/html/ch02s06.html

http://www.spice-space.org/page/UsbRedir

http://fedoraproject.org/wiki/Features/UsbNetworkRedirection

5.2服务器上安装软件

[root@controller2 vhosts]# rpm -qa | grep usb
usbredir-0.5.1-1.el6.x86_64
libusb-0.1.12-23.el6.x86_64
usbutils-003-4.el6.x86_64
libusb1-1.0.9-0.6.rc1.el6.x86_64

5.3 虚拟机xml文件中添加USB redirection驱动

#首先关闭虚拟机,然后修改其xml文件,添加下面标签
<!-- 移除xml文件中其它的USB设备,然后添加下面的部分 --><controller type=‘usb‘ index=‘0‘ model=‘ich9-ehci1‘/><controller type=‘usb‘ index=‘0‘ model=‘ich9-uhci1‘>
  <master startport=‘0‘/></controller><controller type=‘usb‘ index=‘0‘ model=‘ich9-uhci2‘>
  <master startport=‘2‘/></controller><controller type=‘usb‘ index=‘0‘ model=‘ich9-uhci3‘>
  <master startport=‘4‘/></controller><redirdev bus=‘usb‘ type=‘spicevmc‘/><redirdev bus=‘usb‘ type=‘spicevmc‘/><redirdev bus=‘usb‘ type=‘spicevmc‘/><redirdev bus=‘usb‘ type=‘spicevmc‘/>

1.3中是在xml文件中添加usb驱动,其对应的命令行参数如下(当使用qemu-kvm命令行启动虚拟机时需要):

-device ich9-usb-ehci1,id=usb -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,multifunction=on -device ich9-usb-uhci2,masterbus=usb.0,firstport=2 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4 -chardev spicevmc,name=usbredir,id=usbredirchardev1 -device usb-redir,chardev=usbredirchardev1,id=usbredirdev1 -chardev spicevmc,name=usbredir,id=usbredirchardev2 -device usb-redir,chardev=usbredirchardev2,id=usbredirdev2 -chardev spicevmc,name=usbredir,id=usbredirchardev3 -device usb-redir,chardev=usbredirchardev3,id=usbredirdev3

5.4 客户端配置

客户端连接工具使用virt-viewer

windows7版本的virt-viewer默认不支持USB重定向,需要手动重新编译,Linux下的客户端可以编译源码支持USB重定向

virt-viewer源码: http://virt-manager.org/download/sources/virt-viewer/virt-viewer-1.0.tar.gz

virt-viewer windows客户端: http://virt-manager.org/download/sources/virt-viewer/virt-viewer-x64-1.0.msi

6 spice使用TLS和密码实现双重认证

默认情况下,客户端和虚拟机传输的数据是未加密的,下面的步骤中将使用TLS加密客户端和虚拟机之间的连接

6.1 生成CA证书,服务器证书

6.1.1 创建证书存放目录
cd /etc/pkimkdir libvirt-spice
cd libvirt-spice
6.1.2 使用下面脚本创建证书

注意:脚本生成的ca-cert.pem文件,最后输出的变量”SUBJECT“值都需要拷贝到客户端

#!/bin/bash
 
SERVER_KEY=server-key.pem
# creating a key for our caif [ ! -e ca-key.pem ]; then
 openssl genrsa -des3 -out ca-key.pem 1024fi# creating a caif [ ! -e ca-cert.pem ]; then
 openssl req -new -x509 -days 1095 -key ca-key.pem -out ca-cert.pem  -subj "/C=IL/L=Raanana/O=Red Hat/CN=my CA"fi# create server keyif [ ! -e $SERVER_KEY ]; then
 openssl genrsa -out $SERVER_KEY 1024fi# create a certificate signing request (csr)if [ ! -e server-key.csr ]; then
 openssl req -new -key $SERVER_KEY -out server-key.csr -subj "/C=IL/L=Raanana/O=Red Hat/CN=my server"fi# signing our server certificate with this caif [ ! -e server-cert.pem ]; then
 openssl x509 -req -days 1095 -in server-key.csr -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pemfi
 # now create a key that doesn‘t require a passphraseopenssl rsa -in $SERVER_KEY -out $SERVER_KEY.insecuremv $SERVER_KEY $SERVER_KEY.securemv $SERVER_KEY.insecure $SERVER_KEY
 
# show the results (no other effect)
openssl rsa -noout -text -in $SERVER_KEY
openssl rsa -noout -text -in ca-key.pem
openssl req -noout -text -in server-key.csr
openssl x509 -noout -text -in server-cert.pem
openssl x509 -noout -text -in ca-cert.pem
 
# copy *.pem file to /etc/pki/libvirt-spiceif [[ -d "/etc/pki/libvirt-spice" ]]then
 cp ./*.pem /etc/pki/libvirt-spice
else
 mkdir /etc/pki/libvirt-spice
     cp ./*.pem /etc/pki/libvirt-spice
fi
 
# echo SUBJECT
echo "SUBJECT is:" \" `openssl x509 -noout -text -in server-cert.pem | grep Subject: | cut -f 10- -d " "` \"

6.2虚拟机加载证书

#默认不管vnc还是spice都是监听在127.0.0.1上,这样肯定不能从网络中访问

#下面的设置默认会使所有的虚拟机开启两个端口,一个普通端口,一个为使用ssl加密的安全端口,并且监听所有地址

#vim /etc/libvirt/qemu.conf
spice_listen="0.0.0.0"spice_tls=1spice_tls_x509_cert_dir="/etc/pki/libvirt-spice"
 #下面的为默认密码认证,仅当虚拟机xml文件中没有设置passwd参数时才生效,为了能够使用不同密码,这里不启用,改在xml文件中设置密码
#spice_password = "123456"
 #重启libvirtd加载证书/etc/init.d/libvirtd restart

6.3 在虚拟机xml文件中设置密码及安全端口

xml文件中安全端口可以有不同设置方法

A <graphics type=‘spice‘ autoport=‘yes‘ listen=‘0.0.0.0‘ passwd=‘123456‘>     B <graphics type=‘spice‘ port=‘5901‘ autoport=‘no‘ listen=‘0.0.0.0‘ passwd=‘123456‘>C <graphics type=‘spice‘ tlsPort=‘-1‘ autoport=‘no‘ listen=‘0.0.0.0‘ passwd=‘123456‘>

A: 每台虚拟机自动配置两个端口,普通端口和安全端口,并且端口号自动分配(5900+N)

B: 不自动配置端口,手动指定一个普通端口,不开启安全端口

C: 不自动配置端口,只开启安全端口,并且安全端口自动分配(5900+N)

passwd=123456  设置使用密码认证,即客户端连接虚拟机时,会弹出密码验证窗口

6.4 windows客户端中使用spice加密连接

6.4.1 拷贝ca-cert.pem证书

拷贝服务器上脚本生成的ca-cert.pem文件到windows下某个目录,比如 F:\files\ca\

6.4.2 windows中添加环境变量
=IL, L=Raanana, O=Red Hat, CN=my server  

#(变量值为脚本最后输出内容),添加环境变量不是必须的操作,是为了下面能够使用%SUBJECT%这个变量
6.4.3 在cmd中测试连接

打开cmd, 进入remote-viewer.exe程序所在目录,默认为 C:\Program Files\VirtViewer\bin

#运行命令
remote-viewer.exe --spice-ca-file F:\ca\ca-cert.pem spice://192.168.11.166?tls-port=5905 --spice-host-subject="%SUBJECT%"

6.5 Linux客户端中使用spice加密连接

首先安装virt-viewer客户端

  virt--viewer --spice-ca- ca-cert.pem --spice-host-subject  spice:
#也可以把‘C=IL,L=Raanana,O=Red Hat,CN=my server‘部分设置为一个全局环境变量SUBJECT,以简化命令

7 spice的多客户端支持

7.1 多显示器支持

spice允许客户端使用多个显示器连接到同一台虚拟机,为了实现这个功能,虚拟机必须配置有多个qxl设备驱动(对于Windows虚拟机),或者有一个配置为支持多个heads的qxl设备驱动(Linux虚拟机)

为了支持多显示器,必须为虚拟机配置qxl驱动,虚拟机中也需要安装qxl驱动支持(xorg-x11-drv-qxl),参考http://www.spice-space.org/download.html中guest部分

7.1.1 Linux虚拟机配置

对于Linux虚拟机,配置好qxl驱动之后,默认会启用多显示器支持.如果Linux系统版本过旧,可以参考这个http://hansdegoede.livejournal.com/12969.html

技术分享

7.1.2 windows虚拟机配置

修改xml文件,添加多个video标签,然后重新启动虚拟机

<video>
    <model type=‘qxl‘>
</video>
<video>
    <model type=‘qxl‘>
</video>

7.2 多客户端支持

多客户端支持允许多个用户连接同一台虚拟机,参考http://www.spice-space.org/page/Features/MultipleClients

7.2.1 使用qemu-kvm命令行

对于使用qemu-kvm命令行创建的虚拟机,只需要给宿主机添加下面的环境变量

export SPICE_DEBUG_ALLOW_MC=1

添加之后,用qemu-kvm命令创建虚拟机,可以看到输出中多了一行,表示spice已经启用多客户端支持

技术分享

7.2.2 使用libvirt
对于使用libvirt管理的虚拟机,添加上面的环境变量不生效,需要修改虚拟机xml文件
使用qemu:commandline标签传递变量"SPICE_DEBUG_ALLOW_MC"值给虚拟机
<!-- 更改第一行为下面 --><domain type=‘kvm‘ xmlns:qemu=‘http://libvirt.org/schemas/domain/qemu/1.0‘><!-- 在下面类似位置添加 --><domain>
  <devices>
  ...  </devices>
  <qemu:commandline>
    <qemu:env name=‘SPICE_DEBUG_ALLOW_MC‘ value=‘1‘/>
  </qemu:commandline></domain>

添加上面的之后,重启虚拟机,即可

如果要验证添加的参数是否生效,可以在启动虚拟机(cos_v1)时,查看虚拟机日志输出

tail -f /var/log/libvirt/qemu/cos_v1.log
#下面是输出2014-12-26 10:06:10.763+0000: starting up
LC_ALL=C PATH=/sbin:/usr/sbin:/bin:/usr/bin HOME=/root USER=root LOGNAME=root QEMU_AUDIO_DRV=spice SPICE_DEBUG_ALLOW_MC=1 /usr/libexec/qemu-kvm -name cos_v1 -S -M rhel6.5.0 ...
...char device redirected to /dev/pts/7((null):29858): Spice-Warning **: reds.c:4010:do_spice_init: spice: allowing multiple client connections (crashy)    #这行表明添加成功