KVM全虚拟化要点与优化

Posted 计算机ISO

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KVM全虚拟化要点与优化相关的知识,希望对你有一定的参考价值。

Linux KVM 全虚拟化

安装基本环境

  1. 安装软件包

  • Ubuntu/debian

    apt-get -y install qemu-kvm libvirt-bin virtinst bridge-utils

    可选:

    apt-get -y install virt-viewer libguestfs-tools uml-utilities virt-manager

  • rhel/centosyum -y install qemu-kvm libvirt libvirt-client bridge-utils virt-install

    可选:

    yum -y install virt-manager virt-viewer guestmount

  1. 添加libvirtd账号adduser root libvirtd  

  2. 检查安装情况  virsh -c qemu:///system list  


虚拟机操作  

创建虚拟机

eg:

virt-install -n nfv2 -r 102400 -c /public/ubuntu-14.04.3-server-amd64.iso --vcpus 56 --cpu Haswell,-rtm,-hle,+rdrand,+f16c --description "MEC VM" --disk path=/var/lib/libvirt/images/nfv1.img,size=100,format=qcow2 --network bridge=br0,model=e1000 --network bridge=br1,model=virtio --graphics vnc,listen=0.0.0.0 --host-device=pci_0000_81_00_0 
  • -n:虚拟机名

  • -c:指定 cdrom

  • –vcpus:指定虚拟 CPU 数量

  • –cpu Haswell,….:指定 CPU 架构以及启用各种特性

  • –description:虚拟机描述

  • –disk:指定虚拟机的虚拟硬盘

    • size:虚拟镜像容量,默认单位是 GB

    • format:虚拟镜像格式,可以是 raw, qcow2 等,详情查看 qemu-img 的 man 文档

  • –network:指定网络设备

    • bridge=br1,model=virtio:指定虚拟机中的网卡桥接到物理机的 br1 中,这个网卡的类型为 virtio(支持 dpdk)

  • -graphics:配置图形设备

  • –host-device:直接将物理机的硬件交给虚拟机管理使用

    • device=pci_000_81_00_0:这里的配置格式为bus_device_function,可以通过 “lspci | grep Eth” 查看, 加速卡可以通过 “lspci -nd 8086:0435” 查看。

    • bus 一般是 0000

    • 假如 “lspci -nd 8086:0435” 输出为:00:07.0 0b40: 8086:0435,则 device 是是 07,function 是 0

    • 最后的 –host-device=pci_0000_05_00_0 表示将 ipsec 加速卡给这台虚拟机独占使用  

复制虚拟机

eg:

virt-clone --connect=qemu:///system -o ltepc11vm1 -n ltepc11vm2 -f /var/lib/libvirt/images/ltepc11vm2_img


常用命令

创建一个 ubuntu 测试系统  

virt-install --name ltepc7vm1 -r 2048 --disk path=/var/lib/libvirt/images/ltepc7vm1_img,size=20 --vcpu=2 --os-type linux -w bridge=br0 -w bridge=br1, -w bridge=br2, -w bridge=br3 --virt-type kvm --cdrom=/public/ubuntu-14.04.3-server-amd64.iso

创建一个 rhel 系统  

virt-install --name nfv1ltepc35 -r 4096 --disk path=/var/lib/libvirt/images/nfv1ltepc35nfv1_img,size=100 --vcpu=2 --os-type linux --os-variant=rhel2.1 -w bridge=br0 -w bridge=br1, -w bridge=br2, -w bridge=br3, -w bridge=br4 --virt-type kvm --cdrom=/public/rhel-server-7.1-x86_64-dvd.iso

创建一个用于运行 NFV 的系统  

virt-install -n nfv2 -r 102400 -c /public/ubuntu-14.04.3-server-amd64.iso --vcpus 56 --cpu Haswell,-rtm,-hle,+rdrand,+f16c --description "Casa MEC VNF" --disk path=/var/lib/libvirt/images/nfv1.qco,size=200,format=qcow2 --network bridge=br0,model=e1000 --network bridge=br1,model=virtio --graphics vnc,listen=0.0.0.0 --host-device=pci_0000_81_00_0 

根据已有镜像文件直接创建运行 NFV 的系统

virt-install -n vm1 -r 24576 --vcpus 9 --cpu Haswell,-rtm,-hle,+rdrand,+f16c --description "Casa MEC VNF"  --network bridge=br0,model=e1000 --network bridge=br1,model=e1000 --network bridge=br2,model=e1000 --network bridge=br3,model=e1000 --graphics vnc,listen=0.0.0.0 --disk path=/var/lib/libvirt/images/vm1.qco --boot hd=/var/lib/libvirt/images/vm1.qco 

修改登录配置相关

sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config && echo "UseDNS no" >> /etc/ssh/sshd_config && service ssh restart

虚拟机日常操作  

  1. 启动/关闭  

virsh start vm1
   -- 启动虚拟机 vm1
virsh autostart vm1
   -- 设置 vm1 为开机启动
virsh destroy vm1
   -- 关闭 vm1,类似于断电关机
virsh reboot vm1
   -- 重启 vm1,如果是用 virsh edit 修改了 vm1 的配置,用这个方式重启虚拟机修改不会生效。需要 destroy 再 start
  1. 睡眠  

