install

sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils

create vm

#!/bin/sh
vm_name=$1
vm_img="/var/kvm/vm/${vm_name}.qcow2"
qemu-img create -f qcow2 $vm_img 8G
virt-install \
     --name $vm_name \
     --ram 512 \
     --disk path=$vm_img,format=qcow2 \
     --accelerate \
     --network network=default,model=virtio \
     --cdrom /var/kvm/iso/ubuntu-14.04.3-server-amd64.iso \
     --boot cdrom \
     --vnc 
sudo virt-install --connect=qemu:///system --name=cirros --ram=512 --vcpus=1 --disk /var/lib/libvirt/images/cirros-0.3.4-x86_64-disk.img,format=qcow2 --import --network network=default --vnc

Kvm虚拟机部署方案

涉及的几个概念:

  • Domain: 虚拟机的一个运行实例,简单的理解,就是一个虚拟机虚拟出来的操作系统。它的叫法可是多种多样:instance,guest OS,virsual machine,其实都指的同一个概念。
  • Hypervisor: 指的就是虚拟机本身,比如qemu, kvm, xen…
  • libvirt 由几个不同的部分组成,其中包括应用程序编程接口 (API) 库、一个守护进程 (libvirtd),以及一个默认命令行实用工具 (virsh),libvirtd守护进程负责对虚拟机的管理工作,在用各种工具对虚拟机进行管理的时候,这个守护进程一定要跑起来,而且这个进程可以分为两种,一种是root权限的libvirtd,一种是普通用户权限的libvirtd,前者权限大,可以虚拟计算机的各种设备。
  • 开启root权限的libvirtd守护进程要以root身份去运行:sudo libvirtd –daemon

gentoo

Using virt-manager

常用的命令,例如virt-install都是需要virt-manager提供的,需要安装


virt-network

如果app-emulation/libvirt 没有 virt-network 会出现异常如下:

this function is not supported by the connection driver: virConnectNumOfNetworks

echo ">=app-emulation/libvirt-1.0.3-r2 virt-network qemu" >> /etc/portage/package.use

libvirt需要使用virt-network支持,但不需要net-misc/bridge-utils,猜错了。

