在Ubuntu 12.04 LTS服务器上借助KVM实现虚拟化

原文: http://virtual.51cto.com/art/201206/341911_all.htm

安装

vmbuilder:创建基于Ubuntu的虚拟机的一个脚本

apt-get install ubuntu-virt-server python-vm-builder kvm-ipxe

配置网桥

创建基于镜像的虚拟机

现在我们可以创建第一个虚拟机:基于镜像的虚拟机(如果你预计该虚拟机会有大量的流量和频繁的读写操作,可以改而使用基于LVM的虚拟机,如下面第6节所示——基于镜像的虚拟机其硬盘输入/输出操作很频繁)。

虚拟机目录

我想在/var/lib/libvirt/images/目录中创建虚拟机(无法在/root目录中创建虚拟机,因为libvirt-qemu用户在该目录中没有读取权限)。

我们将为想要创建的每个虚拟机建立一个新的目录(每个虚拟机都会有一个名为ubuntu-kvm的子目录),比如:

  1. /var/lib/libvirt/images/vm1
  2. /var/lib/libvirt/images/vm2
  3. /var/lib/libvirt/images/vm3

如果你试图在/var/lib/libvirt/images/vm1创建第二个虚拟机,就会看到错误消息,表明ubuntu-kvm已经存在(除非你使用--dest=DESTDIR变量运行vmbuilder)。

我们会使用vmbuilder工具来创建虚拟机。你可以在<JeOSVMBuilder> 进一步了解vmbuilder。

模板

定义分区

现在我们进入到虚拟机的分区。我们创建了一个文件,名为vmbuilder.partition……

cd /var/lib/libvirt/images/vm1/
cat > vmbuilder.partition <<EOF
# 定义所需的分区,如下所示:
root 8000
swap 4000
---
/var 20000
EOF

这定义了:

  1. 大小为8000MB的根分区(/)
  2. 4000MB的交换分区
  3. 20000MB的/var分区
  4. ---这一行表示:下列分区(本例中的/var)在另外的磁盘镜像上(也就是说这将创建两个磁盘镜像,一个用于根分区和交换分区,另一个用于/var分区)。

当然,你可以随意定义自己喜欢的任何分区(只要你定义了根分区和交换分区);当然,它们可以在一个磁盘镜像中——这只是个例子。

boot.sh

我想在虚拟机中安装openssh-server。为了确保每个虚拟机都获得一个独特的OpenSSH密钥,我们创建虚拟机时无法安装openssh-server。

因此,我们创建了名为boot.sh的脚本,虚拟机第一次启动时,就会执行该脚本。它会安装openssh-server(生成独特密钥);

用户第一次登录后,它还会迫使用户更改密码。(让虚拟机使用默认的用户名administrator,默认密码是howtoforge):

cd /var/lib/libvirt/images/vm1/
cat > boot.sh <<EOF
#!/bin/sh
# 虚拟机第一次启动时,该脚本将运行。
# 它以根用户来运行。
# 到期终止用户帐户
passwd -e administrator

# 安装openssh-server
apt-get update
apt-get install -qqy --force-yes openssh-server
EOF

确保你把用户名administrator换成了默认登录名。

vmbuilder

大多数选项不言自明。

--part指定了有分区详细信息的文件,相对于我们的工作目录(在运行vmbuilder之前要进入到虚拟机目录);

--templates指定了保存模板文件的目录(再次相对于我们的工作目录)

--firstboot指定了首次启动脚本。

--libvirt=qemu:///system告诉KVM把该虚拟机添加到可用虚拟机的列表。

--addpkg让你可以指定创建虚拟机过程中想安装的Ubuntu程序包(上文解释了为什么不该把openssh-server添加到该列表中,而是应该使用首次启动脚本)。

--bridge建立了桥接网络;由于我们已在第2节建立了网桥br0,我们在此指定该网桥。

--mirror可以使用--mirror来指定官方的Ubuntu库,比如http://de.archive.ubuntu.com/ubuntu。如果你略去--mirror,那么就会使用默认的Ubuntu库:http://archive.ubuntu.com/ubuntu

