zoukankan      html  css  js  c++  java
  • QEMU-KVM虚拟化:存储

    以下命令行亲自执行有效,执行环境:

    Compiled against library: libvirt 4.5.0
    Using library: libvirt 4.5.0
    Using API: QEMU 4.5.0
    Running hypervisor: QEMU 1.5.3

    QEMU存储虚拟化结构栈

    QEMU可以处理几种不同的磁盘映像格式。首选格式为raw或qcow2。Raw是一种非常简单的格式,它将文件系统中的字节逐字节存储在文件中。大多数其他仿真器都支持此格式。Qcow2是QEMU自己的图像格式,对小图像很有用。并且支持磁盘映像压缩以及捕获磁盘映像状态的快照。

    从QEMU的存储协议栈来说,应用程序和虚拟机内核的工作类似于裸机。虚拟机通过硬件仿真(Hardware emulation)与QEMU交互,并将IO执行情况的控制流和数据流交互给QEMU,QEMU代表虚拟机对磁盘镜像文件执行I/O操作。而从主机内核层面上,主机内核会将虚拟机I/O视为一种用户空间的应用程序IO请求进行正常的执行处理。

    硬件仿真(Hardware emulation)主要有3种:

    • Virtio 是准虚拟化存储接口,提供较好的性能,virtio_blk 是准虚拟化块设备接口。
    • IDE 是 QEMU 全虚拟化接口,提供最好的兼容性,但是性能最差。
    • SCSI 是新的给特定设备的接口。

    全虚拟化 I/O

    过程:
    1. 客户机的设备驱动程序发起 I/O 请求操作请求
    2. KVM 模块中的 I/O 操作捕获代码拦截这次 I/O 请求
    3. 经过处理后将本次 I/O 请求的信息放到 I/O 共享页 (sharing page),并通知用户空间的 QEMU 程序。
    4. QEMU 程序获得 I/O 操作的具体信息之后,交由硬件模拟代码来模拟出本次 I/O 操作。
    5. 完成之后,QEMU 将结果放回 I/O 共享页,并通知 KMV 模块中的 I/O 操作捕获代码。
    6. KVM 模块的捕获代码读取 I/O 共享页中的操作结果,并把结果放回客户机。 

    qemu-kvm 关于磁盘设备和网络的主要选项

    -drive option[,option[,option[,...]]]:定义一个硬盘设备;可用子选项有很多。
        file=/path/to/somefile:硬件映像文件路径;
        if=interface:指定硬盘设备所连接的接口类型,即控制器类型,如ide、scsi、sd、mtd、floppy、pflash及virtio等;
        index=index:设定同一种控制器类型中不同设备的索引号,即标识号;
        media=media:定义介质类型为硬盘(disk)还是光盘(cdrom);    
        format=format:指定映像文件的格式,具体格式可参见qemu-img命令;
    -boot [order=drives][,once=drives][,menu=on|off]:定义启动设备的引导次序,每种设备使用一个字符表示;不同的架构所支持的设备及其表示字符不尽相同,在x86 PC架构上,a、b表示软驱、c表示第一块硬盘,d表示第一个光驱设备,n-p表示网络适配器;默认为硬盘设备(-boot order=dc,once=d)

    详情:libvirt 虚机的生命周期 (Libvirt Virtual Machine Lifecycle)

    I/O 全虚拟化和准虚拟化 [KVM I/O QEMU Full-Virtualizaiton Para-virtualization]
    https://www.cnblogs.com/sammyliu/p/4543657.html
    libvirt 介绍 [ Libvrit for KVM/QEMU ]
    https://www.cnblogs.com/sammyliu/p/4558638.html
    Nova 通过 libvirt 管理 QEMU/KVM 虚机 [Nova Libvirt QEMU/KVM Domain]
    https://www.cnblogs.com/sammyliu/p/4568188.html
    使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照 (Nova Instances Snapshot Libvirt)
    https://www.cnblogs.com/sammyliu/p/4468757.html
    使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机 [Nova Libvirt QEMU/KVM Live Migration]
    https://www.cnblogs.com/sammyliu/p/4572287.html

    KVM/QEMU 的 vitio 实现采用在 Guest OS 内核中安装前端驱动 (Front-end driver)和在 QEMU 中实现后端驱动(Back-end)的方式。前后端驱动通过 vring 直接通信,这就绕过了经过 KVM 内核模块的过程,达到提高 I/O 性能的目的。

    纯软件模拟的设备和 Virtio 设备的区别:virtio 省去了纯模拟模式下的异常捕获环节,Guest OS 可以和 QEMU 的 I/O 模块直接通信。

    Libvirt

    为什么需要Libvirt?

    1. Hypervisor 比如 qemu-kvm 的命令行虚拟机管理工具参数众多,难于使用。
    2. Hypervisor 种类众多,没有统一的编程接口来管理它们,这对云环境来说非常重要。
    3. 没有统一的方式来方便地定义虚拟机相关的各种可管理对象。

    Libvirt提供了什么?

    1. 它提供统一、稳定、开放的源代码的应用程序接口(API)、守护进程 (libvirtd)和和一个默认命令行管理工具(virsh)。
    2. 它提供了对虚拟化客户机和它的虚拟化设备、网络和存储的管理。
    3. 它提供了一套较为稳定的C语言应用程序接口。目前,在其他一些流行的编程语言中也提供了对libvirt的绑定,在Python、Perl、Java、Ruby、PHP、OCaml等高级编程语言中已经有libvirt的程序库可以直接使用。
    4. 它对多种不同的 Hypervisor 的支持是通过一种基于驱动程序的架构来实现的。libvirt 对不同的 Hypervisor 提供了不同的驱动,包括 Xen 的驱动,对QEMU/KVM 有 QEMU 驱动,VMware 驱动等。在 libvirt 源代码中,可以很容易找到 qemu_driver.c、xen_driver.c、xenapi_driver.c、vmware_driver.c、vbox_driver.c 这样的驱动程序源代码文件。
    5. 它作为中间适配层,让底层 Hypervisor 对上层用户空间的管理工具是可以做到完全透明的,因为 libvirt 屏蔽了底层各种 Hypervisor 的细节,为上层管理工具提供了一个统一的、较稳定的接口(API)。
    6. 它使用 XML 来定义各种虚拟机相关的受管理对象。

         目前,libvirt 已经成为使用最为广泛的对各种虚拟机进行管理的工具和应用程序接口(API),而且一些常用的虚拟机管理工具(如virsh、virt-install、virt-manager等)和云计算框架平台(如OpenStack、OpenNebula、Eucalyptus等)都在底层使用libvirt的应用程序接口。

    Libvirt API 的实现

    libvirt API 的实现是在各个 Hypervisor driver 和 Storage dirver 内。Hypervisor 驱动包括:

    Libvirti API 所管理的主要对象

     
    对象 解释
    Domain (域) 指运行在由Hypervisor提供的虚拟机器上的一个操作系统实例(常常是指一个虚拟机)或者用来启动虚机的配置。
    Hypervisor 一个虚拟化主机的软件层
    Node (主机) 一台物理服务器。
    Storage pool (存储池) 一组存储媒介的集合,比如物理硬盘驱动器。一个存储池被划分为小的容器称作卷。卷会被分给一个或者多个虚机。
    Volume (卷) 一个从存储池分配的存储空间。一个卷会被分给一个或者多个域,常常成为域里的虚拟硬盘。
     

    对象的管理模型

    对象名称 对象 Python 类 描述
    Connect 与 Hypervisor的连接
    virConnectPtr
    在调用任何 API 去管理一个本地或者远端的Hypervisor前,必须建立和这个Hypervisor的连接。
    Domain Guest domain
    virDomainPtr
    用于列举和管理已有的虚机,或者创建新的虚机。唯一标识:ID,Name,UUID。一个域可能是暂时性的或者持久性的。暂时性的域只能在它运行期间被管理。持久性的域在主机上保存了它的配置。
    Virtual Network 虚拟网络
    virNetworkPtr
    用于管理虚机的网络设备。唯一标识:Name,UUID。一个虚拟网络可能是暂时性的或者持久性的。每个主机上安装libvirt后,它都有一个默认的网络设备“default”。它向该主机上运行的虚机提供DHCP服务,以及通过NAT连接到主机上。
    Storage Pool 存储池
    virStoragePoolPtr
    用于管理虚拟机内的所有存储,包括 local disk, logical volume group, iSCSI target, FibreChannel HBA and local/network file system。唯一标识:Name,UUID。一个存储池可能是暂时性的或者持久性的。Pool 的 type 可以是  dirfsnetfsdiskiscsilogicalscsi,mpathrbdsheepdoggluster 或者 zfs。
    Storage Volume   存储卷
    virStorageVolPtr
    用于管理一个存储池内的存储块,包括一个池内分配的块、磁盘分区、逻辑卷、SCSI/iSCSI Lun,或者一个本地或者网络文件系统内的文件等。唯一标识:Name,Key,Path。
    Host device  主机设备
    virNodeDevPtr
    用于管理主机上的物理硬件设备,包括 the physical USB or PCI devices and logical devices these provide, such as a NIC, disk, disk
    controller, sound card, etc。唯一标识:Name。

    Libvirt XML 定义

    Libvirt 使用 XML 来定义各种对象,例如

      <devices>
        <emulator>/usr/libexec/qemu-kvm</emulator>
        <disk type='file' device='disk'>
          <driver name='qemu' type='raw'/>
          <source file='/data/centos7.raw'/>
          <target dev='vda' bus='virtio'/>
          <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
        </disk>
        <disk type='file' device='cdrom'>
          <driver name='qemu' type='raw'/>
          <target dev='hda' bus='ide'/>
          <readonly/>
          <address type='drive' controller='0' bus='0' target='0' unit='0'/>
        </disk>

    其中,与 OpenStack Nova 关系比较密切的有:

    disk (磁盘) 任何磁盘设备,包括软盘(floppy)、硬盘(hard disk)、光驱(cdrom)或者半虚拟化驱动都使用 <disk> 元素来定义。 方式:
    <disk type='**' device='**'>。其中:
    • ”type“ 用来指定device source 的类型:"file", "block", "dir", "network", 或者 "volume"。具体的 source  由 <source> 标签定义。
    • ”device“ 用来指定 device target 的类型:"floppy", "disk", "cdrom", and "lun", 默认为 "disk" 。具体的 target 由 <target> 标签定义。

    (1)”volume“ 类型的 disk
        <disk type='volume' device='disk'>
          <driver name='qemu' type='raw'/>
          <source pool='blk-pool0' volume='blk-pool0-vol0'/>
          <target dev='hdk' bus='ide'/>
        </disk>
    (2)”file“ 类型的 disk
        <disk type='file' snapshot='external'>
          <driver name="tap" type="aio" cache="default"/>
          <source file='/var/lib/xen/images/fv0' startupPolicy='optional' />
          <target dev='hda' bus='ide'/>
        </disk>
    (3)”block“ 类型的 disk
       <disk type='block' device='cdrom'>
          <driver name='qemu' type='raw'/>
          <target dev='hdd' bus='ide' tray='open'/>
          <readonly/>
        </disk>
    (4)”network“ 类型的 disk
    复制代码
     <disk type='network' device='cdrom'>
          <driver name='qemu' type='raw'/>
          <source protocol="http" name="url_path">
            <host name="hostname" port="80"/>
          </source>
          <target dev='hde' bus='ide' tray='open'/>
          <readonly/>
        </disk> 
    复制代码
     
    Host device assignment (主机设备分配)

    复制代码
       <hostdev mode='subsystem' type='usb'> #USB 设备直接分配
          <source startupPolicy='optional'>
            <vendor id='0x1234'/>
            <product id='0xbeef'/>
          </source>
          <boot order='2'/>
        </hostdev>
        <hostdev mode='subsystem' type='pci' managed='yes'> #PCI 设备直接分配
          <source>
            <address domain='0x0000' bus='0x06' slot='0x02' function='0x0'/>
          </source>
          <boot order='1'/>
          <rom bar='on' file='/etc/fake/boot.bin'/>
        </hostdev>
    复制代码
     
    Network interface (网卡)
    有几种 interface 类型:
    (1)type = ‘network’ 定义一个连接 Virtual network 的 interface
    复制代码
    <devices>
        <interface type='network'>
          <source network='default'/> #虚拟网络的名称为 ‘default’
        </interface>
        ...
        <interface type='network'>
          <source network='default' portgroup='engineering'/>
          <target dev='vnet7'/>
          <mac address="00:11:22:33:44:55"/>
          <virtualport>
            <parameters instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
          </virtualport>
    
        </interface>
      </devices>
    复制代码
    #virsh:attach-interface --domain d-2 --type network --source isolatednet1 --mac 52:53:00:4b:75:6f --config
    (2)type=‘birdge’ 定义一个 Bridge to LAN(桥接到物理网络)的interface:前提是主机上存在一个 bridge,该 bridge 已经连到物理LAN。
    复制代码
        <interface type='bridge'> #连接到 br0
          <source bridge='br0'/>
        </interface>
        <interface type='bridge'> #连接到br1
          <source bridge='br1'/>
          <target dev='vnet7'/>
          <mac address="00:11:22:33:44:55"/>
        </interface>
        <interface type='bridge'> #连接到 Open vSwithc bridge ovsbr
          <source bridge='ovsbr'/>
          <virtualport type='openvswitch'>
            <parameters profileid='menial' interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
          </virtualport>
        </interface>
    复制代码
    #virsh:attach-interface --domain d-2 --type bridge --source virbr0 --mac 52:22:33:44:55:66 --config
    (3)type=‘ethernet’ 定义一个使用指定脚本连接到 LAN 的 interface
    <devices>
        <interface type='ethernet'>
          <target dev='vnet7'/>
          <script path='/etc/qemu-ifup-mynet'/>
        </interface>
      </devices>
    (4)type=‘direct’ 定义一个直接连到物理网卡(Direct attachment to physical interface)的 interface:需要 Linux macvtap 驱动支持
        <interface type='direct' trustGuestRxFilters='no'>
          <source dev='eth0' mode='vepa'/>
        </interface>
    (5)type=‘hostdev’ 定义一个由主机PCI 网卡直接分配(PCI Passthrough)的 interface: 分配主机上的网卡给虚机
    复制代码
    <devices>
        <interface type='hostdev' managed='yes'>
          <driver name='vfio'/>
          <source>
            <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
          </source>
          <mac address='52:54:00:6d:90:02'/>
          <virtualport type='802.1Qbh'>
            <parameters profileid='finance'/>
          </virtualport>
        </interface>
      </devices>
    复制代码
     
    network (网络)
    <bridge name="virbr0" stp="on" delay="5" macTableManager="libvirt"/>
    <domain name="example.com" localOnly="no"/>
    <forward mode="nat" dev="eth0"/>
    

    1. bridge:定义一个用于构造该虚拟网络的网桥。 

    2. domain:定义 DHCP server 的 DNS domain。

    3. forward: 定义虚拟网络直接连到物理 LAN 的方式. ”mode“指转发模式。

     (1) mode=‘nat’:所有连接到该虚拟网络的虚拟的网络都会经过物理机器的网卡,并转换成物理网卡的地址。

    复制代码
    <network>
            <name>default</name>
            <bridge name="virbr0" />
            <forward mode="nat"/>
            <ip address="192.168.122.1" netmask="255.255.255.0">
              <dhcp>
                <range start="192.168.122.2" end="192.168.122.254" />
              </dhcp>
            </ip>
            <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" />
          </network>
    复制代码

    也可以指定公共的IP地址和端口号。

    <forward mode='nat'><nat><address start='1.2.3.4' end='1.2.3.10'/> </nat> </forward>
    <forward mode='nat'><nat><port start='500' end='1000'/></nat></forward>
    (2) mode=‘route’:类似于 NAT,但是不使用NAT,而是使用routing table。  
    复制代码
          <network>
            <name>local</name>
            <bridge name="virbr1" />
            <forward mode="route" dev="eth1"/>
            <ip address="192.168.122.1" netmask="255.255.255.0">
              <dhcp>
                <range start="192.168.122.2" end="192.168.122.254" />
              </dhcp>
            </ip>
            <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" />
          </network>
    复制代码
    (3) mode=‘bridge’:使用不受libvirt管理的bridge,比如主机上已有的bridge;open vswitch bridge;使用 macvtap's "bridge"  模式
          <network>
            <name>host-bridge</name>
            <forward mode="bridge"/>
            <bridge name="br0"/>
          </network>
    (4) mode=‘passthrough’:使用 a macvtap "direct" connection in "passthrough" mode 指定主机上的特定网卡用于虚拟网络   
    复制代码
     <forward mode='passthrough'>
        <interface dev='eth10'/>
        <interface dev='eth11'/>
        <interface dev='eth12'/>
        <interface dev='eth13'/>
        <interface dev='eth14'/>
      </forward>
    复制代码
    (5) mode=‘hostdev’:直接分配主机上的网络设备。
    <forward mode='hostdev' managed='yes'>
        <driver name='vfio'/>
        <address type='pci' domain='0' bus='4' slot='0' function='1'/>
        <address type='pci' domain='0' bus='4' slot='0' function='2'/>
        <address type='pci' domain='0' bus='4' slot='0' function='3'/>
      </forward>
     

    详细的 XML 定义说明在 https://libvirt.org/format.html

    镜像文件管理工具qemu-img

    qemu支持的镜像文件格式
    可以通过qemu-img -h查看其支持的镜像格式,支持20多中格式:blkdebug blkverify bochs cloop cow tftp ftps ftp https http dmg nbd parallels qcow qcow2 qed host_cdrom host_floppy host_device file raw sleepdog vdi vmdk vpc vvfat。这里主要介绍一下raw和qcow2格式

    qemu-img有很多命令,包括下面常用的

    info
      查看镜像的信息
    create
      创建镜像
    check
      检查镜像
    convert
      转化镜像的格式,(raw,qcow ……)
    snapshot
      管理镜像的快照
    rebase
      在已有的镜像的基础上创建新的镜像
    resize
      增加或减小镜像大小

    create创建镜像

    qemu-img create [-f fmt] [-o options] filename [size]
    对于qcow2,-o支持的参数包括compatacking-fileacking-fmtencryptioncluster_sizeprellocation
    qemu-img create -f raw /data/centos7.raw 10G

    convert 转化镜像文件格式

    qemu-img convert [-c] [-f fmt] [-O output_fmt] [-o options] filename output_filename
    [-c]表示是否对文件进行压缩
    [-o options]可以指定后端镜像文件(保证源和目标的后端一致)、文件大小、是否加密等
    qemu-img convert -c -O qcow2 vm2.raw vm2.qcow2

    snapshot管理镜像文件终端 快照
    qemu-img snapshot [-l| -a snapshot| -c snapshot| -d snapshot] filename
    [-l]列出所有快照
    [-a]使用某一个快照
    [-c]创建一个快照
    [-d]删除一个快照

    查看快照
    qemu-img snapshot -l /images/vm2.qcow2
    注意:只有qcow2才支持快照
    
    打快照
    qemu-img snapshot -c booting vm2.qcow2
    
    从快照恢复:
    qemu-img snapshot -a 1 /images/vm2.qcow2
    然后从kvm启动这个虚拟机,会发现虚拟机又在打快照时的状态了
    
    删除快照:
    qemu-img snapshot -d 2 /images/vm2.qcow

    resize 改变镜像文件大小

    qemu-img rebase [-f fmt] [-t cache] [-p] [-u] -b backing-file [-F backing-fmt] filename
    只有qcow2和qed格式支持
    qemu-img resize filename [+/-]size
    size支持K M G T 单位
    qemu-img resize vm2.raw +2GB

    qemu-kvm存储配置

    qemu-kvm创建和开启虚机的存储配置
    存储配置主要涉及三部分
    (1)指定存储器
    (2)设置启动顺序
    (3)详细配置存储驱动器(设置存储驱动器的详细属性,先略过)

    指定存储器,主要是指指定客户机的IDE设备、软盘设备、CD-ROM、Flash存储器、SD卡具体使用哪个镜像文件
    配置客户机的启动顺序,在指定了各个存储器设备后,可以指定客户机在启动的时候选择启动设备的顺序

    qemu-kvm ... -boot [order=a|b|c|d|n][,once=drivces][,menu=on|off]
    [,splash=filename][,splash-time=sp-time]
    a|b分别表示第1、2软驱,c表示第一个硬盘,d表示cd-rom;
    once表示第一次启动的启动顺序;
    menu设置开机交互界面;
    splash ,splash-time设置开机bios显示的图片和时间
    详细配置存储驱动器

    -drive option[,option[,option.....]]
    为客户机添加一个新的存储驱动器,可以指定对应的镜像文件、接口类型、
    媒介类型、快照、缓存等

    qemu-kvm创建虚拟机

    qemu-kvm -name c1 -smp 2 -m 128 -cpu host -drive file=/data/VMs/c1/c1.img,if=virtio,media=disk,cache=writeback,format=qcow2 -net nic,macaddr=52:54:00:00:00:11,model=virtio -net tap,script=/etc/qemu-ifup -vnc :0 

    virt-install创建虚拟机

    # 默认网络
    virt-install --virt-type kvm --name centos7 --ram 1024 --cdrom=/home/CentOS-7-x86_64-Minimal-2003.iso --disk path=/data/centos7.raw --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole
    # 桥接网络:
    virt-install --virt-type kvm --name openstack-middleware1 --ram 4096 --vcpus 4 --cdrom=/usr/local/src/CentOS-7-x86_64-Minimal-1511.iso --disk path=/var/lib/libvirt/images/CentOS-7-x86_64-GenericCloud-1511-ok.qcow2 --network bridge=br0 --graphics vnc,listen=0.0.0.0 --noautoconsole
     
  • 相关阅读:
    算法:最小公倍数的求解方法
    使用C语言中qsort()函数对浮点型数组无法成功排序的问题
    用两个栈模拟实现一个队列
    单链表反向查找
    单链表逆序
    斐波那契(Fibonacci)数列的几种计算机解法
    最大子列和问题
    Visual Studio个人常用快捷键
    数字根(digital root)
    秦九韶算法(霍纳算法)求解多项式
  • 原文地址:https://www.cnblogs.com/starcrm/p/13288836.html
Copyright © 2011-2022 走看看