存档

文章标签 ‘kvm’

以只读方式启动虚拟机

2012年9月5日 2 条评论

有时候想在虚拟机里面做一些测试, 又不想让这些测试损坏虚拟机镜像, 这时候就 需要能有一种只读的方式可以用来启动虚拟机.

其实, QEMU 支持各种各样的快照模式, Live Snapshot, Temporary Snapshot 等等. 利用这些模式, 就可以实现上面所说的功能.

创建一个快照

用 qemu-img 指令创建一个原始镜像的快照.

$ qemu-img create -f qcow2 -b vm-base.img vm-append.img

vm-base.img 是原始的镜像, vm-append.img 是快照名字. 之后对 VM 所做的所有修改都只会改变 vm-append.img, vm-base.img 将是只读的.

启动 VM 的时候, 使用创建的这个快照文件即可.

$ qemu-kvm -hda vm-append.img

据我所知, 有些基于 QEMU/KVM 的虚拟化管理平台(e.g. oVirt)有一种叫 stateless 的启动模式, 就是用的上面的方式, 启动虚拟机之前创建一个快照, 虚拟机结束之后再把快照删除.

NB: raw 不支持快照, 所以最好用 qcow2 的镜像格式(qed 也可以)

使用临时快照

用上面的方式来实现 Read-only 略显麻烦, 比如每次启动虚拟机的时候都要手动 创建一个快照, 感觉有点奇怪, 再比如更严重的, QEMU 异常退出怎么办? 快照文件 岂不是会占用而外的空间, 难道需要开启另外一个 daemon 程序监控 QEMU?

好在, QEMU 支持另一种快照模式 – 临时快照, 这种模式不需要经过 1)创建快照, 2)指定快照名称, 3)VM 关机后删除快照就可以实现上述功能.

使用也很简单, 在 QEMU 启动的时候, 增加一个 -snapshot 的参数就可以了.

$ qemu-kvm -hda vm.img -snapshot

下面简叙一下原理: 如果传递了 -snapshot 的参数, 会在初始化 img 的时候创建 一个临时的快照. 并且在具体打开这个 img 的时候把这个文件删除. 请注意, Linux 允许一个文件打开之后删除, 其实只是删除了文件名, 对这类文件的正常操作, 内核会有一个比较优雅的方式来处理.

但是为什么要删除呢而不是让用户visable呢? 在我看来有两点:

  1. 一旦这个进程结束(正常或者是异常), 这个文件的内容马上就被系统回收, 不会造成空间浪费. 感觉是不是比上面的方式优雅?
  2. 处于安全性的考虑, 一旦文件被删除以后, 除了这个进程(VM进程), 其它 是不可能打开和操作这个文件的, 文件的安全性得到保障. 之前在邮件列表 上看到有人提到把这个文件名让用户来设置, 看了它的代码实现后, 发觉 QEMU 的开发者想问题的时候还是很靠谱的.(当然, 这个提议没有通过)

之后, 如果用户想要把快照的内容写回去, QEMU 提供了方式可以写回去的方式, 例如在 nographic 模式下用 Ctrl-a s 把数据写回去, 过多的 write back 不再讨论, 毕竟这里主要研究”只读”.

int get_tmp_filename(char *filename, int size)
{
    int fd;
    const char *tmpdir;
    tmpdir = getenv("TMPDIR");
    if (!tmpdir)
        tmpdir = "/tmp";
    if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
        return -EOVERFLOW;
    }
    fd = mkstemp(filename);
    if (fd < 0 || close(fd)) {
        return -errno;
    }
    return 0;
}
 
/* 检查用户是否启用临时快照 */
if (flags & BDRV_O_SNAPSHOT) {
    ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
}
 
/* 打开文件的时候检查是否是临时快照, 如果是, 把文件删除 */
static int bdrv_open_common(BlockDriverState *bs, const char *filename,
    int flags, BlockDriver *drv)
{
    if (bs->is_temporary) {
        unlink(filename);
    }
}

分类: kvm, QEMU 标签: ,

Nested KVM

2012年8月11日 没有评论

最近同事抱怨开发的机器不够用, 由于是研发 KVM 相关的程序, 所以需要有带有硬件 虚拟化支持的机器. 其实公司服务器很多都是闲置的, 所以只要 Guest 能支持 KVM, 问题就迎刃而解了. 简单的对这个问题做了一下研究.

