Friday, February 13, 2015

Libvirt/KVM 中的网络模式

NAT

默认方式。虚拟机获取一个私有 IP(例如 192.168.122.0/24 网段的),并通过本地主机的 NAT 访问外网。
创建一个本地网桥 virbr0,包括两个端口:virbr0-nic 为网桥内部端口,vnet0 为虚拟机网关端口(192.168.122.1)。

brctl show

bridge name bridge id STP enabled interfaces virbr0 8000.52540082327e yes virbr0-nic vnet0
虚拟机启动后,配置 192.168.122.1(vnet0)为网关。所有网络操作均由本地主机系统负责。

DNS/DHCP 的实现

本地主机系统启动一个 dnsmasq 来负责管理。
# ps aux|grep dnsmasq
nobody    2496  0.0  0.0  12892   572 ?        S     2014   0:18 /usr/sbin/dnsmasq --strict-order --pid-file=/var/run/libvirt/network/default.pid --conf-file= --except-interface lo --bind-interfaces --listen-address 192.168.122.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmas /default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts

NAT 的实现

主机系统负责进行 SNAT。
# iptables -nvL -t nat
Chain PREROUTING (policy ACCEPT 76M packets, 3728M bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 412K packets, 28M bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  tcp  --  *      *       192.168.122.0/24    !192.168.122.0/24    masq ports: 1024-65535
  231 27466 MASQUERADE  udp  --  *      *       192.168.122.0/24    !192.168.122.0/24    masq ports: 1024-65535
62902 5535K MASQUERADE  all  --  *      *       192.168.122.0/24    !192.168.122.0/24

Chain OUTPUT (policy ACCEPT 412K packets, 28M bytes)
 pkts bytes target     prot opt in     out     source               destination

通过 MacvTap 直接挂在虚机到物理网卡

比较新的 kvm 中支持。基于原先的 MacVlan + tun。
原理是创建一个 tun 设备,直接绑定到指定的(物理)端口进行收发包,在系统中生成 macvtapN@ethX 类似格式的虚拟网卡。
# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:1a:64:99:f2:60 brd ff:ff:ff:ff:ff:ff
14: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether 52:54:00:82:32:7e brd ff:ff:ff:ff:ff:ff
15: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 500
    link/ether 52:54:00:82:32:7e brd ff:ff:ff:ff:ff:ff
70: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 500
    link/ether fe:54:00:39:c8:23 brd ff:ff:ff:ff:ff:ff
71: macvtap0@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UNKNOWN qlen 500
    link/ether 52:54:00:66:79:1d brd ff:ff:ff:ff:ff:ff
共有四种模式:VEPA、bridge、private、passthrough。
libvirt 的配置文件中关键信息为
 <devices>
    ...
    <interface type='direct'>
      <source dev='eth0' mode='vepa'/>
    </interface>
  </devices>

VEPA (Virtual Ethernet Port Aggregator)

默认模式。多个虚拟机指定同一个接口(例如 eth0),通过该接口连接到外部的物理网络。但虚机之间的访问需要先绕到外部的物理(也可以配置为软交换机)交换机,然后由外部交换机进行转发,再绕回来。
需要外部交换机支持 Reflective Relay,或者发夹(Hairpin)模式,即从一个接口发上来的流量还能扔回去。

bridge

跟 VEPA 模式类似,但绑到同一接口上(不确定同一主机上多个网卡之间是否可以)上的多个虚机之间直接本地就转发到对应的 macvtap 设备上了,不需要到外面再绕回来。当然,要求源和目的虚机都配置为 bridge 模式。

private

虚拟机之间不能相互访问,即使外部交换机支持 Reflective Relay 也不成。除非虚机处在不同的子网,经过外面网关的转发再绕回来。要求源和目的虚机都配置为 private 模式。这种模式是不是很眼熟,多租户的公有云里面应该用处挺大。

passthrough

如果本地物理网卡支持 SRIOV,那虚机可以直接绑定到不同的 VF 上。这种模式支持虚机迁移。

连接到本地的软件交换机

例如 OpenvSwitch 等,可以先在软件交换机上创建一个 tap 接口,然后在 kvm 中指定绑定到这个 tap 接口。
跟 MACvTap 比,因为 tap 口已经创建了,直接绑定即可。
这种情况下跟 MACvTap 类似,本地系统不进行地址分配和 NAT 等,需要用户自己配置。

基本步骤

需要的脚本:
/etc/ovs-ifup
--------------------------------------------------------------------
#!/bin/sh

switch='br0'
/sbin/ifconfig $1 0.0.0.0 up
ovs-vsctl add-port ${switch} $1
--------------------------------------------------------------------

/etc/ovs-ifdown
--------------------------------------------------------------------
#!/bin/sh

switch='br0'
/sbin/ifconfig $1 0.0.0.0 down
ovs-vsctl del-port ${switch} $1
--------------------------------------------------------------------
创建网桥和虚拟接口。
# ovs-vsctl add-br br0
# ovs-vsctl add-port br0 eth0
启动虚拟机。
# kvm -m 512 -net nic,macaddr=00:11:22:EE:EE:EE -net \
tap,script=/etc/ovs-ifup,downscript=/etc/ovs-ifdown -drive \
file=/path/to/disk-image,boot=on

参考的 libvirt 虚机配置

[...]
    <interface type='bridge'>
      <mac address='52:54:00:fb:00:01'/>
      <source bridge='ovsbr0'/>
      <virtualport type='openvswitch'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
[...]

参考

  • https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Virtualization_Administration_Guide/chap-Virtualization_Administration_Guide-Virtual_Networking.html
  • http://seravo.fi/2012/virtualized-bridged-networking-with-macvtap
  • http://git.openvswitch.org/cgi-bin/gitweb.cgi?p=openvswitch;a=blob_plain;f=INSTALL.KVM;hb=HEAD

No comments:

Post a Comment