linux kvm 虚拟化

qemu 、KVM

QEMU的缺点是因为是纯软件模拟,所有非常慢。QEMU 1.0的时候有一个QEMU和KVM结合的分支。KVM只是一个内核的模块,没有用户空间的管理工具,KVM的虚拟机可以借助QEMU的管理工具来管理。QEMU也可以借助KVM来加速,提升虚拟机的性能。QEMU-KVM的分支版本发布了3个正式的版本1.1、1.2、1.3,随后和QEMU的主版本合并,也就是说现在的QEMU版本默认支持KVM,QEMU和KVM已经紧密地结合起来了。

KVM的最后一个自己的版本是KVM 83,随后和内核版本一起发布,和内核版本号保持一致,所以要使用KVM的最新版本,就要使用最新的内核。

Libvirt

Libvirt是一套开源的虚拟化的管理工具,主要由3部分组成:

·一套API的lib库,支持主流的编程语言,包括C、Python、Ruby等。

·Libvirtd服务。

·命令行工具virsh。

Libvirt的设计目标是通过相同的方式管理不同的虚拟化引擎,比如KVM、Xen、HyperV、VMware ESX等。但是目前实际上多数场景使用Libvirt的是KVM,而Xen、HyperV、VMware ESX都有各自的管理工具。

Libvirt可以实现对虚拟机的管理,比如虚拟机的创建、启动、关闭、暂停、恢复、迁移、销毁,以及虚拟机网卡、硬盘、CPU、内存等多种设备的热添加。

Libvirt还支持远程的宿主机管理,只要在宿主机上启动Libvirtd服务并做好配置,就可以通过Libvirt进行虚拟机的配置。通道可以是以下方式:

·SSH。

·TCP。

·基于TCP的TLS。

Libvirt将虚拟机的管理分为以下几个方面:

第一,存储池资源管理,支持本地文件系统目录、裸设备、lvm、nfs、iscsi等方式。在虚拟机磁盘格式上支持qcow2、vmdk、raw等格式。

第二,网络资源管理,支持Linux桥、VLAN、多网卡绑定管理,比较新的版本还支持Open vSwitch。Libvirt还支持nat和路由方式的网络,Libvirt可以通过防火墙让虚拟机通过宿主机建立网络通道,和外部的网络进行通信。

开启CPU 虚拟化技术

在BIOS中开启CPU虚拟化技术,intel 的相关名称是 vmx, vt-x, vt-d, AMD 的相关名称是 SVM。

egrep '(vmx|svm)' /proc/cpuinfo 有输出内容,说明CPU支持虚拟化。

宿主机环境配置

centos 6.6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost ~]# rpm -qa|grep -E 'qemu|libvirt|virt' 

libvirt-client-0.10.2-29.el6.x86_64 
#Libvirt的客户端,最重要的功能之一就是就在宿主机关机时可以通知虚拟机也关机,
#使虚拟机系统正常关机,而不是被强制关机,造成数据丢失

gpxe-roms-qemu-0.9.7-6.10.el6.noarch #虚拟机iPXE的启动固件,支持虚拟机从网络启动

libvirt-python-0.10.2-29.el6.x86_64   #libvirt为Python提供的API
python-virtinst-0.600.0-18.el6.noarch  #一套Python的虚拟机安装工具

qemu-KVM-0.12.1.2-2.415.el6.x86_64 #KVM在用户空间运行的程序

Virt-manager-0.9.0-19.el6.x86_64  #基于 Libvirt 的图像化虚拟机管理软件

libvirt-0.10.2-29.el6.x86_64   #用于管理虚拟机,它提供了一套虚拟机操作API
virt-viewer-0.5.6-8.el6.x86_64  #显示虚拟机的控制台console
virt-top-1.0.4-3.15.el6.x86_64  #类似于top命令,查看虚拟机的资源使用情况
virt-what-1.11-1.2.el6.x86_64  #在虚拟机内部执行,查看虚拟机运行的虚拟化平台

qemu-img-0.12.1.2-2.415.el6.x86_64  #用于操作虚拟机硬盘镜像的创建、查看和格式转化

centos 7

1
2
3
4
5
6
7
8
[root@KVM-host-CentOS7 ~]# rpm -qa | grep -E 'qemu-img|libvirt-[0-9]|virt-install'
qemu-img-1.5.3-60.el7_0.10.x86_64
virt-install-0.10.0-20.el7.noarch
libvirt-1.1.1-29.el7_0.3.x86_64

[root@KVM-host-CentOS7 ~]# lsmod |grep KVM  #查看KVM模块是否载入
KVM_intel 138567  6 
KVM 441119  1 KVM_intel