virsh suspend vm1
   -- 暂停虚拟机 vm1,相当于 sleep
virsh resume vm1
   -- 回复暂停的虚拟机 vm1
  1. 连接VM控制台  3.1 virt-viewer    virt-viewer 可以通过 X11 转发连接 VM,这里的 X11 转发是由服务器上将 VM 的控制台转发到本地的 X-SERVER。所以这个通信过程是由服务器端发起的,也即服务器需要能主动连接到客户 IP 才能使用这种方式。  在 VM 所在的 Host 上执行  

      virsh virt-viewer vm1
     -- 使用 virt-viewer 查看虚拟机 vm1

    3.2 vnc   要使用 VNC 功能,前提是在 VM 中配置了 VNC,注意一次只能有一个用户通过 VNC 方式连接到同一台 VM。 VNC 的方式是由用户使用的客户端去主动连接 VM 所在的 Host,所以不需要 Host 能主动连接客户端也可以使用。

    ubuntu 访问:    vncviewer x.x.x.x:0  如果提示没有 vncviewer 命令,可以安装 xvnc4viewer,这个应用提供了一个 vncviewer  apt-get install xvnc4viewer  

    VM配置VNC  

    <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
    <listen type='address' address='0.0.0.0'/>
    </graphics>

    或在使用 virt-install 命令创建 VM 时加入下面参数  --graphics vnc,listen=0.0.0.0. 3.3 virsh console. virsh console 可以让用户直接从 Host 连接到 VM 的 console,直接在控制台操作,不需要额外打开图形窗口。在 VM 所在的 Host 上执行:virsh console vm1  如果要结束连接,按 ctrl+] 退出

    Q:提示没有控制台A:在 host 执行  virsh edit vm1在虚拟机配置文件的 节点中添加

      <serial type='pty'>
       <target port='0'/>
     </serial>
     <console type='pty'>
       <target type='serial' port='0'/>
     </console>
      virsh destroy vm1
     virsh start vm1

    Q:可以连接但无法操作A:以下操作在 VM 内操作,由于 console 不能使用,此时需要使用 virt-viewer 来连接 VM 并登录进行操作。

    I. 从 tty1.conf 复制一个 ttyS0.conf,创建对应的 servicecp /etc/init/tty1.conf /etc/init/ttyS0.confII. 修改 ttyS0.confvi /etc/init/ttyS0.conf将 “exec /sbin/getty -8 38400 tty1” 修改为 “exec /sbin/getty -L 115200 ttyS0 xterm”III. 修改 /etc/default/grubvi /etc/default/grub添加 “console=ttyS0,115200” 到GRUB_CMDLINE_LINUX_DEFAULT 选项中,如下:GRUB_CMDLINE_LINUX_DEFAULT="console=ttyS0,115200"修改之后更新 grubupdate-grubIV. 重启reboot

  2. 配置每个虚拟机的配置文件都放在 /etc/libvirt/qemu/ 下同名的 xml 文件中,修改这个文件可以修改虚拟机的配置。需要注意的是,要使修改生效,需要在修改之后关闭虚拟机再 start 才会生效,直接在虚拟机内 reboot 是不会生效的。