概念

Nested KVM 指的是在 一个运行的 KVM 虚拟机里面在运行 KVM 虚拟机.

现在 Nested KVM 已经相对稳定了(以前 Nest KVM 甚至不支持 Intel 的 CPU).

实现

配置 KVM 模块

首先需要加载 KVM 模块, 这个地球人都知道, 我就不多说了, 不知道的翻我以前的 BLOG

Intel 的 Nested KVM 配置

检查是否开启了 Nested KVM,

 $ cat /sys/module/kvm_intel/parameters/nested Y 

如果结果是 Y, 那么说明加载 KVM 的时候已经开启了 Nested KVM, 否则使用以 下指令重载 KVM 模块

 $ sudo modprobe -r kvm-intel $ sudo modprobe kvm-intel nested=1 

AMD 的 Nested KVM 配置

AMD 的和 KVM 的类似.

检查是否开启了 Nested KVM,

 $ cat /sys/module/kvm_amd/parameters/nested 1 

如果结果是 1, 那么说明加载 KVM 的时候已经开启了 Nested KVM, 否则使用以 下指令重载 KVM 模块

 $ sudo modprobe -r kvm-amd $ sudo modprobe kvm-amd nested=1 

启动虚拟机

首先说明一点, Nested KVM 在 QEMU 里面经过了一些变化, 见此.

主要是之前 QEMU 有一个选项 -enable-nesting 用来开启这个功能的, 但是有一些 developper 谈到在那个时候 Intel 不支持该功能, 所以建议把这个选项去掉, 如果 是 AMD 的 CPU, 默认开启这个功能.

所以有以下的两种情况:

旧版本的 QEMU/KVM

旧版本的 QEMU/KVM 不支持 Intel 的 CPU, 所以如果是 Intel 的 CPU, 就不用尝试了.

 $ qemu-system-x86_64 enable-kvm -enable-nesting -cpu host -m 512 debian.raw 

请注意 -enable-nesting 参数, 没有也可能开启此功能, 但是不保证成功, 我在 16 核的 AMD 上测试的结果是没有 -enable-nesting 参数是没有此功能的.

PS, 我在 CentOS-6.3(内核版本 2.6.32-220.el6.x86_64) 上测试时, “AMD Opteron(tm) Processor 6128” 启动虚拟机启动失败, 换成 “amd opteron” 就没有问题.

新版的 QEMU/KVM

 $ qemu-system-x86_64 enable-kvm -cpu host -m 512 debian.raw 

新版的 nested KVM 完全不需要 QEMU 作任何修改, 只需要指定 cpu 参数就行了, 这里我选择模拟和 host 一样的 CPU.

分类: kvm, QEMU 标签: ,

USB Redirection

2012年6月29日 没有评论

更多的信息请参考

http://hansdegoede.livejournal.com/

安装必要的包

在我的 Gentoo 上:

 $ emerge libusbx usbredir spice-protocol spice 

libusbx 是 libusb-1.0 的一个fork, 由于将 USB Redirection merge 到 libusb-1.0 非常缓慢(貌似两个开发者有些冲突), libusbx 的开发者把具有 USB Redirection 的 libusb-1.0 重命名为 libusbx 并且 release 了稳定版本.

usbredir 是处理 USB Redirection 的协议

spice-protocol 是 SPICE protocol 的协议头文件

spice 是 SPICE server 和 client

QEMU 编译 USB Redirection 支持

作为 一个 QEMU contributor, QEMU 肯定要自己编译

 $ ./configure --prefix=/home/mathslinux/usr --enable-kvm --enable-debug --enable-werror \ --target-list="x86_64-softmmu" --enable-usb-redir --enable-spice $ make && make install 

以上指令给 QEMU 添加了 spice 支持, usb 重定向支持, 并把 QEMU 安装到了 我的家目录的 usr 下

启动 QEMU

 $ ~/usr/bin/qemu-system-x86_64 -enable-kvm -cpu core2duo -smp 4 -m 4096 \ -usb -device usb-ehci -spice port=5900,addr=0.0.0.0,disable-ticketing \ -vga qxl -global qxl-vga.vram_size=67108864 -readconfig ich9-ehci-uhci.cfg \ -chardev spicevmc,name=usbredir,id=usbredirchardev1 \ -device usb-redir,chardev=usbredirchardev1,id=usbredirdev1,debug=3 \ Ubuntu-12-04-append.img 

