Appearance
在安装虚拟化组件时,通常会自动创建一个默认的虚拟网络配置,这包括一个名为virbr0的网桥、virbr0-nic的虚拟网络接口、iptables的NAT配置及DNSMASQ的配置等。
==libvirt网络的最重要的组件是虚拟网络交换机,默认由linux的网桥实现。Libvirt默认会创建一个名为virbr0的网桥。虚拟网络交换机也是从其接收的数据包中获得MAC地址,并存储在MAC表中。物理交换机的端口数量有限,而虚拟机交换机的端口数量则没有限制。==
查看默认网络配置文件
[root@localhost ~]# virsh net-list
Name State Autostart Persistent
--------------------------------------------
default active yes yes
[root@localhost ~]# virsh net-dumpxml default
<network connections='1'>
<name>default</name>
<uuid>83d85c8b-6d82-4e4b-a368-eb419a58bb2b</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:55:86:28'/>
<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>
</network>forward mode:定义了虚拟网络将连接到物理网络,mode属性确认了转发方法,目前允许的方法由:
nat
router
open
birdge
private
vepa
passthrough
hostdev
如果没有配置forward属性,则该网络与任何其他网络都是隔离的,也就是isolated模式。nat会在连接到该网络的虚拟机和物理网络之间进行网络地址转换。
TUN/TAP设备的工作原理与管理
libvirt的虚拟网络离不开TAP类型的虚拟网络接口设备。
虚拟网络接口设备完成的功能与物理网卡类似,有两种常见类型:TUN和TAP。在Linux内核官方网站上是这样定义的:TUN/TAP为用户空间程序提供数据包的接收和传输。可以将其视为简单的点对点或以太网设备。它们不是从物理介质接收数据包,而是从用户空间程序接收数据包。它们也不是通过物理介质发送数据包,而是将其写入用户空间程序。
也就是说,TUN/TAP接口是没有关联物理设备的虚拟接口。用户空间程序可以附加到TUN/TAP接口并处理发送到该接口的流量。