Libvirt还包含了很多工具的库,可以使用yum install libvirt*命令安装。

Libvirt及guestfish相关的工具在平时的运维过程中经常会用到,建议使用yum install libguest* libvirt*命令安装。

入门: 安装环境、创建第一个虚拟机

  1. BIOS 开启 CPU 的虚拟化支持。
  2. 安装 qemu、libvirt和其他需要的组件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     pacman -Sy --needed \
       qemu \
       dhclient \
       openbsd-netcat \
       virt-viewer \
       libvirt \
       dnsmasq \
       dmidecode \
       ebtables \
       virt-install \
       virt-manager \
       bridge-utils
    
  3. 调整执行权限

    方便 libvirt 的工具 default to qemu:///system ,否则缺省使用 qemu:///session

    1
    2
     sudo cp -rv /etc/libvirt/libvirt.conf ~/.config/libvirt/ &&\
     sudo chown ${YOURUSER}:${YOURGROUP} ~/.config/libvirt/libvirt.conf
    
    1
     usermod -a -G polkit,wheel your-user-name
    

    edit /etc/polkit-1/rules.d/50-libvirt.rules

    1
    2
    3
    4
    5
    6
    7
    8
     /* Allow users in wheel group to manage the libvirt
     daemon without authentication */
     polkit.addRule(function(action, subject) {
         if (action.id == "org.libvirt.unix.manage" &&
             subject.isInGroup("wheel")) {
                 return polkit.Result.YES;
         }
     });
    

    修改完,注销重新登陆, 或者重启 libvirtd

  4. 配置、启动 libvirtd

    1
    2
     sudo systemctl start libvirtd
     sudo systemctl enable libvirtd
    

    libvirt keeps its files at /var/lib/libvirt/

    images目录是 VM磁盘镜像 的默认存放目录。

  5. 创建一个虚拟机

    • 使用 virt-manager 图形界面创建
      1. 启动 virt-manager 出现GUI的管理界面。
      2. 点击 Create a new virtual machine
      3. 选择 Local install media ,添加新的 Storage Pool 到 存放iso的地方,选中需要的系统安装iso文件
      4. 设置系统的名称、CPU、内存、磁盘、网络(可以先选择 NAT)
      5. 点击 完成 后, virt-viewer 会弹出来现实安装进度。
    • 使用 virt-install 安装

      1
      2
      3
      4
      5
      6
      7
      8
      9
        virt-install \
          --name ubuntu1804 \
          --ram 2048 \
          --disk path=/var/lib/libvirt/images/u19.qcow2,size=8 \
          --vcpus 2 \
          --os-type linux \
          --os-variant generic \
          --console pty,target_type=serial \
          --cdrom /var/lib/libvirt/isos/ubuntu-18.04.4-live-server-amd64.iso
      

入门:第一台虚拟机安装

使用 Virt-Manager 图形化管理工具

  1. 安装 virt-manager

    1
    2
     # CentOS 6.5
     yum groupinstall -y "Desktop" "Desktop Platform" "Desktop Platform Development" "Fonts" "General Purpose Desktop" "Graphical Administration Tools" "Graphics Creation Tools" "Input Methods" "X Windows System" "Chinese Support[zh]" "Internet Browser"
    
  2. 安装 VNC 连接宿主机图形界面

    1
     yum install -y tigervnc tigervnc-server
    

    vim /etc/sysconfig/vncservers

    1
    2
     VNCSERVERS="1:root"
     VNCSERVERARGS[2]="-geometry 800x600 -nolisten tcp -localhost"
    

    使用 vncpasswd 设置登陆密码

    启动 vnc server: service vncserver restart

    配置完成后,使用 VNC Viewer登陆宿主机图形界面,例如, 192.168.106.221:5901

    如果出现 VNC Viewer的闪退,可以修改网络速度设置试试,Options… 中取消勾选 Adapt to network speed(recommended),滑块到 Best quality

  3. 启动 Virt-Manager

    CentOS 图形界面 > Applications 菜单 > System Tools > Virtual Machine Manager

使用 virt-install 命令

1
virt-install --name=testvm --ram=2048 --vCPUs=4 --os-type=Windows --hvm --cdrom=/root/w2003cnent.iso  --file=/root/SDG100.img --file-size=10 --bridge=br0 --vnc --vncport=5920

--name:设置虚拟机名称。
--ram:配置虚拟机内存,单位是MB。
--vCPUs:配置CPU个数。
--hvm:配置使用全虚拟化。
--os-type:指定操作系统类型,如Linux、Windows。
--cdrom:使用cdrom安装系统,指定ISO位置。
--bridge:配置桥接的网卡。
--vnc:打开VNC支持。
--vncport:配置VNC端口。

