参考:https://wiki.libvirt.org/page/Networking
Networking
本文介绍了基于libvirt的应用的通用网络配置。可用于所有虚拟化,不管是Xen,KVM或者其他。
两种方式 "virtual network" , "shared physical device"。前者在所有的发布版本上都是一致的,封装好的,可以直接使用。后者需要自定义配置。
1 NAT forwarding (即 "virtual networks")
1.1 Host configuration
1.2 Guest configuration
1.3 Applying modifications to the network
1.3.1 virsh net-update
1.3.2 Arbitrary changes to the network
1.4 Forwarding Incoming Connections
2 Bridged networking (即 "shared physical device")
2.1 Host configuration
2.1.1 Fedora/RHEL Bridging
2.1.1.1 Using NetworkManager directly
2.1.1.2 Disabling NetworkManager (for older distros)
2.1.1.3 Creating network initscripts
2.1.2 Debian/Ubuntu Bridging
2.2 Guest configuration
3 PCI Passthrough of host network devices
3.1 Assignment with
3.2 Assignment with
3.3 Assignment from a pool of SRIOV VFs in a libvirt
4 Other networking docs/links
NAT forwarding (即 "virtual networks")
Host configuration
每个标准libvirt安装都提供自带的NAT基础连接到虚机。这也被称为'default virtual network'。你可以通过如下操作查看:
# virsh net-list --all
Name State Autostart
-----------------------------------------
default active yes
如果没有,那么如下的example XML config可以加载激活使用。
# virsh net-define /usr/share/libvirt/networks/default.xml
Network default defined from /usr/share/libvirt/networks/default.xml
# virsh net-autostart default
Network default marked as autostarted
# virsh net-start default
Network default started
当libvirt的default network运行,你可以看到一个独立的网桥设备。这个设备实际上没有任何物理接口,因为它使用NAT+转发 来连接外面的网络。不需要加任何接口。
# brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.000000000000 yes
Libvirt会添加iptables rules到 INPUT, FORWARD, OUTPUT and POSTROUTING 规则链以允许guest的出入流量使用virbr0设备。它需要开启ip_forward。有些应用可能会禁用ip_forward,所以最好将如下配置添加到 /etc/sysctl.conf.
net.ipv4.ip_forward = 1
如果你在服务器上运行了dnsmasq,请参考 libvirtd and dnsmasq.
Guest configuration
如果host configuration完成了,guest就可以通过network name连到虚拟网络了。比如,如果要将一个guest连到'default'虚拟网络,你需要编辑该guest的domain configuration file:
virsh edit
这里
MAC地址是可选的,如果没有会自动创建。
Applying modifications to the network
有时候,需要在运行的时候编辑网络。最常见的场景,添加新的 static MAC+IP映射虚拟网络的DHCP server。如果你通过"virsh net-edit"编辑网络,任何变更在网络被销毁重启前不会生效,这会导致所有的guest丢失网络连接直到它们的网卡接口重新连接。
virsh net-update
幸运的是,有很多网络变更操作可以通过"virsh net-update"立即生效,比如上面提到的在DHCP绑定MAC+IP。
比如, 添加一个名字为"default"的静态DHCP地址映射连到网络,MAC地址53:54:00:00:01映射到IP地址192.168.122.45,hostname为"bob",可以用如下命令:
virsh net-update default add ip-dhcp-host \
" " \
--live --config
virsh net-update子命令除了 "add", 还有"delete" ,"modify" (for some items),"add-first", "add-last"。
如下是可以使用virsh net-update配置的网络配置项:
ip-dhcp-host
ip-dhcp-range (add/delete only, no modify)
forward-interface (add/delete only)
portgroup
dns-host
dns-txt
dns-srv
注意,命令行的最后内容(并非"--live --config")应该是你想要add/modify/delete的XML片段。
比如,"virsh net-update default add forward-interface"后面跟的XML应该类似于"
(注意引号的使用 - 因为XML包含空格和字符转义,你必须用引号将真个XML片段包含起来,但这也意味着XML内只能使用单引号,或者反斜杠)
Arbitrary changes to the network
虽然很多配置变更可以使用 "virsh net-update",但是还有一些不可以。 在这种情况下,所有的guests只能断开网络知道网络重启。为了解决这个问题,一个可行的解决方案就是,在网络重启后,通过脚本自动挂载所有主机上的所有的接口。
脚本范例 (虽然很久之前用过,但是也有很多人报告失效了) is available here.
Forwarding Incoming Connections
默认,以
如果你想把NAT虚拟网后的一个服务发布出去,你可以给qemu设置一个 libvirt 的 "hook" 脚本,来安装必要的iptables规则转发forward incoming connections to the host on any given port HP to port GP on the guest GNAME。
- 定义
a) guest 的 name 为 "G" (定义在 libvirt domain XML中)
b) guest 的IP地址 为 "I"
c) 接受连接的guest port 为 "GP"
d) 转发连接到guest的 host port 为 "HP"
(为使得guest's IP address 保持不变, 你可以给 guest OS 配置固定IP, 或者在
停止guest运行
创建文件 /etc/libvirt/hooks/qemu (或在一个已经存在的hook script后追加如下内容), 内容类似 (根据你的情况替换GNAME, IP, GP, and HP 变量):
如下是basic script,或者参考"advanced" 版本 here or here's a python script
#!/bin/bash
# IMPORTANT: Change the "VM NAME" string to match your actual VM Name.
# In order to create rules to other VMs, just duplicate the below block and configure
# it accordingly.
if [ "${1}" = "VM NAME" ]; then
# Update the following variables to fit your setup
GUEST_IP=
GUEST_PORT=
HOST_PORT=
if [ "${2}" = "stopped" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -D FORWARD -o virbr0 -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
fi
if [ "${2}" = "start" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -I FORWARD -o virbr0 -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
fi
fi
chmod +x /etc/libvirt/hooks/qemu
重启 libvirtd service.
启动guest.
(注意: 这个办法是hack行为,在libvirt 0.9.13 版本前有瑕疵,如果libvirtd 在guest运行的时候重启了, 所有的支撑virtual network的标准Iptables rules会被重新加载, 导致变更了跟reject rule 有关的FORWARD rule 顺序, 那么在guest 停止和重启之前,这部分不工作了。 在libvirt-0.9.13 和 更新的版本,使用新"reconnect" hook , 在新版本的libvirt中,这个缺陷不存在了。 (不管怎么说, 这个 hook script 依然被认为是非常规操作---hack)。
Bridged networking (即 "shared physical device")
Host configuration
NAT连接使用方便,或者用于自动配置网络连接的情况。更高级的一些用户希望使用桥接方式,guest直接连到Lan网络。下面根据不同的发行版本或者OS版本,做了说明。
注意: 无线不可以使用桥接模式。
注意: 如果你配置桥接后,你发现你的网络连接挂了,不工作了,有可能是路由器/交换机屏蔽了“unauthorized switches”(比如,通过侦测BPDU包)。你需要配置主机网口工作为"switch"。
Fedora/RHEL Bridging
这部分展示如何通过标准网络初始化脚本和systemctl设置桥接。
- 使用NetworkManager 配置
如果发行版有 NetworkManager, 原生支持桥接。文档如下:
- 使用 nm-connection-editor UI: https://www.happyassassin.net/2014/07/23/bridged-networking-for-libvirt-with-networkmanager-2014-fedora-21/
- 使用命令行: https://lukas.zapletalovi.com/2015/09/fedora-22-libvirt-with-bridge.html
- 不使用NetworkManager (for older distros)
如果你的版本是2015年前的,NetworkManager 不支持桥接的设置,只能用传统的网络设置方式,并且不使用NetworkManager管理。( "NM_CONTROLLED=no" )
彻底关闭NetworkManager也是可以的。
# chkconfig NetworkManager off
# chkconfig network on
# service NetworkManager stop
# service network start
- Creating network initscripts
在 /etc/sysconfig/network-scripts 目录,创建两个配置文件。
第一个文件ifcfg-eth0
定义了物理网络接口信息,并且指定归属网桥。
# cat > ifcfg-eth0 <
将HWADDR更改为你的网卡MAC地址。你也可以配置设备的MTU。比如: MTU=9000。
第二个文件 ifcfg-br0
定义桥接设备:
# cat > ifcfg-br0 <
WARNING: TYPE=Bridge 是区分大小写的。
配置完毕后,重启网络 (or reboot)
# service network restart
最后,关闭桥接的网络过滤器netfilter
。
# cat >> /etc/sysctl.conf <
为了性能和安全,建议这么配置。 See Fedora bug #512206.
或者,你可以配置iptables在桥接设备上转发所有:
# echo "-I FORWARD -m physdev --physdev-is-bridged -j ACCEPT" > /etc/sysconfig/iptables-forward-bridged
# lokkit --custom-rules=ipv4:filter:/etc/sysconfig/iptables-forward-bridged
# service libvirtd reload
现在,你有一个 "shared physical device"设备了, 可以用于guests直接接入LAN。
# brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.000000000000 yes
br0 8000.000e0cb30550 yes eth0
注意桥接是完全独立于 virbr0的,不要将物理设备绑定到virbr0。Virbr0仅用于NAT网络连接。
Debian/Ubuntu Bridging
Debian wiki bridging 的文档: https://wiki.debian.org/BridgeNetworkConnections
Guest configuration
要让虚拟机使用桥接,配置文件必须定义桥接。 Bridge to LAN
其实,可以通过bridge name 来配置连接。假设,shared physical device 的 bridge 被定义为 “br0”,guest XML可以配置如下:
# try this if you experience problems with VLANs
mac address 是可选的,如果忽略将会自动生成。
使用 virsh edit
命令来编辑虚拟机配置文件
FAQ :http://wiki.libvirt.org/page/FAQ#Where_are_VM_config_files_stored.3F_How_do_I_edit_a_VM.27s_XML_config.3F
PCI Passthrough of host network devices
还可以将主机的PCI网络设备直接赋予guest。但是首先要保证主机支持 Intel VT-d
or AMD IOMMU
扩展。
有两种方式:
Assignment with
将 generic PCI device 挂载到guest的常用方式:
libvirt PCI Device Assignment
Assignment with
SRIVO Single-root I/O virtualization,单根I/O虚拟化。SR-IOV 使一个单一的功能单元(比如,一个以太网端口)能看起来像多个独立的物理设备,即支持SR-IOV 功能的物理设备能被配置为多个功能单元。
SRIOV 网卡可以提供多路"Virtual Functions" (VF),可以分别挂载给使用PCI设备的guests,并且每个都等效一个物理网卡。这允许许多guests通过直连PCI设备获得高性能,但是只使用一个物理插槽。
VFs可以给以传统方式
可以在把VF赋予guest前就配置好MAC地址。但是在
为了解决这个问题, libvirt-0.9.10 增加了一个新配置项
为了使用
如上信息了解后,你可以编辑guest domain configuration来配置一个设备,参考如下:
...
...
...
(注意,如果没有提供mac地址,会自动创建就和其他类型的interface设备一样 。 另外, 如果你连到一个802.11Qgh硬件交换设备只能使用
element (802.11Qbg (即 "VEPA") switches 在这个模式不支持)
).
当 guest 启动, 应该能看到一个已经配置好MAC地址的由物理设备提供的网络设备。 这个MAC地址在guest和host重启前保持不变。
SRIOV VFs 池的分配在libvirt
把PCI地址赋予guest配置有 两个严格限制:
任何时候,当guest启动时指定的VF必须可用,即管理员必须永久的分配每个VF到单个guest。 (或者每次当guest启动的时候,赋予guest一个当前未使用的VF's PCI address。)
如果guest被移动到其他host,那台host必须在相同的PCI总线位置有相同的硬件。 (或者,在启动前修改guest配置)
从 libvirt 0.10.0 开始,这些都可以通过以 device pool创建libvirt network的方式避免。Device pool 包含SR-IOV的所有的 VFs信息, 然后配置guest调用这个网络;每当guest启动, 一个单独的 VF会从池内取出分配给guest;当guest关闭, VF将被返还到池内以供其他guest使用
如下是一个网络配置范例,一个定义在host上名为"eth3"的,SR-IOV设备VFs池。
passthrough
要使用这个网络,将如上配置到 /tmp/passthrough.xml (使用你自己的SR-IOV device's PF替换 "eth3" ), 然后执行如下命令:
virsh net-define /tmp/passthrough.xml
virsh net-autostart passthrough
virsh net-start passthrough.
虽然只有一个设备被显示出来, libvirt 会自动获得一个首次使用如下interface定义的guest的PF的所有VFs 清单 :
你可以在启动第一个使用该网络的guest后,执行 "virsh net-dumpxml passthrough"命令来确认; 类似如下输出:
passthrough
a6b49429-d353-d7ad-3185-4451cc786437
Other networking docs/links
- David Lutterkort's guide. 注意, 'peth0' (physical) 和 'eth0' (bridge) 在 Fedora 9 不再生效了。由 'eth0' (physical) 和 'br0' (bridge) 替代。
- Anthony Liguori's guide . Debian的 'shared physical devices'
- manual KVM networking - 不使用libvirt加载guests的情况
- Ubuntu libvirt guide -网桥配置节选