Linux中如何克隆KVM虚拟机

4 minute read

背景

当需要批量部署虚拟机时,通常有几种做法,使用模板重新安装。

或者使用已有的虚拟机克隆。

使用模板安装可以参考kickstart脚本的编写方法。

《install kvm hosts use kickstart in CentOS 6 in text mode》

本文介绍一下在已经安装好的虚拟机上,克隆虚拟机的方法。

从0开始安装一个虚拟机

在服务器安装必要的包, 不再需要图形相关的包.

# yum install -y qemu-img qemu-kvm virt-manager libvirt libvirt-python python-virtinst libvirt-client libvirt libvirt-client virt-what  

创建一个虚拟磁盘目录

# mkdir /data03/kvmdisk  

创建虚拟磁盘, 用于虚拟机的系统盘

# qemu-img create -f qcow2 -o encryption=off,cluster_size=2M,preallocation=full /data03/kvmdisk/disk01.img 32G  

or 

# qemu-img create -f raw /data03/kvmdisk/disk01.img 32G  

下载安装镜像

# mkdir /data03/iso  
# cd iso  
# wget http://mirrors.aliyun.com/centos/6.6/isos/x86_64/CentOS-6.6-x86_64-bin-DVD1.iso  

配置

vi /etc/libvirt/libvirtd.conf

listen_tls = 0

启动libvirtd

# service libvirtd start  
# /etc/init.d/messagebus start  
# /etc/init.d/avahi-daemon start   
# /etc/init.d/libvirtd start  

# chkconfig libvirtd on  
# chkconfig libvirt-guests off  
# chkconfig avahi-daemon on  
# chkconfig messagebus on 

查看当前启动的网桥

# brctl show  
bridge name     bridge id               STP enabled     interfaces  
virbr0          8000.5254001263b0       yes             virbr0-nic  
  
# ifconfig  
em1       Link encap:Ethernet  HWaddr 00:22:19:60:77:8F    
          inet addr:172.16.3.150  Bcast:172.16.3.255  Mask:255.255.255.0  
          inet6 addr: fe80::222:19ff:fe60:778f/64 Scope:Link  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1  
          RX packets:5469716 errors:0 dropped:0 overruns:0 frame:0  
          TX packets:2830916 errors:0 dropped:0 overruns:0 carrier:0  
          collisions:0 txqueuelen:1000   
          RX bytes:5147311077 (4.7 GiB)  TX bytes:198552462 (189.3 MiB)  
  
lo        Link encap:Local Loopback    
          inet addr:127.0.0.1  Mask:255.0.0.0  
          inet6 addr: ::1/128 Scope:Host  
          UP LOOPBACK RUNNING  MTU:65536  Metric:1  
          RX packets:79073 errors:0 dropped:0 overruns:0 frame:0  
          TX packets:79073 errors:0 dropped:0 overruns:0 carrier:0  
          collisions:0 txqueuelen:0   
          RX bytes:24506711 (23.3 MiB)  TX bytes:24506711 (23.3 MiB)  
  
virbr0    Link encap:Ethernet  HWaddr 52:54:00:12:63:B0    
          inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1  
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0  
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0  
          collisions:0 txqueuelen:0   
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)  

或者你也可以手工添加网桥

brctl addbr br0  

ip link set br0 up  

ip addr add 192.168.122.1/24 dev br0 

查看虚拟机用到的virbr0网桥地址配置

# grep -r 192.168.122 /etc/libvirt  
/etc/libvirt/qemu/networks/default.xml:  <ip address="192.168.122.1" netmask="255.255.255.0">  
/etc/libvirt/qemu/networks/default.xml:      <range start="192.168.122.2" end="192.168.122.254" />  
/etc/libvirt/qemu/networks/autostart/default.xml:  <ip address="192.168.122.1" netmask="255.255.255.0">  
/etc/libvirt/qemu/networks/autostart/default.xml:      <range start="192.168.122.2" end="192.168.122.254" />  