启动了一个 4 核, 4G内存的虚拟机, spice 端口在 5900, 开启一个 USB Redirection 的通道

启动 Client

据我所知到目前为止, 支持 USB Redirection 重定向的客户端好像只有 spice-gtk(0.11 版本之后)

记得加上 usbredir 的支持

 $ USE="usbredir" emerge spice-gtk 

装完启动 Spice client

 $ spicy -h qemu-ipaddr -p 5900 

分类: kvm, QEMU 标签: ,

QEMU Monitor 重定向

2012年6月29日 2 条评论

有的时候 QEMU 运行在远端, 但是此时需要做一些信息监控, 控制 VM 等的操作, 需要用到 QEMU 的 monitor 通道(libvirt 就是基于这种方式控制 VM 的), 这时候就需要把 Monitor 转发到其他设备(socket, telnet 等), 我们通过 本地的 TCP client 来操作这个通道.

转发到一个 TCP Socket

以下指令把 Monitor 转发到本地的 TCP 4444 端口, 作为 server 端, nowait 表示不需要等待 client 来激活马上启动 VM. IpAddress 是允许连接的 Client. 如果只想本机连接, IpAddress 填 127.0.0.1, 如果想要所有为空.

 $ qemu-kvm -monitor tcp:IpAddress:4444,server,nowait VM.img 

转发到 telnet 端口

以下指令把 Monitor 转发到本地的 telnet 4444 端口, 在另外一 台机器(IpAddress)上, 可以使用 telnet qemu-ipaddr 4444 来连接

 $ qemu-kvm -monitor telnet:IpAddress:4444,server,nowait VM.img 

这时候, 只要在随便一台机器上打开 telnet 客户端就可以连接远端的 QEMU monitor 了.

 $ telnet qemu-ipaddress 4444 

分类: kvm, QEMU 标签: ,

QEMU Image 格式

2012年3月28日 2 条评论

raw

qemu-img 默认创建的镜像格式, 在支持 sparse file 的文件系统上,
据实际使用量来占用空间使用量. 简单, 和其它格式的转换比较容易.

qemu-img create -f raw raw.img 8G # 创建一个 8G 的 Image
ls -lsh raw.img # 查看实际大小, -s 可以查看实际的大小
0 -rw-r--r-- 1 root root 8.0G  3月 27 19:56 raw.img

qcow2

完整的 Thin Provision 支持, 加密支持, 压缩支持, 强大的快照支持.
支持的选项有:

backing_file
backing_fmt
encryption
cluster_size
preallocation

另外, 目前 qcow3 也快开发完成了.

Comparison

Performance Backup Encryption compression
raw Good NO NO NO
qcow2 Bad YES YES YES

目前, 简单来说, 想要获得高性能就采取预分配的 raw 格式, 想要完善的支持 Thin
Provision, 支持更强大的功能, 就采取 qcow2 格式. 具体选择得看应用场景.

Thin Provision

未完待续

分类: kvm, QEMU 标签: ,

在 QEMU 上使用 KGDB 调试内核

2011年12月28日 3 条评论

最近在研究 Linux Kernel, 由于我看问题喜欢直接看本质, 所以直接从代码开始看起,
但是 Linux 发展到现在代码何其多, 何其复杂, 里面的流程, 逻辑, 甚至各种变量绝对不是
我以前开发的项目能比的, 比如说里面全局变量的大量使用, 各种 goto 的使用,
所以必须要有一个好的阅读方法和好的阅读手段. 阅读代码的 Emacscscope 足以.
但是对于习惯 gdb 调试的我, 还是希望可以利用 gdb 的强大优势帮助学习. 在加上
QEMU 来作为 kernel 的运行平台, 这样的组合不事半功倍都说不过去.

内核构建

下载内核

经我测试 linux-2.6.24 和 linux-2.6.25 没有 KGDB 的支持. 为了能有 KGDB 的
支持, 我选择版本稍微高一点内核.