virsh edit/undefine vpc
   -- 打开一个 vi 来修改 vpc 的配置文件,退出时会检查配置语法等。

 4.1 配置文件分析示例  以下是一个 KVM 虚拟机的 xml 配置文件。

  <domain type='kvm'>
 <name>henbgw</name> -- 虚拟机名字,也就是 donamin name,virsh define donamefile.xml 定义一台虚拟机的时候,定义的虚拟机名字就是从这里读取的
 <uuid>6abf3fc3-7ff4-0a59-820d-84ec203436aa</uuid> -- 每个虚拟机在创建的时候会生成唯一的 UUID
 <description>Casa VM CNE</description>
 <memory unit='KiB'>62914560</memory>
 <currentMemory unit='KiB'>62914560</currentMemory>
 <vcpu placement='static'>56</vcpu> -- 虚拟 CPU 核心数
 <os>
   <type arch='x86_64' machine='pc-i440fx-trusty'>hvm</type>
   <boot dev='hd'/> -- 表示从硬盘启动
 </os>
 <features>
   <acpi/>
   <apic/>
   <pae/>
 </features>
 <cpu mode='custom' match='exact'> -- 使用自定义的 CPU 模式
   <model fallback='allow'>Haswell</model> -- CPU 架构为 haswell
   <feature policy='force' name='f16c'/> -- 强制启用 f16c 特性
   <feature policy='force' name='rdrand'/>
   <feature policy='disable' name='hle'/> -- 禁用  hle 特性
   <feature policy='disable' name='rtm'/>
 </cpu>
 <clock offset='utc'/>
 <on_poweroff>destroy</on_poweroff>
 <on_reboot>restart</on_reboot>
 <on_crash>restart</on_crash>
 <devices>
   <emulator>/usr/bin/kvm-spice</emulator>
   <disk type='file' device='disk'> -- 配置磁盘
     <driver name='qemu' type='qcow2'/> -- 磁盘格式为 qcow2
     <source file='/var/lib/libvirt/images/henbgw.qco'/> -- 磁盘的文件
     <target dev='hda' bus='ide'/>
     <address type='drive' controller='0' bus='0' target='0' unit='0'/>
   </disk>
   <controller type='usb' index='0'>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
   </controller>
   <controller type='pci' index='0' model='pci-root'/>
   <controller type='ide' index='0'>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
   </controller>
   <interface type='bridge'> -- 配置网络接口,bridge 模式连接到 host
     <mac address='52:54:00:d6:a5:40'/> -- 自动生成的 mac 地址
     <source bridge='br0'/> -- 表示这个网络接口连接到 host 的 br0
     <model type='e1000'/> -- model 为 e1000
     <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> -- 自动生成的 pci 信息
   </interface>
   <interface type='bridge'>
     <mac address='52:54:00:79:91:42'/>
     <source bridge='br1'/>
     <model type='e1000'/>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
   </interface>
   <serial type='pty'>
     <target port='0'/>
   </serial>
   <console type='pty'>
     <target type='serial' port='0'/>
   </console>
   <input type='mouse' bus='ps2'/>
   <input type='keyboard' bus='ps2'/>
   <graphics type='vnc' port='-1' autoport='yes'/>
   <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>

 4.2 添加硬盘/cdrom  假设 VM 原有一块虚拟硬盘,文件名为 c0.qco,新添加的一块硬盘为 c0-1.qco  假设原有硬盘 c0.qco 在 VM 中的配置如下:

    <devices>
   <disk type='file' device='disk'>
     <driver name='qemu' type='qcow2'/>
     <source file='/var/lib/libvirt/images/c0.qco'/>
     <target dev='hda' bus='ide'/>
   </disk>
 </devices>

 则新添加的 VM 配置可以为:

    <devices>
   <disk type='file' device='disk'>
     <driver name='qemu' type='qcow2'/>
     <source file='/var/lib/libvirt/images/c0-1.qco'/>
     <target dev='hda' bus='ide'/>
     <address type='drive' controller='0' bus='1' target='0' unit='1'/>
   </disk>
   </devices>

 unit 区别于原有硬盘的 0,这个新添加的硬盘的 unit 为 1.

 添加完成后关闭虚拟机再开机。

 添加 cdrom

    <devices>
   <disk type='file' device='cdrom'>
     <driver name='qemu' type='raw'/>
     <source file='/var/lib/libvirt/images/casa-axyom-4.9.2-111.iso'/>
     <target dev='hdb' bus='ide'/>
     <readonly/>
   </disk>
 </devices>

 将该 cdrom 作为启动盘

    <os>
   <boot dev='cdrom'/>
   <boot dev='hd'/>
 </os>
  <interface type='bridge'>
 <source bridge='br0'/>
 <model type='virtio'/>
 </interface>

 添加完成后关闭虚拟机再开机。

 4.4 添加 Passthrough PCI 设备

    <devices>
 ....
   <hostdev mode='subsystem' type='pci' managed='yes'>
     <source>
       <address domain='0x0000' bus='0x81' slot='0x00' function='0x3'/>
     </source>
   </hostdev>
 ....
   </devices>

 4.5  配置多个 NUMA 节点  在物理机上用 virsh edit xxx(xxx 为虚拟机名)打开配置文件,在 子节点内添加 配置。

    <cpu>
   ...
   <numa>
     <cell cpus='0-27' memory='31457280'/>
     <cell cpus='28-55' memory='31457280'/>
   </numa>
   ...
   </cpu>

 注意:

  1. 所有 numa 节点分配的内存加起来应该等于该 VM 的总内存,否则会被忽略 numa 配置

  2. memory 的单位和配置文件中 currentMemory 相同,都是 KiB

  3. 在 host 上用 virsh edit xxx (xxx 为虚拟机名)修改后,需要 virsh destroy xxx && virsh start xxx 才生效

  4. 检查是否生效:在 VM 内用 lscpu 检查,在最后几行会列出 NUMA node 信息

  5. 如果要配置以逗号分隔的语法指定的 CPU NUMA 节点,ubuntu 14.04 默认安装的 libvirt 会构造出错误的 qemu 命令导致无法启动 VM,提示如下:error: unsupported configuration: disjoint NUMA cpu ranges are not supported with this QEMU

 4.6 配置 CPU pin

    <cputune>
   <vcpupin vcpu='0' cpuset='0'/>
   <vcpupin vcpu='1' cpuset='1'/>
   </cputune>

 4.7 配置 memory backend

    <domain>
   ....
   <memoryBacking>
     <hugepages/>
       <page size="1" unit="G" nodeset="0-3,5"/>
       <page size="2" unit="M" nodeset="4"/>
     </hugepages>
   </memoryBacking>
   ....
   </domain>
  1. 删除虚拟机

