1. virsh常用命令

# 查看VM接口信息, 包括MAC地址
$ sudo virsh domiflist hxt-centos7.5-01

2. 虚拟化环境准备

2.1. 安装qemu libvirt virt-manager等

sudo yum install -y qemu-kvm-ma qemu-img virt-manager libvirt libvirt-python libvirt-client virt-install virt-viewer

2.2. qemu编译安装(可选)

可以使用内部git repo

#clone qemu
git clone ssh://1680532@bjsss013.hxtcorp.net:29418/virtualization/qemu
#使用2.10版本
git checkout stable-2.10
#或使用更新的2.12版本
git checkout stable-2.12
#我们还是习惯性的切换到新的编译器
scl enable devtoolset-6 bash
#编译安装
sudo yum install glib2-devel pixman-devel libfdt-devel libaio-devel libseccomp-devel
./configure --target-list=aarch64-softmmu --enable-kvm --enable-linux-aio --enable-seccomp
make -j
sudo make install -j
  • 默认路径/usr/local
  • 编译成功后, 有qemu-system-aarch64
  • 不指定aarch64-softmmu的话, 默认编译的target list会很多, 其他架构如mips x86_64等也会编译
  • 注意: 后面virt-manager实际使用的是/usr/libexec/qemu-kvm, 后者是yum install qemu-kvm-ma而来, 和这里的qemu-system-aarch64没有关系.

2.3. libvirt编译安装高版本(可选)