# mkdir -p ~/Develop/Linux && cd ~/Develop/Linux
# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.34.tar.bz2
# tar xf linux-2.6.34.tar.bz2

配置内核

# cd ~/Develop/Linux/linux-2.6.34 
# make defconfig # 用 defconfig 生成 一个精简内核 
# make menuconfig

确保下面的被选中

 General setup  ---> 
     [ * ] Prompt for development and/or incomplete code/drivers
Kernel hacking  --->
     [ * ] Compile the kernel with debug info
     [ * ] Compile the kernel with frame pointers
     [ * ] KGDB: kernel debugger  --->
           < * >   KGDB: use kgdb over the serial console

OK, 下面开始编译内核

# make -j5 # 因为我是 4 核的 CPU, 所以这里使用5个线程同时并发执行

QEMU 构建

安装 QEMU

这里可以选择多种安装方式, 可以选择从源码安装或者从发行版的二进制安装.
作为一个比较喜欢追根究底的 geek, 我选择的是源码安装.

另外, 我调试的只是 kernel, 所以没有硬件虚拟话我是可以忍受的,
所以我把 kvm 从编译参数那里去掉了.

# mkdir -p ~/Develop/QEMU
# cd ~/Develop/QEMU
# wget http://wiki.qemu.org/download/qemu-1.0.tar.gz
# tar xf qemu-1.0.tar.gz
# cd qemu-1.0
# ./configure --prefix=./ --target-list="i386-softmmu x86_64-softmmu" --disable-kvm
# make -j3 && make install

注意, 因为我不想把 qemu 和我系统的 qemu 冲突, 我简单的将 qemu
安装在 qemu 源码目录下.

文件系统构建

安装 busybox

# mkdir ~/Develop/busybox
# wget http://www.busybox.net/downloads/busybox-1.19.3.tar.bz2
# tar xf busybox-1.19.3
# cd busybox-1.19.3
# make menuconfig

静态编译的选择很重要, 如果不选择的话, 需要把 libc.so 和 ld.so 等
复制到文件系统里面, 稍微麻烦一些, 这里我们选择最简单的方式.

另外这个版本静态编译的时候 mount umount会出错, 方正对我来说不需要,
我暂时去掉.

Busybox Settings  ---> 
   Build Options  --->
        [ * ] Build BusyBox as a static binary (no shared libs)
Linux System Utilities  --->
   [ ] mount 
   [ ] umount

执行 make install 后, 会在 busybox 的源码目录地下创建一个 _install
的文件夹, 这个文件夹就是需要复制到文件系统里面的东西.
# make install

制作文件系统

首先创建一个虚拟盘, 并挂载到当前 tmp 目录下.

# cd ~/Develop
# dd if=/dev/zero of=initrd.img bs=1k count=8192
# mkfs.ext3 -F -v -m0 initrd.img
# mkdir tmp
# mount -o loop initrd.img  tmp

然后把编译好的 busybox 复制到挂在虚拟盘的目录里面.

# cp -dpRrf ~/Develop/Linux/busybox-1.19.3//_install/* tmp

创建一些必须的设备文件, 其实设备号几乎是通用的, 所以我直接把本机的设备文件
复制过来了.

# cp -dfrpa /dev/console tmp/dev
# cp -dfrpa /dev/tty* tmp/dev
# cp -dfrpa /dev/mem tmp/dev
# cp -dfrpa /dev/null tmp/dev
# cp -dfrpa /dev/random tmp/dev
# umount tmp

运行

# ~/Develop/QEMU/qemu-1.0/bin/qemu-system-x86_64 \
# -kernel ~/Develop/Linux/linux-2.6.34/arch/x86/boot/bzImage \
# -hda ~/Develop/initrd.img -m 2048 -append "root=/dev/sda init=/bin/sh"

在运行的时候碰到了 init 段错误的问题. 我不知道是不是静态编译导致的.
解决这个问题有两个办法, 或者从其他发行版复制一个静态的 busybox过来,
我试过, 没有问题. 或者把内核启动参数改为 init=/bin/sh 不让 kernel
去启动 init. 我选的是后者.

开始调试

-s 表示用默认的 1234 端口, 开启 gdb server

