KVM&QEMU学习笔记(二)

来源:互联网 发布:大学生应知相关法律 编辑:程序博客网 时间:2024/06/05 10:56
使用快照

快照(Snapshot)是Copy-on-write的一种应用。QEMU支持两种快照:

  1. 内部快照(internal snapshot):在qcow2镜像的snapshot table中维护的快照,所有快照都存放在一个镜像文件中
  2. 外部快照(external snapshot):与Backing file很类似,在外部文件中创建新的镜像,原先的镜像只读
内部快照

内部快照的原理是:

  1. 创建一个Snapshot后,在Snapshot Table中新增一项,复制L1 Table
  2. 当L2 Table或者Data Cluster发生改变,则把改变前的数据复制一份(Copy-on-write),由新创建的Snapshot的L1 Table来管理
  3. L2 Table或者Data Cluster的变化,直接写到原始位置
  4. 要删除快照,很简单,直接把Snapshot Table对应项、以及复制的L1-L2-DS删除即可
  5. 要加载快照,则需要依据L1-L2-DS信息,将其合并到镜像的L1-L2-DS信息中

可以使用Monitor来创建、加载、删除内部快照:

# 保存一个内部快照(qemu) savevm snapshot-1 qemu-img info hda.img# 输出如下:#Snapshot list:#ID        TAG                 VM SIZE                DATE       VM CLOCK#1         snapshot-1             112M 2016-09-07 18:05:48   00:00:21.536#Format specific information:#    compat: 1.1#    lazy refcounts: false # 加载内部快照(qemu) loadvm snapshot-1 # 删除内部快照(qemu) delvm snapshot-1

外部快照

外部快照与内部快照相反:内部快照是原数据变化,外部快照则是新文件变化。

可以使用Monitor来管理外部快照:

snapshot_blkdev ide0-hd0 snapshot.img qcow2
配置客户机磁盘

有了磁盘镜像文件后,你需要为qemu-system-*指定参数,给客户机增加磁盘。有几种不同的配置方式:

# 最简单的方式-hda hda.img  # 使用-drive配置块设备,可以指定if为virtio来提升性能-drive file=hda.img,index=0,media=disk,if=virtio # 使用-device配置通用设备-drive file=hda.img,if=none,id=virtio-disk0,format=qcow2,cache=none # 可以指定virtio-blk-pci来提升性能-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=virtio-disk0,bootindex=1

配置网络

QEMU中的网络,包含两部分的内容:

  1. 客户机使用的虚拟网络设备
  2. 和上述虚拟设备通信的网络后端,这些后端负责把虚拟设备的数据包发到宿主机的网络中

要创建一个网络后端,可以指定如下选项:

# TYPE为后端类型:user、tap、bridge、socket、vde等# id为一个标识符,将虚拟网络设备和网络后端关联在一起# 如果客户机有多个虚拟网络设备,则每一个都需要自己的网络后端-netdev TYPE,id=NAME,...

QEME支持多种网络后端:

USER后端

如果没有指定网络选项,QEMU默认会模拟单张Intel e1000 PCI网卡,该网卡基于user后端(SLIRP)连接到宿主机:

# 不指定网络qemu # 等价配置。自0.12开始废弃的配置方式 -net nic相当于-device DEVNAME;-net TYPE相当于-netdev TYPEqemu -hda disk.img -net nic -net user# 等价配置。-netdev指定网络后端,-device指定虚拟网络设备,后者通过netdev字段引用后端的IDqemu -netdev user,id=network0 -device e1000,netdev=network0

在客户机看来:

  1. 本身的IP地址被分配为 10.0.2.15+
  2. 分配IP的虚拟DHCP为 10.0.2.2
  3. 虚拟DNS服务器为 10.0.2.3
  4. 虚拟Samba服务器为 10.0.2.4,客户机可以通过此服务器访问宿主机的文件系统

用户模式网络可以很方便的访问网络资源。但是它有很多限制:

  1. 默认的,它运作方式类似于防火墙,且不允许任何入站流量。这个限制可以通过端口重定向解决
  2. 仅仅支持TCP、UDP协议,对于ICMP则不支持
  3. 性能比较差

为了支持入站请求,你可以使用端口重定向(Redirecting ports)——把针对宿主机某个端口的请求转发给客户机的某个端口。映射后,客户机可以对外提供SSH、HTTP等服务:

# 把宿主机的7080端口重定向到客户机的80端口;把宿主机的7022端口重定向到客户机的22端口qemu-system-x86_64 -redir tcp:7080::80 -redir tcp:7022::22 -hda ~/Vmware/KVM/centos7-base.img -m 512  # 从宿主机SSH到客户机ssh root@127.0.0.1 -p 7022

你可以不使用默认的10.0.2网段:

Shell1-netdev user,id=network0,net=192.168.5.0/24,dhcpstart=192.168.5.9 

客户机OS配置

依据客户机安装的操作系统,可能需要进行一些配置,才能正常使用网络。以CentOS 7 Minimal + 用户模式网络为例,需要修改以下配置文件:

NETWORKING=yes# 如果不使用IPV6NETWORKING_IPV6=no
# 如果不使用IPV6
IPV6INIT=no
# 开机启动此网卡,默认不启动
ONBOOT=yes
网关、DNS不需要设置。修改完这些配置文件后,重启客户机网络: /etc/init.d/network restart  。然后执行yum update 测试一下能否正常联网(不要使用ping测试)
TAP后端

QEMU的TAP后端利用宿主机的TAP设备,为客户机提供完整的桥接网络支持,如果外部需要使用标准端口连接到客户机, 或者多个客户机需要相互通信,可以使用该方式。 TAP后端还具有以下优势:

  1. 非常好的性能
  2. 可以配置以支持各种网络拓扑

但是,你需要在宿主机上进行网络拓扑的配置,而且各种系统的配置不同。

使用TAP后端前,你需要确认你的宿主机的内核支持TAP网络接口: /dev/net/tun 文件存在则说明支持。如果没有这样的文件,可以尝试手工创建:

sudo mkdir /dev/netsudo mknod /dev/net/tun c 10 200sudo /sbin/modprobe tun


如果你想创建几个客户机之间的私有网络,可以使用该方式。未参与进来的客户机、真实网络无法看到此网络。基于TAP的私有桥接网络
如果你不是root,则你需要 /dev/kvm 的读写权限。

首先,添加一个以太网桥设备:

sudo ip link add br0 type bridge# 也可以使用:sudo brctl addbr br0添加网桥# 要删除网桥,执行: ip link delete br0# 注意:网桥会在重启后消失 # 启用此网桥sudo ip link set br0 up # 为网桥分配IP地址sudo ip addr add 10.0.0.1 dev br0 # 在宿主机添加一条直接路由,便于它能和客户机通信sudo ip route add 10.0.0.0/8 dev br0
创建一个创建TAP设备并桥接到网桥的脚本:

#!/bin/sh switch=br0 if [ -n "$1" ];then        # tunctl -u `whoami` -t $1        # 添加一个tap设备,在我的机器上不需要,原因见下面        # ip tuntap add $1 mode tap user `whoami`        # 不知道从什么时候开始,QEMU会在执行此脚本之前就创建好tap设备,因此会报下面的错误        # ioctl(TUNSETIFF): Device or resource busy        # 启动tap设备        ip link set $1 up        # brctl addif $switch $1        # 将网桥和tap设备进行桥接        ip link set $1 master $switch        exit 0else        echo "Error: no interface specified"        exit 1fi
创建一个生成随机MAC地址的脚本:

#!/bin/bash# generate a random mac address for the qemu nicprintf 'DE:AD:BE:EF:%02X:%02X\n' $((RANDOM%256)) $((RANDOM%256))
启动客户机的脚本:

#!/bin/bash# $1 base name of virtual disk# $2 memory size# $3 tap device id mac=`/usr/bin/qemu-genmac`src=/usr/bin/qemu-ifupsudo qemu-system-x86_64 -enable-kvm -device e1000,netdev=$3,mac=$mac -netdev tap,id=$3,script=$src,downscript=no \                        -hda ~/Vmware/KVM/$1.img -m $2

为上面的脚本文件添加可执行权限:

sudo chmod +x /usr/bin/qemu-ifup-br0sudo chmod +x /usr/bin/qemu-genmacsudo chmod +x /usr/bin/qemu-start-br0

执行下面的命令,启动一台客户机(或者更多虚拟机,但是命令中的tap0要更换为不同的名字):

/usr/bin/qemu-start centos7-base 512 tap0

修改客户机的IP地址,使用10.0.0.0/8网段:

TYPE=EthernetBOOTPROTO=staticDEFROUTE=yesPEERDNS=yesPEERROUTES=yesIPV4_FAILURE_FATAL=noIPV6INIT=noNAME=ens3UUID=d9f47102-b177-4a27-ae98-86f6939d6680DEVICE=ens3ONBOOT=yesIPADDR=10.0.0.10PREFIX=8GATEWAY=10.0.0.1
现在可以互相ping客户机和宿主机,应该可以正常连通了。