text 交互式安装虚拟机操作系统

在没有图形环境时, 可以使用text模式安装操作系统.

virt-install \
   --name=centos6_6_x64 \
   --disk path=/data03/kvmdisk/disk01.img,device=disk,bus=virtio,perms=rw,cache=writethrough \
   --graphics none \
   --vcpus=4 --ram=4096 \
   --location=/data03/iso/CentOS-6.6-x86_64-bin-DVD1.iso \
   --network bridge=virbr0 \
   --os-type=linux \
   --os-variant=rhel6 \
   --extra-args="console=tty0 console=ttyS0,115200n8"

安装完后,连接到虚拟机的console的方法

# virsh  
> console $domainID  
> 退出console 按下 ctrl+]  

例如 :

[root@db-172-16-3-150 ~]# virsh  
Welcome to virsh, the virtualization interactive terminal.  
  
Type:  'help' for help with commands  
       'quit' to quit  
  
virsh # list  
 Id    Name                           State  
----------------------------------------------------  
 2     centos6_6_x64                  running  

virsh # console 2            # 使用Id或者Name都可以连接
Connected to domain centos6_6_x64  
Escape character is ^]  
  
CentOS release 6.6 (Final)  
Kernel 2.6.32-504.el6.x86_64 on an x86_64  
  
digoal.sky-mobi.com login: root  
Password:   
Last login: Thu Apr  2 00:12:27 on ttyS0  
[root@digoal ~]#   
[root@digoal ~]#   
[root@digoal ~]# exit  
logout  
  
CentOS release 6.6 (Final)  
Kernel 2.6.32-504.el6.x86_64 on an x86_64  
  
digoal.sky-mobi.com login:           # 这里按下ctrl+]返回本地控制台  
virsh #   
virsh #   

设置开机自动启动虚拟机

# vi /etc/rc.local  
/usr/bin/virsh start centos6_6_x64  

优化虚拟机配置

1. 主要是删掉一些不必要的控制器(如USB), 然后添加CPU模块, 使用本地CPU的flag.

#virsh
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # 
virsh # list
 Id Name                 State
----------------------------------
  6 kvm101               running
  8 kvm103               running
  9 kvm104               running
 10 kvm105               running
 11 kvm106               running
 12 kvm102               running

优化例子

virsh # edit kvm101
<domain type='kvm'>
  <name>kvm101</name>
  <uuid>366072c0-2ee0-027a-e887-e60d50bad5a7</uuid>
  <memory>83886080</memory>
  <currentMemory>83886080</currentMemory>
  <vcpu>10</vcpu>
  <cpu mode='host-passthrough'>    # 注意这里可能要指定CPU,而不是host-passthrough,否则可能保存会失败,或者自动抹除。 /usr/libexec/qemu-kvm -cpu ? 可以得到支持的CPU
    <model fallback='allow'/>    
  </cpu>
--------- 例如 /usr/share/libvirt/cpu_map.xml
  <cpu match='exact'>
     <model fallback='forbid'>Nehalem</model>
     <vendor>Intel</vendor>
     <feature policy='require' name='fma'/>    #  这里可以指定CPU flag
     <feature policy='require' name='pse'/>    #  这里可以指定CPU flag
  </cpu>
---------
  <os>
    <type arch='x86_64' machine='rhel6.2.0'>hvm</type>
    <boot dev='hd'/>
  </os>
  <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='raw' cache='writeback'/>
      <source file='/u01/kvmdisk/disk01.img'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </disk>
    <interface type='bridge'>
      <mac address='52:54:00:3e:78:0d'/>
      <source bridge='virbr0'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
  </devices>
</domain>


"/tmp/virshKtG0oG.xml" 36L, 1133C written                                                                                                                                                                        
Domain kvm101 XML configuration edited.

重启虚拟机后生效。

克隆虚拟机