# ~/Develop/QEMU/qemu-1.0/bin/qemu-system-x86_64 \
# -s -S -kernel ~/Develop/Linux/linux-2.6.34/arch/x86/boot/bzImage \
# -hda ~/Develop/initrd.img -m 2048 -append "root=/dev/sda init=/bin/sh"

在我的 Emacs 里面, 使用 /tmp/gdb/bin/gdb –annotate=3 ~/Develop/Linux/linux-2.6.34/vmlinux
来启动, 进去以后, 设置断点, 然后 target remote localhost:1234 连接 gdb server

其它.

我 gdb 的启动指令是 /tmp/gdb/bin/gdb 而不是默认的 gdb, 因为默认的 gdb 在我的 x86
平台上调试的时候有一个小 bug, 根据邮件列表上的说法.
需要 hack 代码, 然后重新编译. 我打了一个小 patch.

--- gdb-7.3.1-orign/gdb/remote.c    2011-07-15 10:04:29.000000000 +0800
+++ gdb-7.3.1/gdb/remote.c  2011-12-27 18:37:34.319902796 +0800
@@ -5702,9 +5702,21 @@
   buf_len = strlen (rs->buf);
 
   /* Further sanity checks, with knowledge of the architecture.  */
+#if 0
   if (buf_len > 2 * rsa->sizeof_g_packet)
     error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
-
+#endif
+  if (buf_len > 2 * rsa->sizeof_g_packet) {
+     rsa->sizeof_g_packet = buf_len ;
+     for (i = 0; i < gdbarch_num_regs (gdbarch); i++) {
+         if (rsa->regs[i].pnum == -1)
+             continue;
+         if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
+             rsa->regs[i].in_g_packet = 0;
+         else 
+             rsa->regs[i].in_g_packet = 1;
+     }    
+  }
   /* Save the size of the packet sent to us by the target.  It is used
      as a heuristic when determining the max size of packets that the
      target can safely receive.  */

最后献上一张截图: (Emacs 又立功了)

Emacs_KGDB

分类: Kernel, kvm, linux, QEMU 标签: , , , ,

KVM 初体验

2011年8月5日 没有评论

上次和 明源兄 聊天的时候, 得知他使用的虚拟机是 KVM. 这个东西以前经常听说过, 加之现在我对虚拟化的很感兴趣. 遂在我的 laptop 上体验了一把(我公司的那台 intel 电脑竟然不支持虚拟化).

我的 laptop 上安装的是 Archlinux.

检查CPU是否支持虚拟化

如果以下指令有输出结果的话, 就说明 cpu 支持虚拟化, 不然要玩 KVM 请换电脑吧.

# egrep '^flags.*(vmx|svm)' /proc/cpuinfo

比如我公司的另一台的电脑输出是:

flags       : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm xsave lahf_lm dts tpr_shadow vnmi flexpriority
flags       : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm xsave lahf_lm dts tpr_shadow vnmi flexpriority

安装

# sudo pacman -S kernel26 qemu-kvm

使用

将当前用户加入到 kvm 组中, 并加载 kvm-intel(如果是 AMD, 用 kvm-amd) 驱动

# gpasswd -a geniux kvm
# modprobe kvm
# modprobe kvm-intel

如果 kvm-intel 加载的时候出错, 并且 CPU 支持虚拟化的话, 很可能是 BIOS 没有打开虚拟支持. 我的 laptop 上就是这样, 我是在 BIOS Setting 里面打开了 Virtualization Technology 选项.

创建一个虚拟磁盘, -f qcow2 表示创建这种格式的磁盘, 此格式的磁盘类似于 virtualbox 里面创建的动态扩展大小的磁盘(最大 8G).

# qemu-img create -f qcow2 winxp.img 8G # Create a new disk image

然后启动 kvm 安装系统, 这里我虚拟了一个 XP 的安装, 安装解释是 iso 文件. 主要是想测试一下他的图形性能, 因为一直有人说 kvm 的图形性能话不好, 我想看看不好到什么程度.

# kvm -m 512M -hda kvm/winxp.img -cdrom /mnt/root/Software/XP-hengqi.iso -boot d

剩余的步骤和在 Virtualbox 下安装系统差不多. 装完以后我启动了虚拟的 XP, 我靠, 果然很卡, 可能需要图形加速的参数没有打开吧.

分类: kvm, 虚拟化 标签: , ,