$ equery g app-emulation/libvirt
 * dependency graph for app-emulation/libvirt-2.3.0
 `--  app-emulation/libvirt-2.3.0  [~amd64 keyword] 
   `--  app-misc/scrub-2.5.2  (app-misc/scrub) amd64 
   `--  dev-libs/libgcrypt-1.7.3  (dev-libs/libgcrypt) amd64 
   `--  dev-libs/libnl-3.2.27  (dev-libs/libnl) amd64 
   `--  dev-libs/libxml2-2.9.4  (>=dev-libs/libxml2-2.7.6) amd64 
   `--  net-analyzer/netcat6-1.0-r2  (>=net-analyzer/netcat6-1.0-r2) amd64 
   `--  net-analyzer/openbsd-netcat-1.105-r1  (>=net-analyzer/openbsd-netcat-1.105-r1) [~amd64 keyword] 
   `--  net-libs/gnutls-3.3.24-r1  (>=net-libs/gnutls-1.0.25) amd64 
   `--  net-libs/libssh2-1.7.0  (net-libs/libssh2) amd64 
   `--  net-misc/curl-7.50.3  (>=net-misc/curl-7.18.0) amd64 
   `--  sys-apps/dmidecode-2.12-r1  (sys-apps/dmidecode) amd64 
   `--  sys-apps/util-linux-2.26.2  (>=sys-apps/util-linux-2.17) amd64 
   `--  sys-devel/gettext-0.19.7  (sys-devel/gettext) amd64 
   `--  sys-libs/ncurses-5.9-r5  (sys-libs/ncurses) amd64 
   `--  sys-libs/readline-6.3_p8-r2  (sys-libs/readline) amd64 
   `--  sys-libs/libapparmor-2.10.1-r1  (sys-libs/libapparmor) [~amd64 keyword] 
   `--  sys-process/audit-2.4.3-r1  (sys-process/audit) amd64 
   `--  sys-libs/libcap-ng-0.7.7  (sys-libs/libcap-ng) amd64 
   `--  sys-libs/glibc-2.22-r4  (sys-libs/glibc) amd64  [rpc(+)]
   `--  net-firewall/firewalld-0.4.3.3  (net-firewall/firewalld) amd64 
   `--  sys-fs/fuse-2.9.7  (>=sys-fs/fuse-2.8.6) amd64 
   `--  sys-cluster/glusterfs-3.7.4  (>=sys-cluster/glusterfs-3.4.1) [~amd64 keyword] 
   `--  sys-block/open-iscsi-2.0.873  (sys-block/open-iscsi) amd64 
   `--  sys-fs/lvm2-2.02.116-r4  (>=sys-fs/lvm2-2.02.48-r2) amd64  [-device-mapper-only(-)]
   `--  net-fs/nfs-utils-1.3.1-r5  (net-fs/nfs-utils) amd64 
   `--  sys-process/numactl-2.0.11  (>sys-process/numactl-2.0.2) amd64 
   `--  sys-process/numad-0.5-r1  (sys-process/numad) amd64 
   `--  sys-kernel/openvz-sources-2.6.32.111.12  (sys-kernel/openvz-sources) amd64 
   `--  sys-block/parted-3.2  (>=sys-block/parted-1.8) amd64  [device-mapper]
   `--  net-libs/libpcap-1.8.0  (>=net-libs/libpcap-1.0.0) amd64 
   `--  sys-auth/polkit-0.113  (>=sys-auth/polkit-0.9) amd64 
   `--  app-emulation/qemu-2.7.0-r5  (>=app-emulation/qemu-0.13.0) amd64 
   `--  dev-libs/yajl-2.0.4-r3  (dev-libs/yajl) amd64 
   `--  sys-cluster/ceph-9.2.1-r2  (sys-cluster/ceph) amd64 
   `--  dev-libs/cyrus-sasl-2.1.26-r9  (dev-libs/cyrus-sasl) amd64 
   `--  sys-libs/libselinux-2.5-r1  (>=sys-libs/libselinux-2.0.85) amd64 
   `--  net-dns/dnsmasq-2.76  (net-dns/dnsmasq) amd64  [script]
   `--  net-firewall/ebtables-2.0.10.4  (net-firewall/ebtables) amd64 
   `--  net-firewall/iptables-1.4.21-r1  (>=net-firewall/iptables-1.4.10) amd64  [ipv6]
   `--  net-misc/radvd-2.14  (net-misc/radvd) amd64 
   `--  sys-apps/iproute2-4.4.0  (sys-apps/iproute2) amd64  [-minimal]
   `--  app-emulation/virtualbox-4.3.38  (app-emulation/virtualbox) amd64 
   `--  app-emulation/virtualbox-bin-5.1.8.111374  (>=app-emulation/virtualbox-bin-2.2.0) [~amd64 keyword] 
   `--  net-analyzer/wireshark-2.2.1  (net-analyzer/wireshark) amd64 
   `--  app-emulation/xen-4.6.3-r2  (app-emulation/xen) amd64 
   `--  app-emulation/xen-tools-4.6.3-r1  (app-emulation/xen-tools) amd64 
   `--  virtual/udev-215  (virtual/udev) amd64 
   `--  x11-libs/libpciaccess-0.13.4  (>=x11-libs/libpciaccess-0.10.9) amd64 
   `--  net-dns/avahi-0.6.32  (>=net-dns/avahi-0.6) amd64  [dbus]
   `--  app-text/xhtml1-20020801-r4  (app-text/xhtml1) amd64 
   `--  dev-lang/perl-5.22.2  (dev-lang/perl) amd64 
   `--  dev-libs/libxslt-1.1.29  (dev-libs/libxslt) amd64 
   `--  dev-perl/XML-XPath-1.130.0-r1  (dev-perl/XML-XPath) amd64 
   `--  virtual/pkgconfig-0-r1  (virtual/pkgconfig) amd64 
[ app-emulation/libvirt-2.3.0 stats: packages (54), max depth (1) ]


COW and snapshot


cow image

copy-on-write image 需要设置一个backing image, backing image不能在写东西。以下是将windowsxp.qcow2作为backing image, 制作一个 clone.qcow2(此clone.qcow2可挂载新虚拟机)

sudo qemu-img create -f qcow2 -o backing_file=windowxp.qcow2 clone.qcow2

文件系统看到的东西:

$ ls -lth
-rw-r--r-- 1 qemu qemu  35M Dec 22 10:51 clone.qcow2
-rw-r--r-- 1 qemu qemu 4.0G Dec 21 17:35 windowxp.qcow2

镜像内容看到的东西:

$ qemu-img info clone.qcow2
image: clone.qcow2
file format: qcow2
virtual size: 100G (107374182400 bytes)
disk size: 43M
cluster_size: 65536
backing file: windowxp.qcow2
Format specific information:
    compat: 1.1
    lazy refcounts: false

$ qemu-img info windowxp.qcow2 
image: windowxp.qcow2
file format: qcow2
virtual size: 100G (107374182400 bytes)
disk size: 3.9G
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false

snapshot可针对整个vm而言,但每个qcow2文件也有snapshot的痕迹。

生成一个snapshot

$ sudo virsh snapshot-create xpclone
Domain snapshot 1482389568 created

查看snapshot情况