http://www.cnblogs.com/5201351/p/4461000.html

kvm虚拟机的克隆分为两种情况,第一种kvm宿主机上对虚拟机直接克隆

第二种通过复制配置文件与磁盘文件的虚拟机复制克隆(适用于异机的静态迁移)。

现笔者将分别两种kvm虚拟机克隆的的详细操作过程都记录如下:

方法一: kvm宿主机上对虚拟机直接克隆(需要在关机或暂停的状态下操作)

1、查看所有的虚拟机、以及需要克隆的虚拟机的硬盘文件的位置。

[root@5201351_kvm ~]# virsh list --all           //查看已安装的所有的kvm虚拟机

2、我们可以通过编辑需要克隆的源虚拟机配置文件,去发现它的磁盘文件位置,命令如下:

[root@5201351_kvm ~]# virsh edit kvm_client00    //通过编辑虚拟机的配置文件,查看其硬盘文件的位置

如通过如下的内容,可以看出磁盘文件的位置

<source file='/var/lib/libvirt/images/kvm_client00.img'/>

3、开始克隆,将kvm_client00虚拟机克隆成新的虚拟机kvm_client01,新的虚拟机的磁盘文件为/var/lib/libvirt/images/kvm_client01.img

[root@5201351_kvm ~]# virt-clone -o kvm_client00 -n kvm_client01 -f /var/lib/libvirt/images/kvm_client01.img

4、这时克隆就完了、我们可以通过virsh list –all进行查看,如果需要删除克隆的虚拟机,我们只需要执行如下命令即可。

[root@5201351_kvm ~]# virsh undefine kvm_client01         //该命令只是删除wintest01的配置文件,并不删除虚拟磁盘文件

方法二:复制配置文件与磁盘文件进行克隆(可以不用关闭源虚拟机)

1、这里我们还是克隆kvm_client00,我们通过如下命令创建新虚拟机的配置文件

[root@5201351_kvm ~]# virsh dumpxml kvm_client00 > /etc/libvirt/qemu/kvm_client02.xml    //创建新虚拟机的配置文件

2、复制原虚拟机的磁盘文件,通过方法一、我们知道,磁盘默认位置为/var/lib/libvirt/images,我们执行如下命令进行复制

[root@5201351_kvm ~]# cd /var/lib/libvirt/images
[root@5201351_kvm images]# cp kvm_client00.img kvm_client02.img

3、直接编辑修改配置文件kvm_client02.xml,修改name,uuid,disk文件位置,mac地址,vnc端口

4、通过新虚拟机的配置文件,定义新的虚拟机,只需要执行如下一条命令即可。

[root@5201351_kvm ~]# virsh define /etc/libvirt/qemu/kvm_client02.xml   //通过配置文件定义新的kvm虚拟机

需要特别说明的是、以上两种方法克隆的虚拟机、我们都需要进入克隆的新虚拟机里

修改网卡设备文件/etc/udev/rules.d/70-persistent-net.rules,或者直接将其删除,再重启克隆的目的虚拟机

同时还需要修改虚拟机内对应网卡的ip, mac,与重启后新生成的/etc/udev/rules.d/70-persistent-net.rules中的MAC和设备号内容一致。

然后才能重启新建的虚拟机的网卡。

cat /etc/udev/rules.d/70-persistent-net.rules 
# PCI device 0x1af4:0x1000 (virtio-pci)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:3e:78:0d", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

vi /etc/sysconfig/network-scripts/ifcfg-eth0
修改ip
mac

重启network服务

其他管理例子

(1) 删除kvm虚拟机

# virsh undefine wintest01

说明:该命令只是删除wintest01的配置文件,并不删除虚拟磁盘文件。

(2) 重新定义虚拟机配置文件

通过导出备份的配置文件恢复原KVM虚拟机的定义,并重新定义虚拟机。