使用TUN/TAP技术可以在主机上构建虚拟网络接口,它们的功能类似物理网卡,可以为其分配IP,将数据包路由到该接口、分析流量等。TUN/TAP由两种常用的应用场景:VPN和云计算。
TUN设备在OSI模型的第三层,它实现的是虚拟的IP点对点接口,应用程序只能从此接口发送或接收IP数据包。他没有MAC地址,而且不能成为网桥的slave设备。
TAP的运行方式与TUN极为相似,但是它运行在OSI模型的第二层上,应用程序从此接口发送到接收原始以太网数据包,所以它与以太网卡特别相似。他有MAC地址,可以成为网桥的slave设备。
首先是IP命令。ip是iprouter软件包里面的一个强大的网络配置工具,其中tuntap子命令可用于管理TUN/TAP接口,命令如下:
[root@localhost ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:7a:a0:f1 brd ff:ff:ff:ff:ff:ff
altname enp3s0
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:7a:a0:fb brd ff:ff:ff:ff:ff:ff
altname enp19s0
4: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:55:86:28 brd ff:ff:ff:ff:ff:ff
5: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master virbr0 state UNKNOWN mode DEFAULT group default qlen 1000
link/ether fe:54:00:77:1b:a0 brd ff:ff:ff:ff:ff:ff
[root@localhost ~]# ip tuntap help
Usage: ip tuntap { add | del | show | list | lst | help } [ dev PHYS_DEV ]
[ mode { tun | tap } ] [ user USER ] [ group GROUP ]
[ one_queue ] [ pi ] [ vnet_hdr ] [ multi_queue ] [ name NAME ]
Where: USER := { STRING | NUMBER }
GROUP := { STRING | NUMBER }
[root@localhost ~]# ip tuntap list
vnet0: tap vnet_hdrlibvirt在创建TAP设备时,会根据虚拟机网卡类型及用途为TAP设备增加额外的标记,例如为virtio类型网卡增加的标记是vnet_hdr,而对于传统的e1000的网卡则是不设置标记。
新增tap设备
[root@localhost ~]# ip tuntap add dev tap-nicl mode tap
[root@localhost ~]# ip tuntap list
vnet0: tap vnet_hdr
tap-nicl: tap persist
[root@localhost ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:7a:a0:f1 brd ff:ff:ff:ff:ff:ff
altname enp3s0
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:7a:a0:fb brd ff:ff:ff:ff:ff:ff
altname enp19s0
4: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:55:86:28 brd ff:ff:ff:ff:ff:ff
5: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master virbr0 state UNKNOWN mode DEFAULT group default qlen 1000
link/ether fe:54:00:77:1b:a0 brd ff:ff:ff:ff:ff:ff
6: tap-nicl: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 22:aa:20:a3:92:7a brd ff:ff:ff:ff:ff:ff
[root@localhost ~]# ip addr add 172.16.123.1/24 dev tap-nicl我们可以像管理物理网卡一样管理虚拟网络接口,最后一条命令我们给这个TAP设备新增一个ip地址。
删除TAP设备
[root@localhost ~]# ip tuntap del dev tap-nicl mode tap
[root@localhost ~]# ip tuntap list
vnet0: tap vnet_hdrRHEL/CentOS8中使用ip命令配置设备信息,大部分会在设备重启后还原。如果需要持久的TUN/TAP设置,则推荐使用NetworkManager来创建。下面我们通过NetworkManager中的命令行工具nmcli来做类似的实验,命令如下:
[root@localhost ~]# nmcli connection add type tun connection.interface-name newcon1 ifname tap-nic2 mode tap ip4 172.16.123.2/24
Connection 'tun-tap-nic2' (e891d66c-6f3b-4d68-b07b-7fda539d0bdc) successfully added.
[root@localhost ~]# nmcli connection
NAME UUID TYPE DEVICE
ens160 ea093dc0-034a-3862-bd3a-7a5480b1ef41 ethernet ens160
tun-tap-nic2 e891d66c-6f3b-4d68-b07b-7fda539d0bdc tun tap-nic2
lo 74d2fe3a-6414-4a08-9dce-52dad0e64ebd loopback lo
virbr0 6c53ec6a-6a35-4ebf-87e7-106e840b2ee3 bridge virbr0
vnet0 69fbcf34-d668-420c-b96d-6d8e8484cd2c tun vnet0
[root@localhost ~]# nmcli device
DEVICE TYPE STATE CONNECTION
ens160 ethernet connected ens160
tap-nic2 tun connected tun-tap-nic2
lo loopback connected (externally) lo
virbr0 bridge connected (externally) virbr0
vnet0 tun connected (externally) vnet0
ens224 ethernet disconnected --NetworkManager支持的连接类型有多种,包括ehternet、wifi、pppoe、infiniband、bluetooth、bond、bridge、tun、vxlan等。需要注意的是,NetworkManager不区分连接类型究竟是TUN还是TAP,统一称为TUN。
清除虚拟网络接口设备tap-nic2
[root@localhost ~]# nmcli connection delete tun-tap-nic2网桥工作原理与管理
网桥是一种数据链路层的设备。2.4版本后的linux内核之中已经集成了网桥功能。在虚拟化解决方案中,网桥是一个很重要的组件。
通过iproute管理网桥
在iproute软件包中,ip命令是最常用的命令,下面通过它创建一个网桥接口,网桥接口的名称可以用于表示网桥。
[root@localhost ~]# ip link add name br2 type bridge
[root@localhost ~]# ip a
8: br2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 96:b0:04:3d:f6:30 brd ff:ff:ff:ff:ff:ff
[root@localhost ~]# ip link
8: br2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 96:b0:04:3d:f6:30 brd ff:ff:ff:ff:ff:ff从上面的命令可以知道,网桥在被创建出来时会生成一个随机的mac地址。
有了网桥,下面就可以为其添加子接口了。网桥上的子接口既可以是物理接口也可以是虚拟机接口,本次实验将使用虚拟接口。
[root@localhost ~]# ip tuntap add dev tap-nic1 mode tap
[root@localhost ~]# ip tuntap add dev tun-nic1 mode tun
[root@localhost ~]# ip tuntap
vnet0: tap vnet_hdr
tap-nic1: tap persist
tun-nic1: tun persist
[root@localhost ~]# ip link
8: br2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 96:b0:04:3d:f6:30 brd ff:ff:ff:ff:ff:ff
9: tap-nic1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 0a:29:83:8d:68:c8 brd ff:ff:ff:ff:ff:ff
10: tun-nic1: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 500
link/none从输出可以看出,tap-nic1与br2的MAC地址是不同的。由于tun-nic1是一个三层设备,所以它没有MAC地址的。
接下来激活连接及设置子接口
[root@localhost ~]# ip link set br2 up
[root@localhost ~]# ip link set tap-nic1 up
[root@localhost ~]# ip link set tun-nic1 up
[root@localhost ~]# ip link set tap-nic1 master br2
[root@localhost ~]# ip link set tun-nic1 master br2
RTNETLINK answers: Invalid argument由于tun-nic1是一个三层设备,它无法充当网桥的子接口,所以命令执行失败。
查看网络配置
[root@localhost ~]# ip a
8: br2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 0a:29:83:8d:68:c8 brd ff:ff:ff:ff:ff:ff
inet6 fe80::94b0:4ff:fe3d:f630/64 scope link
valid_lft forever preferred_lft forever
9: tap-nic1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel master br2 state DOWN group default qlen 1000
link/ether 0a:29:83:8d:68:c8 brd ff:ff:ff:ff:ff:ff
10: tun-nic1: <NO-CARRIER,POINTOPOINT,MULTICAST,NOARP,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 500
link/noneLinux网桥有个特性:它会自动将第一个网络接口的MAC当作自己的MAC地址。
Libvirt也有一个特性:默认情况下Libvirt生成的MAC地址是·52:54:00开头的。
清理环境
[root@localhost ~]# ip link set tap-nic1 nomaster
[root@localhost ~]# ip link delete br2 type bridge
[root@localhost ~]# ip tuntap delete tap-nic1 mode tap
[root@localhost ~]# ip tuntap delete tun-nic1 mode tun通过NetworkManager管理网桥
可以通过nmcli的connection子命令来管理网桥。与IP命令类似,它也是先创建网桥的连接再创建子接口。不同之处是他会自动创建网桥接口文件。
再下面的实验中,我们将使用一块新网卡ens224作为新网桥的子接口
[root@localhost ~]# nmcli connection add type bridge autoconnect yes connection.interface-name virbr1 ifname virbr1
Connection 'bridge-virbr1' (f2a7e8f6-7200-44da-9020-587d3fa37cc6) successfully added.
[root@localhost ~]# nmcli connection
NAME UUID TYPE DEVICE
ens160 ea093dc0-034a-3862-bd3a-7a5480b1ef41 ethernet ens160
bridge-virbr1 f2a7e8f6-7200-44da-9020-587d3fa37cc6 bridge virbr1
lo 74d2fe3a-6414-4a08-9dce-52dad0e64ebd loopback lo
virbr0 6c53ec6a-6a35-4ebf-87e7-106e840b2ee3 bridge virbr0
vnet0 69fbcf34-d668-420c-b96d-6d8e8484cd2c tun vnet0
[root@localhost ~]# nmcli device
DEVICE TYPE STATE CONNECTION
ens160 ethernet connected ens160
virbr1 bridge connecting (getting IP configuration) bridge-virbr1
lo loopback connected (externally) lo
virbr0 bridge connected (externally) virbr0
vnet0 tun connected (externally) vnet0
ens224 ethernet disconnected --
[root@localhost ~]# cat /etc/NetworkManager/system-connections/bridge-virbr1.nmconnection
[connection]
id=bridge-virbr1
uuid=f2a7e8f6-7200-44da-9020-587d3fa37cc6
type=bridge
interface-name=virbr1
[ethernet]
[bridge]
[ipv4]
method=auto
[ipv6]
addr-gen-mode=default
method=auto
[proxy]为网桥添加静态地址
[root@localhost ~]# nmcli connection modify bridge-virbr1 ipv4.address 192.168.100.3/24 ipv4.method manua
[root@localhost ~]# cat /etc/NetworkManager/system-connections/bridge-virbr1.nmconnection
[connection]
id=bridge-virbr1
uuid=f2a7e8f6-7200-44da-9020-587d3fa37cc6
type=bridge
interface-name=virbr1
[ethernet]
[bridge]
[ipv4]
address1=192.168.100.3/24
method=manual
[ipv6]
addr-gen-mode=default
method=auto
[proxy]将物理网卡绑定到网桥上
[root@localhost ~]# nmcli connection add type bridge-slave autoconnect yes connection.interface-name ens224 master virbr1
Connection 'bridge-slave-ens224' (2c51dd14-9b43-49c5-a254-aa1babaf6048) successfully added.
[root@localhost ~]# nmcli connection
NAME UUID TYPE DEVICE
ens160 ea093dc0-034a-3862-bd3a-7a5480b1ef41 ethernet ens160
bridge-slave-ens224 2c51dd14-9b43-49c5-a254-aa1babaf6048 ethernet ens224
bridge-virbr1 f2a7e8f6-7200-44da-9020-587d3fa37cc6 bridge virbr1
lo 74d2fe3a-6414-4a08-9dce-52dad0e64ebd loopback lo
virbr0 6c53ec6a-6a35-4ebf-87e7-106e840b2ee3 bridge virbr0
vnet0 69fbcf34-d668-420c-b96d-6d8e8484cd2c tun vnet0
[root@localhost ~]# nmcli device
DEVICE TYPE STATE CONNECTION
ens160 ethernet connected ens160
ens224 ethernet connected bridge-slave-ens224
virbr1 bridge connecting (getting IP configuration) bridge-virbr1
lo loopback connected (externally) lo
virbr0 bridge connected (externally) virbr0
vnet0 tun connected (externally) vnet0
[root@localhost ~]# cat /etc/NetworkManager/system-connections/bridge-slave-ens224.nmconnection
[connection]
id=bridge-slave-ens224
uuid=2c51dd14-9b43-49c5-a254-aa1babaf6048
type=ethernet
controller=virbr1
interface-name=ens224
master=virbr1
port-type=bridge
slave-type=bridge
[ethernet]
[bridge-port]
[root@localhost ~]# nmcli connection up bridge-virbr1
Connection successfully activated (master waiting for slaves) (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/10)确认mac地址
[root@localhost ~]# ip a
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master virbr1 state UP group default qlen 1000
link/ether 00:0c:29:7a:a0:fb brd ff:ff:ff:ff:ff:ff
altname enp19s0
11: virbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:7a:a0:fb brd ff:ff:ff:ff:ff:ff
inet 192.168.100.3/24 brd 192.168.100.255 scope global noprefixroute virbr1
valid_lft forever preferred_lft forever
inet6 fe80::d722:b969:f972:6202/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@localhost ~]# bridge link
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master virbr1 state forwarding priority 32 cost 100
5: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master virbr0 state forwarding priority 32 cost 100从输出可以看出ens224的master是virbr1,这说明它是网桥virbr1的子接口。同时注意virbr1的MAC地址已经不是原有哪个随机生成的MAC地址了,而是借用了第一个子接口,即ens224的MAC地址00:0c:29:7a:a0:fb。
清理环境
[root@localhost ~]# cp -rvf /etc/NetworkManager/system-connections/bridge-* ./bak/
'/etc/NetworkManager/system-connections/bridge-slave-ens224.nmconnection' -> './bak/bridge-slave-ens224.nmconnection'
'/etc/NetworkManager/system-connections/bridge-virbr1.nmconnection' -> './bak/bridge-virbr1.nmconnection'
[root@localhost ~]# nmcli connection down bridge-virbr1
Connection 'bridge-virbr1' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/10)
[root@localhost ~]# nmcli connection delete bridge-virbr1
Connection 'bridge-virbr1' (f2a7e8f6-7200-44da-9020-587d3fa37cc6) successfully deleted.
[root@localhost ~]# cat /etc/NetworkManager/system-connections/
bridge-slave-ens224.nmconnection ens160.nmconnection
[root@localhost ~]# cat /etc/NetworkManager/system-connections/bridge-slave-ens224.nmconnection
[connection]
id=bridge-slave-ens224
uuid=2c51dd14-9b43-49c5-a254-aa1babaf6048
type=ethernet
controller=virbr1
interface-name=ens224
master=virbr1
port-type=bridge
slave-type=bridge
[ethernet]
[bridge-port]
[root@localhost ~]# ip a
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:7a:a0:fb brd ff:ff:ff:ff:ff:ff
altname enp19s0
[root@localhost ~]# nmcli connection delete bridge-slave-ens224
Connection 'bridge-slave-ens224' (2c51dd14-9b43-49c5-a254-aa1babaf6048) successfully deleted.
[root@localhost ~]# nmcli connection
NAME UUID TYPE DEVICE
ens160 ea093dc0-034a-3862-bd3a-7a5480b1ef41 ethernet ens160
lo 74d2fe3a-6414-4a08-9dce-52dad0e64ebd loopback lo
virbr0 6c53ec6a-6a35-4ebf-87e7-106e840b2ee3 bridge virbr0
vnet0 69fbcf34-d668-420c-b96d-6d8e8484cd2c tun vnet0
[root@localhost ~]# nmcli device
DEVICE TYPE STATE CONNECTION
ens160 ethernet connected ens160
lo loopback connected (externally) lo
virbr0 bridge connected (externally) virbr0
vnet0 tun connected (externally) vnet0
ens224 ethernet disconnected --为了后续实验,将原有配置文件备份到/root/bak下面
KVM/libvirt常用的网络类型
在掌握TUN/TAP设备及网桥基本原理之后,我们就可以来学习KVM/libvirt常用的网络类型了。
虚拟机支持的网络
为虚拟机创建网络连接的时候,除了需要设置虚拟网卡的设备类型(virtio、e1000或rtl8139)之外,我们还需要为其指定网络连接的目标,可以将其分为两类。
- 虚拟的网络:由libvirt来管理维护,例如NAT,Routed和Isolated等。虚拟机的配置是interface type="network"
- 共享的物理设备:由宿主机操作系统管理维护吗,例如带物理网卡子接口的网桥、宿主机的物理网卡等。虚拟机配置是interface type="bridge"或interface type="direvt"。
在RHEL/Centos Stream中,不同管理工具支持的虚拟机的网络类型、表示方法有些思维的差异。例如:virt-manager使用Network source的一个选项来设置虚拟机的网络连接,如图所示,通过virsh的edit子命令编辑虚拟机的XML文件则可以支持所有的网络类型。

