我们来看一下如何使用NetworkManager创建桥接网卡,并让KVM虚拟机桥接联网。

1 查看网络设备

$ nmcli device 

DEVICE TYPE STATE CONNECTION
eno1 ethernet 已连接 Wired Connection 1
lo loopback 连接(外部) lo
virbr0 bridge 连接(外部) virbr0

如上,物理网卡的设备名称为: eno1

$ nmcli connection 

NAME UUID TYPE DEVICE
Wired Connection 1 2c9e92d1-d13c-31cc-b50c-240973b91581 ethernet eno1
lo 7e82f974-30d8-4ad6-ad8f-f2d981c39da3 loopback lo
virbr0 f2d511c5-e36d-4326-98e5-aa7a0cd2c963 bridge virbr0

如上,网卡对应的连接名称为:Wired Connection 1

2 创建网桥

$ nmcli connection add type bridge con-name br0 ifname br0

将物理网卡关联到网桥上

$ nmcli connection add type bridge-slave ifname eno1 master br0

现在我们切换连接,先停止物理网卡原来的连接,然后启用桥接

$ nmcli connection down "Wired Connection 1"
$ nmcli connection up br0

稍等一会儿,等DHCP获取IP,然后我们查询一下ip情况:

$ ip addr

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
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
altname enp0s31f6
altname enx00d8618b2ae9
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc htb state DOWN group default qlen 1000
link/ether 52:00:00:00:00:00 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: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 32:ca:00:00:00:00 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.62/24 brd 10.0.0.255 scope global dynamic noprefixroute br0
valid_lft 7190sec preferred_lft 7190sec

如上,桥接设备可以正常获取到IP了。

我们让电脑每次开机使用桥接方式连网,避免每次都去修改连连接方式:

$ nmcli con mod "Wired Connection 1" connection.autoconnect no
$ nmcli con mod br0 connection.autoconnect on

网卡的设置到此完毕。

3 设置虚拟机

如果使用virt-manager,可按如下方式设置网络设备即可:
kvm-bridge-network-kvm-config-1


也可以通过配置文件的方式设置,在devices节点下添加如下interface:

<interface type="bridge">
  <mac address="52:54:00:12:34:56"/>
  <source bridge="br0"/>
  <model type="virtio"/>
  <address type="pci" domain="0x0000" bus="0x02" slot="0x01" function="0x0"/>
</interface>

另外,还需要将桥接设备br0添加到kvm的白名单中,避免虚拟机开机报错:

$ echo 'allow br0' | sudo tee -a /etc/qemu/bridge.conf

这就可以了。

4 可选配置

0x1 关闭桥接设备的包过滤,提升桥接网卡的性能

关闭桥接网卡的包过滤:

$ sudo mkdir -p /etc/sysctl.d

$ sudo bash -c 'cat << EOF > /etc/sysctl.d/99-netfilter-bridge.conf
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
EOF'

立即加载br_netfilter模块:

$ sudo modprobe br_netfilter

开机自动加载此模块:

$ echo 'br_netfilter' | sudo tee /etc/modules-load.d/br_netfilter.conf

使配置立即生效

$ sudo sysctl -p /etc/sysctl.d/99-netfilter-bridge.conf

0x2 给 virt-manager 创建一个网卡选项

新建一个配置文件:

$ cat << EOF > ~/bridged-network.xml
<network>
   <name>bridged-network</name>
   <forward mode="bridge" />
   <bridge name="br0" />
</network>
EOF

使用配置文件定义选项:

$ sudo virsh net-define ~/bridged-network.xml

使选项立即生效,并且每次开机自动生效:

$ sudo virsh net-start bridged-network
$ sudo virsh net-autostart bridged-network

之后我们在virt-manager 上就可以直接选择这个配置了,不必每次都输入设备名称:
kvm-bridge-network-kvm-config-2

5 你可能想知道的

0x1 什么是桥接?

桥接需要两个东西:

  1. 网桥,网桥就是一个交换机,当然,这是一个虚拟的交换机。
  2. 网口,网口可以是物理的或者虚拟的,在Linux上我们称之为网络设备。

所谓桥接,就是将物理网口和虚拟网口连接到虚拟交换机上。

所以虚拟机若要通过桥接的方式连网, 就需要将虚拟机的网口连接到虚拟交换机上,再将宿主机的物理网口也链接到虚拟交换机上。(想一想你家交换机或者路由器,有画面了吗? 就是这样。)

VM network port -> [Virtual Hub] <- Host network port

0x2 设置桥接后,windows虚拟机开机无法识别网卡

windows没有安装qemu guest tool的时候,无法识别virtio和e1000e网卡,有两个办法可以解决:

0x1. 将设备改为rtl8139

<interface type="bridge">
  <mac address="52:54:00:00:00:00"/>
  <source bridge="br0"/>
  <model type="rtl8139"/>
  <address type="pci" domain="0x0000" bus="0x02" slot="0x01" function="0x0"/>
</interface>

0x2. 安装qemu guest tool
https://pve.proxmox.com/wiki/Qemu-guest-agent
https://www.spice-space.org/download.html



参考资料:

  1. Add a bridge interface to Ubuntu desktop using nmcli
  2. Setting up a bridged network for KVM guests