virsh undefine vpc
rm vpc_img(一般vpc的img默认地址为 /var/lib/libvirt/images/)
cd /var/lib/libvirt/images && virsh pool-refresh default
  1. 取消开机自启动删除 /etc/libvirt/qemu/autostart/ 目录下的对应虚拟机的XML文件

  2. 虚拟机镜像以下所有操作,都可以用 qemu-img 替代 kvm-img7.1 创建镜像

    kvm-img create -f format file size 
    e.g
    kvm-img create -f qcow2 vm_base.qco 100G
    -- 创建一个格式为 qcow2,大小为 100G,文件名为 vm_base.qco 的镜像

    7.2 查看镜像信息

    qemu-img info vm_base.qco
     -- 查看镜像信息
    ll -sh
     -- 查看镜像实际占用的磁盘空间

    7.3 修改镜像容量这里的修改镜像容量指的是修改镜像文件的大小限制,也就是虚拟机内看到的磁盘大小,而不是其实际占用的物理机上的磁盘空间。

    减小容量之前,需要先在虚拟机上缩小分区,将需要缩小的容量空出来,然后再在物理机上进行缩小,否则可能会导致数据丢失。

    增加容量之后,还需要到虚拟机上对新增加出来的磁盘进行分区,格式化,挂载,之后才能正常使用。

    qemu-img resize vm_base.qco 100G
     -- 将 vm_base.qco 的容量大小重新设置为 100G
    qemu-img resize vm_base.qco +80G
     -- vm_base.qco 的容量增加 80G
    qemu-img resize vm_base.qco -80G
     -- vm_base.qco 的容量减少 80G

    7.4 镜像格式转换

    kvm-img convert -f in_format -O out_format src_file dst_file
    e.g
    kvm-img convert -f raw -O qcow2 vm_base.img vm_base.qco

    7.5 创建 copy-on-write 镜像  写时复制镜像可以允许多个虚拟机镜像基于同一个基础镜像,这样可以节省磁盘空间,可以快速地安装虚拟机,并提供类似快照的功能等。

    kvm create -f out_format -b base_file out_file
    e.g
    kvm-img create -f qcow2 -b vm_base.qco test.qco
     -- 根据 vm_base.qco 文件创建格式为 qcow2,名为 test.qco 的 copy-on-write 镜像

    7.6 压缩镜像释放稀疏特性占用的空间

    qemu-img convert -cp -O qcow2 henbgw.qco compressd_henbgw.qco

    7.7 宿主机中挂载虚拟机(vm1)镜像Host 安装所需软件:apt-get install -y libguestfs-tools注意:所有的挂载操作,在操作之前必须先关闭或暂停虚拟机,以避免在挂载之后 VM 仍然向其磁盘写入数据。 操作完成之后必须卸载,然后才能启动虚拟机,否则可能导致不可预知的错误。

     7.7.1 查看镜像中的文件系统  要挂载镜像中的文件系统,如果不是使用 -i 选项自动挂载,想要指定挂载某一个分区,则需要先确定有哪些文件系统,virt-filesystems 可以用来查看镜像中的文件系统:

      # virt-filesystems -a vm1.qco
     /dev/sda1
     /dev/sda2

     如果有多个磁盘,则可以通过多个 -a 选项添加:

      # virt-filesystems -a vm1.qco -a extend.qco
     /dev/sda1
     /dev/sda2
     /dev/sdb1

     7.7.2 通过 VM 挂载:  以下步骤在 Host 中操作

      virsh destroy vm1
     -- 关闭虚拟机 vm1
     mkdir vm1_fs
     guestmount -d vm1 -i --rw ./vm1_fs
         -- 挂载 vm1 的根目录到刚创建的 vm1_fs 目录下,以可读写的方式

     7.7.3 直接挂载镜像  guestmount 也可以直接挂载镜像,而不需要依赖该镜像的 VM。

      guestmount -a vm1.qco -m /dev/sda1 vm1_fs
     -- 将 vm1.qco 内的 /dev/sda1 分区挂载 vm_fs,这里的 /dev/sda1 是 vm1.qco 这个镜像内记录的磁盘分区,也即在 VM 里边看到的那个分区,而不是 Host 上的

     如果要挂载的磁盘里边没有系统,则可以使用给一个包含系统的磁盘来挂载这个虚拟磁盘。下面的示例中,vm1.qco 内是有系统的,extend.qco 中不包含系统,则可以通过下列命令挂载 extend.qco 到 temp 目录。  guestmount -a vm1.qco -a extend.qco -m /dev/sdb1 temp  7.7.4 卸载

      guestunmount ./vm1_fs
     -- 卸载挂载到 ./vm1_fs 目录的镜像

     Q:libguestfs: error: /usr/bin/supermin-helper exited with error status 1.  A:更新 guestfs 相关的应用:  update-guestfs-appliance  Q:挂载是提示 invalid argument

      # guestmount -a onie-x86-vm.img -a extend.img -m /dev/sdb1 temp 
     fuse: failed to access mountpoint temp: Invalid argument
     libguestfs: error: fuse_mount: temp: Invalid argument

     A:用 ls temp 查看 temp 目录,提示 “ls: cannot access temp: Invalid argument” 的错误,

     先尝试 guestunmount temp,然后再重新挂载,guestunmount 可能会提示 failed,但这时候查看 temp 目录如果可以不提示错误,则可以继续挂载。

    7.9 重构镜像的 backing file将 filename 的 backing file 修改为 backing_file。前提是 filename 文件格式支持,目前只有 qcow2 和 qed 格式支持。如果将 backing_file 为 “”,也即不指定文件,则 filename 将会不再有 backing file,原来在 backing file 中的数据会整合到 filename 文件中。rebase -p -f qcow2 [-u] -b backing_file filename

    • -c 指定压缩镜像

    • -p 输出进度

    • -O 输出格式

    • henbgw.qco 待转换文件

    • compressed_henbgw.qco 转换输出文件

  3. 快照 raw 格式的镜像不支持快照功能,qcow2 格式支持。另外 lvm 分区可以用 lvm 快照。 虚拟机的快照文件保存在 /var/lib/libvirt/qemu/snapshot,也可以通过 qemu-img info xxx 命令查看具体的 qcow2 格式的镜像文件来查看快照。常用命令:

virsh snapshot-list vm_name
   -- 查看虚拟机 vm_name 的快照列表
virsh snapshot-create vm_name
   -- 为虚拟机 vm_name 创建一个快照
virsh snapshot-current vm_name
   -- 查看虚拟机 vm_name 当前的快照
virsh snapshot-revert vm_name snapshot_name
   -- 将虚拟机 vm_name 恢复到指定的快照
virsh snapshot-info snapshot_name vm_name
   -- 查看虚拟机 vm_name 的 snapshot_name 的详细信息
snapshot-delete <domain> [<snapshotname>] [--current] [--children] [--children-only] [--metadata]
   -- 删除虚拟机 domain 的快照,可以指定 snapshotname,或当前快照或子快照等
snapshot-parent <domain> [<snapshotname>] [--current]
   -- 查看虚拟机 domain 的名为 snapshotname 的快照是由哪个快照创建来的

eg:以下命令以名为 vm 的虚拟机为例:

virsh snapshot-create vm
virsh snapshot-list vm
virsh snapshot-revert vm 1476407045
virsh snapshot-current vm
virsh snapshot-info vm 1476407045
virsh snapshot-delete vm 1476407045
virsh snapshot-parent vm 1476407045
virsh snapshot-parent vm --current

查看说明

root@qmec30:~# virsh snapshot-list vm
Name                 Creation Time             State
------------------------------------------------------------
1480835894           2015-12-04 02:18:14 -0500 shutoff
  • Name: 快照名

  • State: 创建快照时这个虚拟机的状态

snapshot 的全部命令

snapshot-create   
snapshot-create-as
snapshot-current  
snapshot-delete  
snapshot-dumpxml  
snapshot-edit    
snapshot-info    
snapshot-list    
snapshot-parent  
snapshot-revert  
  1. 暂停和恢复

virsh suspend vm1
virsh resume vm1
  1. Host/Guest 共享目录直接将 Host 中的一个目录共享给 Guest,使用这个目录来保存需要经常修改的数据,可以避免虚拟机的镜像随着使用而增大体积的问题。另外,在 Guest 中往共享的目录写入数据比直接往虚拟镜像中写入数据性能要高。

Host 中配置在 VM 的 domain file 中的 device 标签内添加:

    <filesystem type='mount' accessmode='passthrough'>
     <driver type='path'/>
     <source dir='/public/zpt'/>
     <target dir='/media/host'/>
   </filesystem>
  • source dir 表示 Host 中要共享的目录,这里配置了 /public/zpt 之后,如果没有这个目录会导致虚拟机启动失败。

  • target dir 表示在虚拟机中的挂载点,并不需要真的有这个目录

Guest 中挂载在虚拟机中执行下面的命令挂载共享目录到 /mnt:mount -t 9p -o trans=virtio,version=9p2000.L,rw /media/host /mnt如果要开机自动挂载,则在 /etc/fstab 中添加一行:/media/host               /mnt    9p      trans=virtio,version=9p2000.L,rw  0   0注意如果在虚拟机中使用这个共享目录时无法创建文件的话,可能原因是改虚拟机进程的用户是 libvirt-qemu,需要使用 root 用户来启动虚拟机进程,但用 root 用户来启动虚拟机进程有一定的风险

配置方式如下: 在 /etc/libvirt/qemu.conf 文件中添加下面两行配置:user = "root"检查当前环境是否是 VM如果是基于 QEMU 的 VM,Manufacturer 会显示为 QEMU

# dmidecode -t system
# dmidecode 2.12
SMBios 2.8 present.
Handle 0x0100, DMI type 1, 27 bytes
System Information
   Manufacturer: QEMU
   ...

虚拟机的迁移

  1. 根据已有的硬盘文件新建虚拟机i. 复制已有的虚拟机镜像文件 ii. 使用已有的虚拟机镜像文件作为硬盘文件,并将其制定为启动盘,命令示例:

    virt-install -n vm3 -r 4096 --vcpus 2 --description "Casa VM CNE" --network bridge=br0,model=e1000 --network bridge=br1,model=e1000 --graphics vnc,listen=0.0.0.0 --disk path=/var/lib/libvirt/images/vm1.img --boot hd=/var/lib/libvirt/images/vm1.img
  • –boot hd=xxx:指定虚拟机启动文件

  1. 使用 kvm 自带的 migrate 自动迁移migrate --direct --verbose vm1 root@172.0.5.15:/var/lib/libvirt/ test-migrate动态迁移迁移只是将虚拟机的 CPU 和内存等状态迁移过去,并不会迁移镜像文件,并且迁移过去之后只是启动一个运行实例,并不会将该实例在对端设备上定义为一个 domain