libvirt管理的虚拟网络
在RHEL/Centos stream 中启动libvirted守护程序时,libvirted会读取/etc/libvirt/qemu/networks/autostart/中的符号链接所指向的虚拟网络配置文件,然后使用NetworkManager来创建响应的网桥、TAP等设备,并根据需要配置IP转发、路由表和iptables中的NAT规则,从而为虚拟机提供虚拟网络环境。
NAT模式
对于桌面虚拟化或测试环境来讲,NAT模式是最常用的虚拟网络模式。不需要进行特别配置,此模式的虚拟机就可以访问外部网络,他还允许宿主机与虚拟机直接进行通信。NAT模式的主要“缺点”是宿主机之外的系统无法访问虚拟机。默认的default网络就是NAT模式。
NAT模式的虚拟网络是在iptables的帮助下创建的,其实是使用伪装选项,因此停止iptables会导致虚拟机内部的网络终端。
桥接模式
libvirt不能直接管理桥接模式的网络,所以需要先使用NetworkManager等工具在操作系统中创建一个网桥,然后将一个物理网卡(或捆绑在一起的多个物理网卡)分配给网桥作为子接口,最后将虚拟机连接到此网桥(虚拟交换机)。

网桥是在OSI网络模型的第二层上运行的。网桥(虚拟交换机)virbr1通过ens32与宿主机外部的网络相连接。虚拟机1和虚拟机2在同一个子网中,外部物理网络上的主机可以检测到它们并对其进行访问。
隔离模式
顾名思义,这是一种封闭的网络,连接在此虚拟交换机的虚拟机可以彼此通信,而也可以与宿主机进行通信,但是它们的流量不会通过宿主机扩散到外部,当然也无法从宿主机外部访问它们。