$ sudo virsh snapshot-list --tree xpclone

1482388315
  |
  +- 1482388499
  |   |
  |   +- 1482388910
  |   +- 1482389348
  |     
  +- 1482389568


$ sudo virsh snapshot-current xpclone | head
<domainsnapshot>
  <name>1482389568</name>
  <state>shutoff</state>
  <parent>
    <name>1482388315</name>
  </parent>
  <creationTime>1482389568</creationTime>
  <memory snapshot='no'/>
  <disks>
    <disk name='hda' snapshot='internal'/>

查看qcow2文件的snapshot情况

$ qemu-img info /var/lib/libvirt/images/clone.qcow2 
image: /var/lib/libvirt/images/clone.qcow2
file format: qcow2
virtual size: 100G (107374182400 bytes)
disk size: 1.6G
cluster_size: 65536
backing file: windowxp.qcow2 (actual path: /var/lib/libvirt/images/windowxp.qcow2)
Snapshot list:
ID        TAG                 VM SIZE                DATE       VM CLOCK
1         1482388315                0 2016-12-22 14:31:55   00:00:00.000
2         1482388499             188M 2016-12-22 14:34:59   00:02:30.411
3         1482388910             236M 2016-12-22 14:41:50   00:04:18.761
4         1482389348             183M 2016-12-22 14:49:08   00:03:04.003
5         1482389568                0 2016-12-22 14:52:48   00:00:00.000
Format specific information:
    compat: 1.1
    lazy refcounts: false

每次vm的snapshot操作,会记录在snapshot/DOMAIN/xxx.xml文件上,记录档次vm的状态。 真实的cluster修改还是会记录在qcow2文件上。

./images/clone.qcow2
./qemu/snapshot/xpclone/1482388315.xml
./qemu/snapshot/xpclone/1482388499.xml
./qemu/snapshot/xpclone/1482388910.xml
./qemu/snapshot/xpclone/1482389348.xml
./qemu/snapshot/xpclone/1482389568.xml

clone

如果需要COW,还是需要手动qemu-image -b 实现


By default, virt-clone will show an error if the necessary information to clone the guest is not provided. The –auto-clone option will generate all needed input, aside from the source guest to clone.

Please note, virt-clone does not change anything inside the guest OS, it only duplicates disks and does host side changes. So things like changing passwords, changing static IP address, etc are outside the scope of this tool. For these types of changes, please see virt-sysprep.

virsh-clone只是做拷贝,image文件会被完整拷贝。另外就是qemu的xml有点不一样。

$ sudo diff -u /etc/libvirt/qemu/win2008clone.xml /etc/libvirt/qemu/win2008.xml
--- /etc/libvirt/qemu/win2008clone.xml	2016-12-22 15:39:59.819695796 +0800
+++ /etc/libvirt/qemu/win2008.xml	2016-12-21 17:07:33.885044686 +0800
@@ -1,13 +1,13 @@
 <!--
 WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
 OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
-  virsh edit win2008clone
+  virsh edit win2008
 or other application using the libvirt API.
 -->
 
 <domain type='kvm'>
-  <name>win2008clone</name>
-  <uuid>ff08d8e1-e5a5-423d-8fb8-405f53eada1c</uuid>
+  <name>win2008</name>
+  <uuid>5fe64ca1-4540-4044-b6b9-5d4f11f0bded</uuid>
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>2</vcpu>
@@ -38,7 +38,7 @@
     <emulator>/usr/libexec/qemu-kvm</emulator>
     <disk type='file' device='disk'>
       <driver name='qemu' type='qcow2'/>
-      <source file='/var/lib/libvirt/images/win2008_clone.qcow2'/>
+      <source file='/var/lib/libvirt/images/win2008.qcow2'/>
       <target dev='hda' bus='ide'/>
       <address type='drive' controller='0' bus='0' target='0' unit='0'/>
     </disk>
@@ -62,7 +62,7 @@
       <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
     </controller>
     <interface type='network'>
-      <mac address='52:54:00:ec:61:4d'/>
+      <mac address='52:54:00:b7:07:19'/>
       <source network='default'/>
       <model type='rtl8139'/>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>

You can use “rebase” to perform a “diff” operation on two disk images. This can be useful when you have copied or cloned a guest, and you want to get back to a thin image on top of a template or base image.

Say that “base.img” has been cloned as “modified.img” by copying it, and that the “modified.img” guest has run so there are now some changes compared to “base.img”. To construct a thin image called “diff.qcow2” that contains just the differences, do:

   qemu-img create -f qcow2 -b modified.img diff.qcow2
   qemu-img rebase -b base.img diff.qcow2

At this point, “modified.img” can be discarded, since “base.img + diff.qcow2” contains the same information.