复制镜像文件,在源主机上执行scp /var/lib/libvirt/images/web.qco root@172.0.5.75:/var/lib/libvirt/images/web.qco动态迁移,在源主机上执行virsh migrate web qemu+ssh://172.0.5.75/system --live tcp://172.0.5.75:55555 --verbose将迁移过来的实例定义为一个 domain,在目标主机上执行:

virsh xmldump web > /etc/libvirt/qemu/web.xml
virsh destroy web
virsh define /etc/libvirt/qemu/web.xml

passthrough

vm 直接控制硬件资源,以独占的方式。通过 passthrough 将网口分配给 vm 之后,ifconifg -a 将看不到该网口,该网口在物理机不可用。

  1. 宿主机启用 iommuvi /etc/default/grub 修改 GRUB_CMDLINE_LINUX_DEFAULT 选项,加入 intel_iommu=on,改后如下: GRUB_CMDLINE_LINUX_DEFAULT=”… intel_iommu=on “

  2. 执行 update-grub 更新 grub 配置以生效

  3. 重启宿主机系统

lspci | grep Eth
....
81:00.3 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
....

5.1 向已有的虚拟机 vm1 中添加 pci 设备

手动编辑虚拟机定义文件,添加节点:
virsh edit vm1
    <hostdev mode='subsystem' type='pci' managed='yes'>
     <source>
       <address domain='0x0000' bus='0x81' slot='0x00' function='0x3'/>
     </source>
   </hostdev>

5.2 在创建虚拟机的时候使用 pci 设备

virt-install -n nfv1 -r 102400 -c /public/ubuntu-14.04.3-server-amd64.iso --vcpus 56 --cpu Haswell,-rtm,-hle,+rdrand,+f16c --description "Casa MEC VNF" --disk path=/var/lib/libvirt/images/nfv1.img,size=100 --network bridge=br0,model=e1000 --network bridge=br1,model=virtio --graphics vnc,listen=0.0.0.0 --host-device=pci_0000_81_00_3

嵌套虚拟机(nested)

VMware ESXi 虚拟机上可以运行 KVM,在 KVM 虚拟机上同样可以运行 KVM,实现嵌套 KVM 虚拟机。

在较新(2017-5)的 KVM 性能测试中,经过调整后,第一层 KVM 的性能可以达到 host 的 95% 左右,第二层则只有不到 70% 左右了,所以潜逃虚拟机对性能的影响还是非常严重。


  1. 检查 nested 是否开启nested 功能在加载 kvm_intel 模块的时候默认是开启的,其是否开可以通过查看文件 /sys/module/kvm_intel/parameters/nested 得知,如果该文件内容为 Y 则为开启,为 N 则为关闭。

  cat  /sys/module/kvm_intel/parameters/nested
 Y
  1. 开启 nested如果 nested 功能未开启,首先在 KVM host 上开启 nested 功能。

  modprobe -r kvm_intel
 modprobe kvm_intel nested=1
 cat /sys/module/kvm_intel/parameters/nested
 Y
  1. 修改虚拟机 domain file 以启用 vt-x 特性virsh edit vm_name 修改指定虚拟机的 domain file,加入 vmx 选项

  ...
 <cpu mode='custom' match='exact'>
   <model fallback='allow'>Haswell</model>
   <feature policy='require' name='vmx'/>
 </cpu/>
 ...


  1. 检查是否生效启动虚拟机后,进入虚拟机查看是否可用

kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used

CPU Virtualization

lscpu | grep -i virtual
Virtualization:        VT-x
Virtualization type:   full

如果看到以上输出则说明可以在这个 KVM 虚拟机中运行其它的 KVM 虚拟机~

性能

监控 perf可以使用带有 kvm 选项的 perf 命令,从主机收集客机运行系统的统计数据。 详情参考

CPUlibvirt 关于 CPU 的定义可以参考 /usr/share/libvirt/cpu_map.xml。 KVM 下的 CPU 配置模式主要有三种,在兼容性,性能等方面各有取舍。

  1. custom(自定义)完全自定义的模式,可以在迁移的时候保证在不通的宿主机中保证兼容性。 xml 文件配置:

  <cpu mode='custom' match='exact'>
   <model fallback='allow'>Haswell</model>
   <feature policy='force' name='f16c'/>
   <feature policy='force' name='rdrand'/>
   <feature policy='disable' name='hle'/>
   <feature policy='disable' name='rtm'/>
 </cpu>
  1. host-model这是默认的 CPU 模式,该模式会根据 host 的物理 CPU 特性,选择一个最靠近的标准 CPU 型号。 xml 文件配置

<cpu mode='host-model' />

  1. host-passthrough该模式直接将 CPU 暴露给虚拟机使用,需要注意的是使用该模式的虚拟机无法直接迁移到 CPU 型号不同的 host 上运行。 xml 文件配置:<cpu mode='host-passthrough'/>

  2. cpupin将虚拟机的 CPU 和物理机上的 CPU 绑定起来,可以避免虚拟机中的 CPU 调度和物理机中的不一致导致的性能损耗。 示例配置:

<vcpu placement='static'>56</vcpu>
 <cputune>
   <vcpupin vcpu='0' cpuset='0'/>
   <vcpupin vcpu='1' cpuset='1'/>
   <vcpupin vcpu='2' cpuset='2'/>
   <vcpupin vcpu='3' cpuset='3'/>
   <vcpupin vcpu='4' cpuset='4'/>
   <vcpupin vcpu='5' cpuset='5'/>
   <vcpupin vcpu='6' cpuset='6'/>
   <vcpupin vcpu='7' cpuset='7'/>
   <vcpupin vcpu='8' cpuset='8'/>
   <vcpupin vcpu='9' cpuset='9'/>
   <vcpupin vcpu='10' cpuset='10'/>
   <vcpupin vcpu='11' cpuset='11'/>
   <vcpupin vcpu='12' cpuset='12'/>
   <vcpupin vcpu='13' cpuset='13'/>
   <vcpupin vcpu='14' cpuset='14'/>
   <vcpupin vcpu='15' cpuset='15'/>
   <vcpupin vcpu='16' cpuset='16'/>
   <vcpupin vcpu='17' cpuset='17'/>
   <vcpupin vcpu='18' cpuset='18'/>
   <vcpupin vcpu='19' cpuset='19'/>
   <vcpupin vcpu='20' cpuset='20'/>
   <vcpupin vcpu='21' cpuset='21'/>
   <vcpupin vcpu='22' cpuset='22'/>
   <vcpupin vcpu='23' cpuset='23'/>
   <vcpupin vcpu='24' cpuset='24'/>
   <vcpupin vcpu='25' cpuset='25'/>
   <vcpupin vcpu='26' cpuset='26'/>
   <vcpupin vcpu='27' cpuset='27'/>
   <vcpupin vcpu='28' cpuset='28'/>
   <vcpupin vcpu='29' cpuset='29'/>
   <vcpupin vcpu='30' cpuset='30'/>
   <vcpupin vcpu='31' cpuset='31'/>
   <vcpupin vcpu='32' cpuset='32'/>
   <vcpupin vcpu='33' cpuset='33'/>
   <vcpupin vcpu='34' cpuset='34'/>
   <vcpupin vcpu='35' cpuset='35'/>
   <vcpupin vcpu='36' cpuset='36'/>
   <vcpupin vcpu='37' cpuset='37'/>
   <vcpupin vcpu='38' cpuset='38'/>
   <vcpupin vcpu='39' cpuset='39'/>
   <vcpupin vcpu='40' cpuset='40'/>
   <vcpupin vcpu='41' cpuset='41'/>
   <vcpupin vcpu='42' cpuset='42'/>
   <vcpupin vcpu='43' cpuset='43'/>
   <vcpupin vcpu='44' cpuset='44'/>
   <vcpupin vcpu='45' cpuset='45'/>
   <vcpupin vcpu='46' cpuset='46'/>
   <vcpupin vcpu='47' cpuset='47'/>
   <vcpupin vcpu='48' cpuset='48'/>
   <vcpupin vcpu='49' cpuset='49'/>
   <vcpupin vcpu='50' cpuset='50'/>
   <vcpupin vcpu='51' cpuset='51'/>
   <vcpupin vcpu='52' cpuset='52'/>
   <vcpupin vcpu='53' cpuset='53'/>
   <vcpupin vcpu='54' cpuset='54'/>
   <vcpupin vcpu='55' cpuset='55'/>
 </cputune>
  1. NUMA 平衡策略linux 默认是开启了 NUMA 的平衡策略的,可以通过下面的方式查看具体是否开启:

cat /proc/sys/kernel/numa_balancing
1
root@lte:~# numastat -c qemu-system-x86_64
Per-node process memory usage (in MBs)
PID              Node 0 Node 1 Total
---------------  ------ ------ -----
3028 (qemu-syste     90    461   550
3242 (qemu-syste    425    123   548
3317 (qemu-syste    244    301   545
3394 (qemu-syste   1308    655  1963
3467 (qemu-syste    578    142   720
3538 (qemu-syste    349    196   545
3622 (qemu-syste    893  60616 61509
13059 (qemu-syst   7536    792  8328
48266 (qemu-syst   3460   1544  5004
---------------  ------ ------ -----
Total             14884  64827 79711
root@lte:~#

配置多个 NUMA 节点下面的示例配置中给该虚拟机配置乐乐两个 NUMA 节点,分别指定了 0-27 和 28-55 的 CPU 作为两个 node 的 CPU,memory 是分配每个 node 的内存,这些内存以 KiB 为单位,和 memory 的单位一样。

  <cpu>
   <numa>
     <cell cpus='0-27' memory='31457280'/>
     <cell cpus='28-55' memory='31457280'/>
   </numa>
 </cpu>

内存

  1. hugepageskvm 虚拟机要使用 hugepages 的话,需要在物理机中配置 hugepages,并且物理机中配置的 hugepages 大小要大于虚拟机的总内存大小,而不是虚拟机内所使用的 hugepages 的大小。

i. 物理机中配置 hugepagesubuntu 14.04 默认的 hugepage size 为 2MB。

echo vm.nr_hugepages=xxx >> /etc/sysctl.conf
   -- xxx 为 hugepages 的数量,即 hugepage 的总大小为这个数量 * 2MB。
sysctl -p
   -- 使配置立即生效

ii. 指定虚拟机使用 hugepagesvirsh edit vm,加入下列配置项:

  <memoryBacking>
   <hugepages/>
 </memoryBacking>

如果 host 支持 NUMA,则需要根据 NUMA 状况进行配置,在以下示例中,客机 NUMA 节点 0-5(不包括 NUMA 节点 4)将会使用 1 GB 的大页面,客机 NUMA 节点 4 将使用 2 MB 的大页面,无论客机 NUMA 节点在主机的任何位置。

<memoryBacking>
       <hugepages/>
         <page size="1" unit="G" nodeset="0-3,5"/>
         <page size="2" unit="M" nodeset="4"/>
       </hugepages>
</memoryBacking>

常见错误处理

Q:执行virsh list 提示错误

error: failed to connect to hypervisor
error: no valid connection
error: failed to connect socket to '/var/run/libvirt/libvirt-sock': No such file or directory

A:

service libvirt-bin status
service libvirt-bin start

如果启动服务失败或启动成功后仍然不行,尝试重装 libvirt0 和 libvirt-bin

apt-get remove -y libvirt0 libvirt-bin
apt-get install -y libvirt0 libvirt-bin

Q:virsh start ltepc6vm1 提示

error: Failed to start domain ltepc6vm1
error: internal error: Process exited while reading console log output: char device redirected to /dev/pts/6 (label charserial0)
Could not access KVM kernel module: Permission denied
failed to initialize KVM: Permission denied

A:

chown root:kvm /dev/kvm

Q:Cannot find suitable CPU model for given data

root@LTEMEC13:/etc/libvirt/qemu# virsh start nfv1
error: Failed to start domain nfv1
error: internal error: Cannot find suitable CPU model for given data

A:

rm -rf /var/cache/libvirt/qemu/capabilities/*
reboot

或卸载所有和虚拟机有关的软件再重装。

Q:创建一个之前已创建过的同名虚拟机时提示

ERROR    cannot stat file '/var/lib/libvirt/images/ltepc35nfv1_img ': No such file or directory 

A:这个问题的原因是用户直接手动删除了磁盘中的镜像文件但没有刷新 kvm 的存储池

virsh pool-refresh default

Q:提示不支持 hvm

ERROR   No domains available for virt type 'hvm', arch 'x86_64', domain type 'kvm'

A:在 Intel CPU 的设备上,需要打开 Intel 虚拟化功能才能支持 ‘hvm’,可以通过查看 CPU feature 的方式来检查cat /proc/cpuinfo | grep vmx    -- 这里有输出的话则说明已开启 Intel 虚拟化功能,否则说明没有开启。如果没有开启,则需要在 bios 中打开这个功能。Q:提示设备类型不支持

virsh start vsgw 
error: Failed to start domain vsgw
error: internal error: process exited while connecting to monitor: 2017-07-27T03:16:14.721195Z qemu-system-x86_64: -enable-kvm: unsupported machine type
Use -machine help to list supported machines

这个问题可能是升级了 kvm 但升级不彻底导致的,undefine 虚拟机之后重新创建可以绕过这个问题。

virsh undefine vsgw
virt-install -n vsgw -r 6144 --vcpus 8 --cpu Haswell,-rtm,-hle,+rdrand,+f16c --description "SGW of VEPC Base" --disk path=/var/lib/libvirt/images/vsgw.qco --network bridge=br0,model=e1000 --network bridge=br1,model=e1000 --graphics vnc,listen=0.0.0.0 --boot hd=/var/lib/libvirt/images/vsgw.qco

其他

  1. 查看支持的系统

virt-install --os-variant list

–os-variant=DISTRO_VARIANT The OS variant being installed guests, e.g. ‘fedora6’, ‘rhel5’, ‘solaris10’, ‘win2k’

  1. 网桥配置示例

root@ltepc11:/# vi /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto em1
iface em1 inet manual
auto p4p1
iface p4p1 inet manual
# bridge interfaces
auto br0
iface br0 inet static
    address 172.0.5.75
    netmask 255.255.255.0
    gateway 172.0.5.1
    # dns-* options are implemented by the resolvconf package, if installed
    dns-nameservers 8.8.8.8
    bridge_ports em1
       bridge_stp off
       bridge_fd 0
       bridge_maxwait 0
auto br1
iface br1 inet static
       address 172.1.1.75
       netmask 255.255.255.0
       bridge_ports p4p1
       bridge_stp off
       bridge_fd 0
       bridge_maxwait 0




以上是关于KVM全虚拟化要点与优化的主要内容,如果未能解决你的问题,请参考以下文章

KVM虚拟化网络优化技术总结

KVM虚拟化的优化

实操KVM虚拟机的优化历程---按需优化

KVM命令--优化篇

KVM性能优化

实操干货KVM命令管理虚拟机与性能优化