路由模式
在路由模式下,宿主机充当路由器并配置路由规则,虚拟机通过虚拟交换机与物理网络相连。使用此模式有一个关键点:必须在外部路由器或网关设备上设置正确的IP路由,以便答复数据包返回宿柱机,例如:需要有”将目标地址是192.168.100.0/24的数据包转发给ens32的IP地址“的路由,否则这些回复数据包将永远不会到达宿主机。

除非有特殊的需求(如防火墙的DMZ区域),才会创建这种复杂性的网络,否则通常不会使用此模式。
开放模式
开放模式与路由模式类似,区别在libvirt是否为虚拟网络设置防火墙规则。
在路由模式中,libvirt会配置防火墙规则,例如允许DHCP、DNS等流量,而在配置开放模式时,libvirt不会再此虚拟网络生成任何iptables规则,这样就需要用户自行配置。这就是”开放“所代表的含义。
直接附加模式
虚拟机的直接附加模式既没有使用libvirt管理的虚拟网络,也没有使用宿主机上的网桥,而是通过宿主机上的macvtap驱动程序,将虚拟机的网卡直接附加到宿主机的指定物理网卡。
这种模式最大的优点是再物理交换机上可以同时知道宿主机和虚拟机的网卡,从而可以进行统一的管理。
直接附加有四种模式:VEPA、bridge、private、passthrough,它们在流量控制上有一些差异,默认为VEPA模式。
MACVLAN和IPvlan。