私有桥接下访问互联网

上一节介绍的这种基于TAP的私有桥接网络,可以让客户机、宿主机相互连通,但是客户机无法访问互联网。

要解决此问题,你可以选择以下方法之一:

  1. 让客户机通过宿主机暴露的HTTP/SOCKS代理上网
  2. 配置宿主机的路由规则,设置好源地址转换即可:
sudo sysctl -w net.ipv4.ip_forward=1 # 对客户机网段进行源地址转换sudo iptables -t nat -A POSTROUTING  -s 10.0.0.0/255.0.0.0 ! -d 10.0.0.0/255.0.0.0 -j MASQUERADE 


公共桥接网络

此方式和私有桥接网络类似,主要区别是,除了TAP设备桥接到网桥之外,以太网卡(例如eth0)也桥接到网桥(例如br1)。

你可以通过发行版的配置文件来配置网桥:

# 注意网络管理器组件的影响# 去掉 auto eth0,改为:auto br1 # 配置br1iface br1 inet dhcp    bridge_ports    eth0    bridge_stp      off    bridge_maxwait  0    bridge_fd       0    # 这里附加上原来属于eth0的配置
或者基于脚本来配置: 

sudo ip link add br1 type bridgesudo ip link set br1 upsudo ip link set eth0 master br1  # DHCPsudo killall dhclient && sudo ip addr flush dev eth0sudo dhclient br1


无论用哪种方式,都应该注意到eth0的IP地址需要转移给br1,这样才能确保网络正常运作——br1必须在链路层接收到相关ARP请求,并决定是否需要转发给客户机,eth0没有这种转发能力。

如果eth0所在网络是基于DHCP的,那么客户机配置为DHCP后,会自动获取公共IP地址。否则,需要手工设置客户机的IP地址。 

基于TAP的桥接的简化配置

现在QEMU支持自动桥接TAP设备到宿主机的一个网桥,因此你不再需要编写脚本,修改网络后端为bridge即可:

-netdev bridge,id=tap0,br=br0

注意,使用上述选项时,QEMU需要读取配置文件/etc/qemu/bridge.conf,你只需在此文件中添加一行代码:
allow br0
你可以编写如下脚本自动创建网桥、配置iptables规则。示例:

# Create private bridge link for QEMU/sbin/iplinkaddbr0typebridge/sbin/iplinksetbr0up/sbin/ipaddradd10.0.0.1devbr0/sbin/iprouteadd10.0.0.0/8devbr0# NAT for 10.0.0.0/8/sbin/iptables-tnat-APOSTROUTING  -s10.0.0.0/255.0.0.0!-d10.0.0.0/255.0.0.0  -jMASQUERADE  # Create public bridge link for QEMU/sbin/iplinkaddbr1typebridge/sbin/iplinksetbr1up/sbin/iplinkseteth0masterbr1/usr/bin/killalldhclient&&/sbin/ipaddrflushdeveth0/sbin/dhclientbr1

macvtap直连

关于MacVTap的相关知识,参考Linux知识集锦。建议和libvirt一起使用macvtap。 

基于libvirt的桥接

在使用libvirt时,客户机(Domain)的网络接口配置可以简化为:

<interface type='bridge'>    <mac address='DE:AD:BE:EF:F1:00'/>    <source bridge='br0'/>    <target dev='tap0'/>    <model type='virtio'/></interface>

基于libvirt VLAN的桥接

可以使用libvrit的虚拟局域网,这样宿主机上不会为客户机创建专门的tap设备,那些手工编写的脚本也全都不需要了。虚拟网络配置示例:

<network>  <name>default</name>  <uuid>9bae4de8-ca58-48c5-ba58-109aebf8b954</uuid>  <forward mode='nat'>  </forward>  <bridge name='virbr0' stp='on' delay='0'/>  <ip address='10.0.0.1' netmask='255.0.0.0'>    <dhcp>      <range start='10.0.0.100' end='10.0.0.200'/>    </dhcp>  </ip></network>
客户机(Domain)的网络接口配置示例:
<interface type='network'>    <mac address='DE:AD:BE:EF:F1:00'/>    <source network='default'/>    <model type='virtio'/></interface>
另外,libvirt的虚拟网络提供了DHCP功能,因此客户机的IP地址不需要静态设置。





0 0