# mv /etc/libvirt/qemu/wintest02.xml /etc/libvirt/qemu/wintest01.xml
# virsh define /etc/libvirt/qemu/wintest01.xml

(3) 编辑KVM虚拟机配置文件

# virsh edit wintest01

virsh edit将调用vi命令编辑/etc/libvirt/qemu/wintest01.xml配置文件。也可以直接通过vi命令进行编辑,修改,保存。

可以但不建议直接通过vi编辑。

(1) 挂起服务器

# virsh suspend oeltest01

(2) 恢复服务器

# virsh resume oeltest01

导出KVM虚拟机配置文件

# virsh dumpxml wintest01 > /etc/libvirt/qemu/wintest02.xml

配置开机自启动虚拟机

# virsh autostart oeltest01

通过配置文件启动虚拟机

# virsh create /etc/libvirt/qemu/wintest01.xml

KVM虚拟机开机

# virsh start oeltest01

KVM虚拟机关机或断电

(1) 关机

默认情况下virsh工具不能对linux虚拟机进行关机操作,linux操作系统需要开启与启动acpid服务。在安装KVM linux虚拟机时必须在虚拟机内配置此服务。

# chkconfig acpid on
# service acpid restart

virsh关机

# virsh shutdown oeltest01

(2) 强制关闭电源

# virsh destroy wintest01

给每个虚拟机CPU,指定具体的物理机CPU pinning绑定亲和策略

<cputune>
        <vcpupin vcpu="0" cpuset="1-4,2"/>
        <vcpupin vcpu="1" cpuset="0,1"/>
        <vcpupin vcpu="2" cpuset="2,3"/>
        <vcpupin vcpu="3" cpuset="0,4"/>
</cputune>

or 

  <cputune>
    <vcpupin vcpu="0" cpuset="2"/>
    <vcpupin vcpu="1" cpuset="3"/>
    <vcpupin vcpu="2" cpuset="4"/>
    <vcpupin vcpu="3" cpuset="5"/>
    <vcpupin vcpu="4" cpuset="6"/>
    <vcpupin vcpu="5" cpuset="7"/>
    <vcpupin vcpu="6" cpuset="8"/>
    <vcpupin vcpu="7" cpuset="9"/>
    <vcpupin vcpu="8" cpuset="10"/>
    <vcpupin vcpu="9" cpuset="11"/>
  </cputune>

也可以使用emulatorpin的方式

emulatorpin 标签可以指定一个特定的物理CPU,使虚拟机使用的CPU和存储器都在一个物理机CPU内部

<cputune>
        <emulatorpin cpuset="1-3"/>
</cputune>

vcpu的设置

<vcpu placement='auto'>8</vcpu>
<vcpu placement='static' cpuset='0-10,5'>8</vcpu>
需要保持一致,配置的是物理CPU,配置的CPU的核,包括超线程产生的核; 使用static模式,也必须是; 也可以设置一个虚拟机给32个虚拟CPU,但是一开始只能使用8个,然后可以根据系统压力,热添加CPU给虚拟机。 ``` 32 ``` ### 使用cgoup cpuset限制KVM虚拟机对CPU的访问 使用vcpupin的效果可能不好,所以可以考虑cgroup的cpuset子系统。 ``` /cgroup/cpuset/libvirt/qemu ``` 在这个目录中,每个启动的虚拟机都有一个子目录,设置子目录中的cpuset.cpus即可。 例如, 设置kvm101虚拟机只能使用宿主机的1-10号核。 ``` cd /cgroup/cpuset/libvirt/qemu/kvm101 echo "1-10" > cpuset.cpus ``` ## 参考 http://www.tuicool.com/articles/7FVR32Y http://libvirt.org/formatdomain.html http://www.cnblogs.com/5201351/p/4461000.html Flag Counter ## [digoal's 大量PostgreSQL文章入口](https://github.com/digoal/blog/blob/master/README.md "22709685feb7cab07d30f30387f0a9ae")