PCI直通与SR-IOV
KVM Hypervisor可以将宿主机上符合条件的PCI设备分配给虚拟机,这就是PCI直通。它可以使虚拟机独占式地访问PCI设备,而且不需要或很少需要KVM的参与,所以可以提高性能。
目前大多数网卡支持这种特性,通过PCI直通将它们分配给虚拟机,从而满足对网络性能要求比较高的应用需求。
但是在服务器上安装PCI或者PCI-E设备的数量总是有限的,而且随着设备数量的增加,也会增加成本。SR-IOV就是针对这种问题的一种解决方案。它可以将单个物理PCI设备划分为多个虚拟机的PCI设备,然后把它们分配给虚拟机。例如,将宿主机上支持SR-IOV功能的网卡划分成多个独立的虚拟网卡,将每个虚拟网卡分配给一个虚拟机使用。
创建和管理桥接的网络
当前网络环境:
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:7a:a0:f1 brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 192.168.200.223/24 brd 192.168.200.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe7a:a0f1/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:7a:a0:fb brd ff:ff:ff:ff:ff:ff
altname enp19s0
4: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 52:54:00:55:86:28 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
5: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master virbr0 state UNKNOWN group default qlen 1000
link/ether fe:54:00:77:1b:a0 brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fe77:1ba0/64 scope link
valid_lft forever preferred_lft forever接下来要做的事情:
- 创建网桥
- 将ens224绑定到网桥上
- 给网桥配置地址
- 启用网桥
- 在libvirt新增我们创建的网桥设备
- 新建虚拟机,将网络配置到我们的网桥上
创建网桥
[root@localhost ~]# nmcli connection add type bridge autoconnect yes connection.interface-name br1 ifname br1
Connection 'bridge-br1' (b2a13bcc-a87b-423d-82a9-8656e55a2c44) successfully added.
[root@localhost ~]# nmcli connection
NAME UUID TYPE DEVICE
ens160 ea093dc0-034a-3862-bd3a-7a5480b1ef41 ethernet ens160
bridge-br1 b2a13bcc-a87b-423d-82a9-8656e55a2c44 bridge br1
lo 3d7df94a-bb99-4b8e-89b7-fdb505a34b74 loopback lo
virbr0 70765bf6-111d-42df-a7f5-766206fa39ea bridge virbr0
vnet0 dea19418-8bff-4745-927e-e78b001bf113 tun vnet0
[root@localhost ~]# nmcli device
DEVICE TYPE STATE CONNECTION
ens160 ethernet connected ens160
br1 bridge connecting (getting IP configuration) bridge-br1
lo loopback connected (externally) lo
virbr0 bridge connected (externally) virbr0
vnet0 tun connected (externally) vnet0
ens224 ethernet disconnected --为网桥添加静态地址
[root@localhost ~]# nmcli connection modify bridge-br1 ipv4.addresses 192.168.100.3/24 ipv4.method manua为网桥附加物理网卡
[root@localhost ~]# nmcli connection add type bridge-slave autoconnect yes connection.interface-name ens224 master br1
Connection 'bridge-slave-ens224' (3a49ec87-8783-4141-89ac-c6ed2b612273) successfully added.启动网桥
[root@localhost ~]# nmcli connection up bridge-br1
Connection successfully activated (master waiting for slaves) (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/7)查看网络
[root@localhost ~]# ip a
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br1 state UP group default qlen 1000
link/ether 00:0c:29:7a:a0:fb brd ff:ff:ff:ff:ff:ff
altname enp19s0
6: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:7a:a0:fb brd ff:ff:ff:ff:ff:ff
inet 192.168.100.3/24 brd 192.168.100.255 scope global noprefixroute br1
valid_lft forever preferred_lft forever
inet6 fe80::d1ff:db91:bea2:3b79/64 scope link noprefixroute
valid_lft forever preferred_lft forever接下来的操作通过virsh命令来完成
[root@localhost ~]# cat br1.xml
<network>
<name>bridged-network</name>
<forward mode="bridge" />
<bridge name="br1" />
</network>
[root@localhost ~]# virsh net-create --file br1.xml
Network bridged-network created from br1.xml这里由于我是测试环境,采用create来创建。如果是实际使用环境推荐采用define来创建网络。
创建虚拟机测试


实现多VLAN支持
macvlan
ipvlan l2 和 l3