Windows 虚拟机安装

qcow2 格式的磁盘

Virt-Manager默认创建的磁盘格式是 RAW 格式,如果需要使用 qcow2 格式的磁盘,必须使用 qemu-img create 手工先创建一个 qcow2 格式的磁盘镜像。

qemu-img create Windows-test.qcow2 -f qcow2 50G

然后在 Virt-Manager 上指定 qcow2 格式。

在使用 virt-install 命令,磁盘镜像格式为 qcow2 时,在 virt-install 命令中要特别指明磁盘格式,否则会出现镜像复制之后虚拟机系统不能启动的现象。

光驱自动消失问题

KVM新创建虚拟机,第一次挂载的光驱,重启后自动消失。这是一个功能,专门针对Linux系统,但是Windows系统安装的时候需要多次重启,需要在 Virt-Manager 手动挂载一下 Windows 系统ISO镜像。

也可以修改虚拟机的xml配置文件:

1
2
3
4
5
6
<disk type='file' device='cdrom'>
  <driver name='qemu' type='raw' cache='none'/>
  <source file='/home/CentOS-7.0-1406-x86_64-DVD.iso'/>
  <target dev='hdb' bus='ide'/>
  <readonly/>
</disk>

鼠标不同步问题

Windows在KVM上会出现鼠标不同步问题,Virt-Manager手动添加USB指针设备,或者修改xml文件:

1
<input type='tablet' bus='usb'/>

如果添加两次USB设备,Windows系统虚拟机启动会蓝屏。

Linux 虚拟机安装

除了会碰到Windows系统安装的 qcow2 磁盘格式问题、鼠标不同步问题,Linux虚拟机的安全还可以使用直接指定内核文件路径,然后直接加载的方式。

Options… > Boot Options > 填写 Direct kernel Boot

CPU 管理

多CPU共同工作主要有3种架构,分别是SMP、MPP、NUMA架构。SMP、MPP、NUMA都是为了解决多CPU共同工作的问题。

SMP即多个CPU通过一个总线访问存储器,因此SMP系统有时也被称为一致内存访问(UMA)结构体系。SMP的缺点是扩展性有限,因为在存储器接口达到饱和的时候,增加处理器并不能获得更高的性能,因此SMP方式支持的CPU个数有限。

MPP模式则是一种分布式存储器模式,能够将更多的处理器纳入一个系统的存储器。MPP可以近似理解成一个SMP的横向扩展集群。MPP一般要依靠软件实现。

NUMA模式则是每个处理器有自己的存储器,每个处理器也可以访问别的处理器的存储器。NUMA-Q是IBM最早将NUMA技术应用到i386上的商业方案,可以支持更多的X86 CPU一起工作。

KVM 虚拟机 NUMA 调优

因为NUMA架构每个处理器都可以访问自己和别的处理器的存储器,访问自己的存储器要比访问别的存储器快很多,速度相差10~100倍,所以NUMA调优的目标就是让处理器尽量访问自己的存储器,以提高处理速度。

宿主机的NUMA信息查看与配置

通过 numactl--hardware 命令可以看到当前CPU硬件的情况

使用 numastat 命令可以查看每个节点的内存统计。

numastat命令使用-c参数可以查看相关进程的NUMA内存使用情况。例如,numastat -c qemu-kvm

Linux系统默认是自动NUMA平衡策略。如果要关闭Linux系统的自动平衡,可以使用如下命令:

echo 0 > /proc/sys/kernel/numa_balancing

如果要开启自动NUMA平衡策略,可以使用如下命令:

echo 1 > /proc/sys/kernel/numa_balancing

虚拟机NUMA信息查看与配置

使用virsh numatune命令可以查看或者修改虚拟机的NUMA配置。

1
2
3
virsh # numatune 4
numa_mode      : strict
numa_nodeset   : 0-1

NUMA工作方式可以是strict指定CPU,或者auto使用系统的numad服务。

1
2
3
4
5
6
<numatune>
        <memory mode='strict' placement='auto'/>
</numatune>
<numatune>
        <memory mode='strict' nodeset='0,2-3'/>
</numatune>

可以使用numatune命令配置虚拟机的NUMA。

1
virsh numatune rhel7 --nodeset '0,2-3'

vpcu的设置如下:

1
2
<vcpu placement='auto'>8</vcpu>
<vcpu placement='static' cpuset='0-10,5'>8</vcpu>