#centos7.5默认版本为3.9, 这里用最新的4.6
wget https://libvirt.org/sources/libvirt-4.6.0.tar.xz
#依赖包
sudo yum install gnutls-devel gnutls-utils libnl-devel libxml2-devel device-mapper-devel libpciaccess-devel yajl-devel jansson-devel
sudo yum install dnsmasq dnsmasq-utils
#编译
./configure --with-qemu
make -j
#调试时建议不要install, 默认装到/usr/local; .service文件在/usr/local/lib/systemd/system/
#sudo make install -j
#运行
sudo systemctl start libvirtd
#或
sudo src/virtlogd &
sudo src/libvirtd
#virtsh是libvirt自带的命令行配置工具
sudo tools/virsh
#查看已经安装的虚拟机
sudo tools/virsh list --all
  • 默认安装到/usr/local/bin
  • 默认的socket是/usr/local/var/run/libvirt/libvirt-sock
  • 注意configure时加--with-qemu, 我之前没加也能编译过, 但却缺少qemu/kvm的支持 : ( 检查config.log, 寻找QEMU:应该为yes

2.3.1. libvirt告警信息

libvirtd运行时有几个告警, 应该改掉

warning : virQEMUCapsInit:958 : Failed to get host CPU cache info
error : virCPUGetHost:457 : this function is not supported by the connection driver: cannot detect host CPU model for aarch64 architecture
warning : virLXCDriverCapsInit:82 : Failed to get host CPU cache info
warning : umlCapsInit:73 : Failed to get host CPU cache info

2.3.2. libvirt介绍

2.4. virt-manager安装高版本(可选)

#安装必须的包:
sudo yum install libvirt-glib libvirt-python libosinfo python-ipaddr python-requests gtk3 vte3 gtk-vnc2
#virt-manager是python脚本, 可以直接运行
wget https://virt-manager.org/download/sources/virt-manager/virt-manager-1.5.1.tar.gz
#解压后直接运行
cd virt-manager-1.5.1
#也可以安装, 默认安装到/usr/bin/
sudo ./setup.py install
#指定socket连接libvirtd
sudo ./virt-manager -c 'qemu+unix:///system?socket=/usr/local/var/run/libvirt/libvirt-sock'

本文使用MobaXterm来显示virt-manager的图形界面, 其原理是打开ssh的X11 forward功能, 用MobaXterm内置的X server来显示图形

  • 用普通用户可能有authentication unavailable: no polkit agent available to authenticate action 'org.libvirt.unix.manage'错误, 解决办法: sudo usermod --append --groups libvirt $(whoami)
  • X11 forward只对ssh的owner用户有效, 用sudo会导致GUI无法显示, 原因是x11里root用户也没有对当前普通用户session的权限, 解决方法: 把当前用户的授权记录加到root用户 sudo xauth add $(xauth -f /home/bai/.Xauthority list | tail -1)
  • virsh或virt-manager支持remote方式连接hypervisor, 具体格式参考remote URI 在本例中, 因为编译的libvirt默认路径与通常发行版的路径不同, 这里使用qemu+unix连接本地的socket.

3. 安装虚拟机

3.1. UEFI支持

  • 安装UEFI
    简单来说就是先add一个repoqemu-firmware-jenkins, 再yum install edk2.git-aarch64.noarch 参考KVM:UEFI rpm -ql可以看到这个package里面的文件:
    $ rpm -ql edk2.git-aarch64.noarch
    /usr/share/edk2.git
    /usr/share/edk2.git/aarch64
    /usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw
    /usr/share/edk2.git/aarch64/QEMU_EFI.fd
    /usr/share/edk2.git/aarch64/QEMU_VARS.fd
    /usr/share/edk2.git/aarch64/vars-template-pflash.raw
    
  • /etc/libvirt/qemu.conf加入:
    nvram = [
      "/usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw:/usr/share/edk2.git/vars-template-pflash.raw",
    ]
    
  • 如果使用本文前面提到的手动编译的libvirt, 则要在/usr/local/etc/libvirt/qemu.conf里加入.

3.2. qemu的user

qemu是用libvirtd起的, 在配置文件/usr/local/etc/libvirt/qemu.conf里, 改成如下, 使qemu的默认用户是root.

user = "root"
group = "root"

3.3. 安装linux网桥工具

sudo yum install bridge-utils

3.4. 创建虚拟机

新建一个虚拟机, 这里我们导入一个创建好的disk image(从ISO安装而来), 配置8 core/16384 mem; 其他基本上都是默认配置

这里创建了三个VM, hxt-centos7.5-00, hxt-centos7.5-01, hxt-centos7.5-02

#导出xml配置文件
sudo tools/virsh dumpxml hxt-centos7.5-00 > ~/hxt-centos7.5-00.xml
#使用已有的配置文件创建虚拟机
sudo tools/virsh create ~/repo/save/vm/hxt-centos7.5-base.xml

3.4.1. 访问qemu的monitor

#virsh访问qemu的monitor: --hmp是human monitor protocol的意思
#sudo virsh qemu-monitor-command <vm> --hmp <cmd>
sudo virsh qemu-monitor-command test --hmp help
#很有用的info命令族
sudo virsh qemu-monitor-command test --hmp info
#info qtree可以查看详细的设备信息
sudo virsh qemu-monitor-command test --hmp info qtree

3.5. 虚拟机共享OS image

多个虚拟机的OS image通常都是基本相同的, 于是自然想创建一个base image, 几个VM共享它; 而且某个VM的改动, 只保存改变的部分, 能做到吗? 可以, qemu的qcow2, 就是qemu copy-on-write的缩写, 天然支持, 下面这个文章讲的非常清楚 qemu qcow2 backing files & overlays 前面我们用的image固定大小为32G, 为了节省空间, 先shrink

sudo cp hxt-centos7.5-base.qcow2 hxt-centos7.5-base.qcow2.back
#压缩后33G的image变成850M, 效果非常好
sudo qemu-img convert -O qcow2 -c hxt-centos7.5-base.qcow2.back hxt-centos7.5-base-shrink.qcow2
#比如我想用hxt-centos7.5-base.qcow2做基础image, 分别创建两个thin的image
sudo qemu-img create -f qcow2 -b hxt-centos7.5-base.qcow2 hxt-centos7.5-01.qcow2
sudo qemu-img create -f qcow2 -b hxt-centos7.5-base.qcow2 hxt-centos7.5-02.qcow2
#还可以commit在thin image上的改变, 因为用qemu-imag info能看出来它的backing image是谁
sudo qemu-img commit /guests/F21server.qcow2.snap

参考: https://dustymabe.com/2015/01/11/qemu-img-backing-files-a-poor-mans-snapshotrollback/

3.5.1. 问题

导入disk image失败, 现象是UEFI不能启动os image, 经验证和shrink无关, 直接cp的image也不行, 似乎virt-manager新建VM时导入disk image功能不正常? UEFI打印的错误信息:

!!!!!!!!  ProtectUefiImageCommon - Section Alignment(0x20) is incorrect  !!!!!!!!
FSOpen: Open '\EFI\BOOT\fbaa64.efi' Success
FSOpen: Open '\EFI\BOOT\fbaa64.efi' Success
Section 0 has negative size
Failed to load image: Unsupported
start_image() returned Unsupported
Error: Image at 0007BE8D000 start failed: Unsupported
Unloading driver at 0x0007BE8D000
Image Return Status = Unsupported

网上有人报这个错误, 是UEFI的问题: https://bugzilla.redhat.com/show_bug.cgi?id=1527283

3.5.2. 解决

除了要拷贝disk image, 还要拷贝uefi的VARS.fd文件, 比如

cd /usr/local/var/lib/libvirt/qemu/nvram
#拷贝之前可用的vars.fd
sudo cp hxt-centos7.5-01_VARS.fd hxt-centos7.5-base_VARS.fd

4. 虚拟网络

4.1. NAT网络

NAT网络用于Internet访问.

创建虚拟网络network1, 模式为NAT to eth0

NAT网络network1

libvirtd创建了虚拟网桥virbr1, 以及对应三个VM的三个接口, 如下:

$ brctl show virbr1
bridge name     bridge id               STP enabled     interfaces
virbr1          8000.525400e10733       yes             virbr1-nic
                                                        vnet0
                                                        vnet1
                                                        vnet2

上面的vnetN是tap设备, 工作在kernel协议栈二层. 其原理和tun一样, 区别在于tun工作在三层.

tun/tap设备原理图

进入VM, 配置网络, 测试外网连通性

dhclient eth0
ip addr
curl baidu.com

4.2. 给VM添加OVS bridge

这里ovs已经运行并创建了一个bridge: ovsbr0

export PATH=$PATH:/usr/local/share/openvswitch/scripts
sudo ovs-ctl start
#打开dpdk初始化
sudo ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true
#新增一个bridge
sudo ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev

4.2.1. 使用virt-manager直接添加

Add Hardware, 按下图添加ovsbr0

注意: 还要在xml里面加上<virtualport type='openvswitch'/>, 详见下一小节: 否则会出现错误: Unable to add bridge ovsbr0 port vnet1: Operation not supported

4.2.2. 使用virsh添加

参考Open vSwitch with LibvirtOpenVSwitch KVM libvirt

#这里使用libvirt-4.6.0源码目录
cd libvirt-4.6.0
#编辑xml, 加上下面的配置:
sudo tools/virsh edit hxt-centos7.5-01
    <interface type='bridge'>
      <mac address='52:54:00:38:fe:8c'/>
      <source bridge='ovsbr0'/>
      <virtualport type='openvswitch'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
    </interface>

4.2.3. 启动VM

添加了OVS bridge以后启动VM, 这里我们启动2个VM, 可以看到libvirtd会自动创建相应的port:

$ sudo ovs-vsctl show
f81a1c52-91c1-40a2-b993-6dfeea09317e
    Bridge "ovsbr0"
        Port "vnet3"
            Interface "vnet3"
        Port "vnet1"
            Interface "vnet1"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
    ovs_version: "2.8.4"

vnet1vnet3是libvirtd在VM启动时创建的, 并会在VM关闭时销毁.

此时, 在VM里面配置好ip, 经验证两个VM可以互相ping通.

4.3. 给VM添加vhost接口

这里要添加两个类型是dpdkvhostuser的端口

#增加两个port, 类型是dpdkvhostuser
sudo ovs-vsctl add-port ovsbr0 dpdkvhostuser0 -- set Interface dpdkvhostuser0 type=dpdkvhostuser
sudo ovs-vsctl add-port ovsbr0 dpdkvhostuser1 -- set Interface dpdkvhostuser1 type=dpdkvhostuser

手工修改xml文件virsh edit <VM>, 加入:

  <memoryBacking>
    <hugepages>
      <page size='512' unit='M' nodeset='0'/>
    </hugepages>

  <cpu mode='host-passthrough' check='none'>
    <topology sockets='1' cores='4' threads='1'/>
    <numa>
      <cell id='0' cpus='0-3' memory='8388608' unit='KiB' memAccess='shared'/>
    </numa>
  </cpu>

  <os>
    <type arch='aarch64' machine='virt'>hvm</type>

  <devices>
    <emulator>/usr/local/bin/qemu-system-aarch64</emulator>
    <interface type='vhostuser'>
      <mac address='00:00:00:00:00:01'/>
      <source type='unix' path='/usr/local/var/run/openvswitch/dpdkvhostuser0' mode='client'/>
      <model type='virtio'/>
      <driver queues='2'>
        <host mrg_rxbuf='on'/>
      </driver>
    </interface>

另外一个VM也相应修改, 注意dpdkvhostuser0变成dpdkvhostuser1

4.3.1. troubleshooting

  • 访问socket权限错误: Failed to connect socket /usr/local/var/run/openvswitch/dpdkvhostuser1: Permission denied 解决方法:sudo chmod a+rw /usr/local/var/run/openvswitch/ 参考: https://bugzilla.redhat.com/show_bug.cgi?id=1431556

  • 默认的qemu-kvm不支持vhost-user Parameter 'type' expects a netdev backend type 解决方法: 源码编译qemu, 在xml里用qemu-system-aarch64替代默认的qemu-kvm, 见上面 参考: https://bugzilla.redhat.com/show_bug.cgi?id=1539823

  • 两个VM互相ping不通, VM里面收发包统计一直为0

5. 参考

results matching ""

    No results matching ""