如果你用--ip参数选项符指定IP地址,要确保你还使用--gw参数选项符指定了正确的网关IP(不然,vmbuilder会假设它是网络中的第一个有效地址,实则不然)。网关IP通常与你在/etc/network/interfaces中所用的一样(参阅第2节)。

创建过程可能要花几分钟。

之后,你能在/etc/libvirt/qemu/ (=> /etc/libvirt/qemu/vm1.xml)中找到该虚拟机的XML配置文件:

ls -l /etc/libvirt/qemu/

drwxr-xr-x 3 root root 4096 May 21 13:00 networks
-rw------- 1 root root 2082 May 21 13:15 vm1.xml

磁盘镜像位于我们虚拟机目录的ubuntu-kvm/子目录中:

ls -l /var/lib/libvirt/images/vm1/ubuntu-kvm/

-rw-r--r-- 1 root root 324337664 May 21 13:14 tmpE4IiRv.qcow2
-rw-r--r-- 1 root root 294715392 May 21 13:15 tmpxvSVOT.qcow2

创建第二个虚拟机

如果你想创建第二个虚拟机(vm2),这里简要概述一下命令:

VMD=/var/lib/libvirt/images/vm2

mkdir -p $VMD/mytemplates/libvirt
cp /etc/vmbuilder/libvirt/* $VMD/mytemplates/libvirt/

vi /var/lib/libvirt/images/vm2/vmbuilder.partition
vi /var/lib/libvirt/images/vm2/boot.sh

cd /var/lib/libvirt/images/vm2/
vmbuilder kvm ubuntu --suite=precise --flavour=virtual --arch=amd64 \
--mirror=http://de.archive.ubuntu.com/ubuntu -o --libvirt=qemu:///system \
--ip=192.168.0.102 --gw=192.168.0.1 --part=vmbuilder.partition --templates=mytemplates \
--user=administrator --name=Administrator --pass=howtoforge \
--addpkg=vim-nox --addpkg=unattended-upgrades --addpkg=acpid \
--firstboot=/var/lib/libvirt/images/vm2/boot.sh \
--mem=256 --hostname=vm2 --bridge=br0

请注意:如果你把-d DESTDIR变量传递给vmbuilder命令,就没必要为虚拟机创建新目录(/var/lib/libvirt/images/vm2)——它让你可以在你已经创建了另一个虚拟机的目录中创建虚拟机。这种情况下,你没必要创建新的vmbuilder.partition和boot.sh文件,也没必要改动模板,而是只要使用现有文件:

cd /var/lib/libvirt/images/vm1/

vmbuilder kvm ubuntu --suite=precise --flavour=virtual --arch=amd64 \
--mirror=http://de.archive.ubuntu.com/ubuntu -o --libvirt=qemu:///system \
--ip=192.168.0.102 --gw=192.168.0.1 --part=vmbuilder.partition --templates=mytemplates \
--user=administrator --name=Administrator --pass=howtoforge \
--addpkg=vim-nox --addpkg=unattended-upgrades --addpkg=acpid \
--firstboot=/var/lib/libvirt/images/vm1/boot.sh \
--mem=256 --hostname=vm2 --bridge=br0 -d vm2-kvm

管理虚拟机

可以通过virsh(虚拟外壳)来管理虚拟机。想连接到虚拟外壳,运行:

virsh --connect qemu:///system

# 虚拟外壳的样子如下:
root@server1:~# virsh --connect qemu:///system
Welcome to virsh, the virtualization interactive terminal.
Type: 'help' for help with commands
'quit' to quit

virsh # help

创建基于LVM的虚拟机

基于LVM的虚拟机与基于镜像的虚拟机相比有一些优点。它们的硬盘输入/输出不大频繁,而且更容易备份(使用LVM快照)。

想使用基于LVM的虚拟机,你就需要一个卷组,它要有未分配给任何逻辑卷的一些闲置空间。在本例中,我使用了大小约为465GB的卷组/dev/vg0……

vgdisplay

  --- Volume group ---
  VG Name               vg0
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               465.29 GiB
  PE Size               4.00 MiB
  Total PE              119115
  Alloc PE / Size       24079 / 94.06 GiB
  Free  PE / Size       95036 / 371.23 GiB
  VG UUID               PRenhH-0MvN-wXCL-nl4i-IfsQ-J6fc-2raYLD

该卷组包含大小约为100GB的逻辑卷/dev/vg0/root和大小约为1GB的逻辑卷/dev/vg0/swap_1,其余空间未分配,可供虚拟机使用:

lvdisplay
  --- Logical volume ---
  LV Name                /dev/vg0/root
  VG Name                vg0
  LV UUID                dwnORf-yG3U-x1ZC-Bet1-TOoc-q1Dd-KZnbtw
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                93.13 GiB
  Current LE             23841
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:0
  --- Logical volume ---
  LV Name                /dev/vg0/swap_1
  VG Name                vg0
  LV UUID                ZdPKO6-sZrr-tIRb-PPcl-aWBj-QAUU-fnYUuP
  LV Write Access        read/write
  LV Status              available
  # open                 2
  LV Size                952.00 MiB
  Current LE             238
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:1

现在我将创建虚拟机vm5,作为基于LVM的虚拟机。我们可以再度使用vmbuilder命令。vmbuilder知道--raw选项,该选项允许将虚拟机写入到块设备(如/dev/vg0/vm5)——我试用了该选项;不过它没有返回错误,我也启动不了虚拟机(start vm5也没有显示任何错误,但是我根本无法访问该虚拟机。)

因此,我将先创建vm5,作为基于镜像的虚拟机,然后转换成基于LVM的虚拟机。

mkdir -p /var/lib/libvirt/images/vm5/mytemplates/libvirt
cp /etc/vmbuilder/libvirt/* /var/lib/libvirt/images/vm5/mytemplates/libvirt/

确保你在仅仅一个镜像文件中创建所有分区,所以在vmbuilder.partition文件中不要使用---:

vi /var/lib/libvirt/images/vm5/vmbuilder.partition
root 8000
swap 2000
/var 10000

vi /var/lib/libvirt/images/vm5/boot.sh

# 虚拟机第一次启动时,该脚本将运行。
# 它以根用户来运行。
# 到期终止用户帐户
passwd -e administrator
# 安装openssh-server
apt-get update
apt-get install -qqy --force-yes openssh-server
cd /var/lib/libvirt/images/vm5/
vmbuilder kvm ubuntu --suite=precise --flavour=virtual --arch=amd64 \
--mirror=http://de.archive.ubuntu.com/ubuntu -o --libvirt=qemu:///system \
--ip=192.168.0.105 --gw=192.168.0.1 --part=vmbuilder.partition --templates=mytemplates \
--user=administrator --name=Administrator --pass=howtoforge \
--addpkg=vim-nox --addpkg=unattended-upgrades --addpkg=acpid \
--firstboot=/var/lib/libvirt/images/vm5/boot.sh \
--mem=256 --hostname=vm5 --bridge=br0

你可以从vmbuilder.partition文件看到,虚拟机将使用最多20GB的空间,于是我们现在创建一个大小为20GB的逻辑卷,名为/dev/vg0/vm5:

lvcreate -L20G -n vm5 vg0

别在新的逻辑卷中创建文件系统!我们将使用qemu-img命令,把镜像转换成基于LVM的虚拟机。

现在我们进入到虚拟机的ubuntu-kvm/目录……即可发现我们的镜像是如何命名的:

cd /var/lib/libvirt/images/vm5/ubuntu-kvm/
ls -l
-rw-r--r-- 1 root root 606470144 May 21 14:06 tmpesHsUI.qcow2

由于我们已知道了镜像的名称(tmpN27tbO.qcow2),可按如下方式来转换它:

qemu-img convert tmpesHsUI.qcow2 -O raw /dev/vg0/vm5

# 之后,你可以删除磁盘镜像:
rm -f tmpesHsUI.qcow2

现在,我们必须改动虚拟机的配置……

virsh edit vm5

# 并改变下列部分……
[...]
# 以便看起来像下面这样:
[...]

# 现在,你可以使用virsh来管理虚拟机:
virsh --connect qemu:///system

# 由于我们已改动了虚拟机的XML文件,必须先运行define命令……
define /etc/libvirt/qemu/vm5.xml
# 然后启动虚拟机:
start vm5

相关链接