<vcpu><numatune>需要保持一致,<numatune>配置的是物理CPU,<vcpu>配置的是CPU的核,包括超线程产生的核。<numatune>使用static模式,<nodeset>也必须是。

可以设置一个虚拟机给32个虚拟CPU,但是一开始只能使用8个,然后根据系统压力,热添加CPU给虚拟机。

1
<vcpu placement='auto' current='8'>32</vcpu>

也可以给每个虚拟机CPU指定具体的物理机CPU pinning策略。

1
2
3
4
5
6
<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>

也可以使用emulatorpin的方式。emulatorpin标签可以指定一个特定的物理CPU范围,比如一个物理CPU内部所有的核,使虚拟机使用的CPU和存储器都在一个物理机CPU内部,xml文件如下:

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

可以在线调整:virsh emulatorpin CentOS7 1-3

1~3的核都在一个物理CPU内部。也可以设置虚拟机对NUMA资源的使用。

1
2
3
4
5
6
7
8
<cpu>
        ...
    <numa>
      <cell cpus='0-3' memory='512000'/>
      <cell cpus='4-7' memory='512000'/>
    </numa>
    ...
</cpu>

标签项意义如下。

cell:numa的cell或者numa节点。
cpus:一个物理CPU可以使用的CPU范围。
memory:可以使用的内存大小,单位为KB。

虚拟机NUMA和内存KSM

KSM技术可以合并相同的内存页,即使是不同的NUMA节点,如果需要关闭跨NUMA节点的内存合并,设置/sys/kernel/mm/ksm/merge_across_nodes参数为0。或者可以关闭特定虚拟机的KSM内存合并,在虚拟机的xml配置文件中添加以下内容就可以:

1
2
3
<memoryBacking>
        <nosharepages/>
</memoryBacking>

CPU绑定操作方法

CPU绑定是一项非常神奇的技术,最神奇的地方就是可以在线配置,并且立即生效,可以解决生产环境CPU利用率严重不平均的问题。

  • CPU信息查看

使用 virsh vcpuinfo 命令查看虚拟机VCPU和物理CPU的对应关系。

  • CPU绑定技术的原理

CPU绑定实际上是Libvirt通过CGroup来实现的,通过CGroup直接去绑定KVM虚拟机进程也可以。通过CGroup不仅可以做CPU绑定,还可以限制虚拟机磁盘、网络的资源控制

  • CPU绑定技术适用于以下场景:

系统的CPU压力比较大。
多核CPU压力不平衡,可以通过cpu pinning技术人工进行调配。

CPU 热添加和应用

CPU热添加是CentOS 7的一个新特性,Linux系统要求宿主机和虚拟机都是CentOS 7,Windows虚拟机系统要求是Windows Server 2008数据中心版或者Windows Server 2012标准版和数据中心版。

Linux系统的CPU热添加

添加CPU(下例原来有个4个VCPU):

1
2
3
4
5
6
7
virsh setvcpus CentOS7 5 --live
# 在虚拟机中激活第5个CPU
echo 1 > /sys/devices/system/cpu/cpu4/online

# 查看虚拟机CPU
cat /proc/interrupts | less
cat /proc/cpuinfo

虚拟机管理: 克隆、备份、恢复

查看所有虚拟机

1
virsh list --all

Clone a VM

1
2
3
4
virt-clone \
  --original ubuntu18.04 \
  --name cloned-ubuntu \
  --file /var/lib/libvirt/images/cu.qcow2

虚拟机的block device 信息

1
virsh domblklist vm-name

查看虚拟机信息

1
virsh dominfo vm-name

cdrom 操作

Eject : virsh change-media $VMName --path sda --eject --live
Insert : virsh change-media $VMName --path sda --source $ISO --insert --live

其他知识

在QEMU中hypervisor: QEMU TCG,Tiny Code Generator(TCG)将源处理器机器代码转换为虚拟机运行所需的机器代码块。

。在Tiny Code Generator(TCG)中,这些已经翻译的代码块放在转换缓存中,并通过跳转指令将源处理器的指令集(ISA)和目标处理器的指令集(ISA)链接在一起。

TCG and KVM are entirely separate modes of operation for QEMU.

If you’re using KVM (via -enable-kvm on the command line) then all guest instructions are either natively executed by the host CPU or (for a few instructions mostly doing I/O to emulated devices) emulated inside the host kernel

If you use QEMU in TCG mode (the default) then we are a pure emulator in userspace and make no use of the host CPU’s hypervisor functionality. qemu-user-mode is always TCG emulation, and never KVM.

  • 安装
    安装 qemu,(或 qemu-headless,一个没有GUI的版本)并根据需要安装下面的可选软件包:

qemu-arch-extra - 额外架构支持
qemu-block-gluster - Glusterfs block 支持
qemu-block-iscsi - iSCSI block 支持
qemu-block-rbd - RBD block 支持
samba - SMB/CIFS 服务器支持

非官方的AUR包 qemu-user-static AUR 为所有QEMU支持的架构提供了一个带用户模式和静态链接模式的变种。它的预编译版本在这个包中: qemu-user-static-binAUR。 它的QEMU命令依照 qemu-target_architecture-static的规则命名, 例如, qemu-x86_64-static 代表目标架构为intel 64位CPU。

1
2
sudo pacman -S qemu qemu-arch-extra qemu-block-gluster qemu-block-iscsi qemu-block-rbd
sudo pacman -S samba

qemu 包提供了 x86_64 架构的模拟器, 可以进行全系统模拟 (qemu-system-x86_64)。 qemu-arch-extra 包提供了 x86_64 用户模式的模拟 (qemu-x86_64)。

  • 全系统模拟模式 (full-system emulation)

在该模式下, QEMU将会模拟一个完整的系统,包含一个或多个处理器以及各种外围设备。这种模式更加贴近真实的系统,且这种模式不要求被模拟的客户机系统是Linux,但它的速度较慢。

QEMU中启用full-system模式的命令依照如下规则进行命名 qemu-system-目标机器架构, 例如 qemu-system-x86_64 用于模拟64位intel架构CPU, qemu-system-i386 模拟32位intel架构CPU, qemu-system-arm 模拟ARM架构(32 位), qemu-system-aarch64 模拟ARM架构(64位), 等等。
如果模拟的CPU架构与宿主机的CPU架构相同, 那么即使在此模式下,QEMU仍有可能使用hypervisor(例如KVM or Xen)的技术对模拟机进行加速。

  • 用户模式(Usermode emulation)

在此模式下, QEMU能够利用宿主机的系统资源来调用为其他架构编译的Linux可执行文件

与其他的虚拟化程序如 VirtualBox 和 VMware 不同, QEMU不提供管理虚拟机的GUI(运行虚拟机时出现的窗口除外),也不提供创建具有已保存设置的持久虚拟机的方法。除非您已创建自定义脚本以启动虚拟机,否则必须在每次启动时在命令行上指定运行虚拟机的所有参数。

  • 硬盘镜像

    • raw镜像
      和客户机器上看到的内容一模一样,并且将始终使用主机上的来宾硬盘驱动器的全部容量。此方法提供的I / O开销最小,但可能会浪费大量空间,因为guest虚拟机上未使用的空间无法在主机上使用。
    • qcow2 格式
      仅当客户系统实际写入内容的时候,才会分配镜像空间。对客户机器来说,硬盘大小表现为完整大小,即使它可能仅占用主机系统上的非常小的空间。此映像格式还支持QEMU快照功能
1
2
3
4
5
6
# 创建 raw 镜像文件,4G大小
# 用 dd 或 fallocate 也可以创建一个 raw 镜像。
qemu-img create -f raw image_file 4G

# 创建 qcow2 镜像文件,4G大小
qemu-img create -f qcow2 image_file 4G

创建上层镜像

1
2
3
qemu-img create -o backing_file=img1.raw,backing_fmt=raw -f qcow2 img1.cow

qemu-system-i386 img1.cow

调整镜像大小

1
2
3
4
# 适用于 raw 和 qcow2
# 在磁盘映像扩容后,必须使用虚拟机内部系统的分区工具对该镜像进行分区并格式化后才能真正开始使用新空间。 
# 在收缩磁盘映像时,必须首先使用虚拟机内部系统的分区工具减少分该分区的大小,然后相应地收缩磁盘映像,否则收缩磁盘映像将导致数据丢失!
qemu-img resize disk_image +10G

安装操作系统

1
qemu-system-x86_64 -cdrom iso文件路径 -boot order=d -m 4G -drive file=镜像文件路径,format=raw

可以用 -boot menu=on 代替 -boot order=d 启动boot菜单方便调试。

执行出错: end Kernel panci - not syncing: System is deadlocked on memory
默认情况下仅分配给虚拟机128MB的内存, 分配的内存大小可以通过 -m 调整, 比如 -m 512M 或 -m 2G

运行虚拟化的系统

1
qemu-system-i386 options disk_image

Ctrl+Alt+g 可以是否鼠标捕获。

启用 KVM

  1. BIOS 开启 CPU 的虚拟化支持。
  2. qemu-system-x86_64 命令加上 -enable-kvm 后,虚拟机的运行速度就正常,qemu tcg 模式下速度很慢。