如何解决通过网桥连接的虚拟机的网络问题(Ubuntu 18.04)

如何解决通过网桥连接的虚拟机的网络问题(Ubuntu 18.04)

在我的服务器(Ubuntu 18.04 LTS)上,我正在运行一个 KVM 虚拟机,该虚拟机已经运行了一年多,但最近 - 可能是因为某些更新 - 每次重新启动主机时,虚拟机都会失去与网络的连接。最近两次发生这种情况时,我设法恢复了连接,但这次我再也无法让它工作了。

我读了很多教程和其他网页,感觉好像什么都试过不止一次,但显然我一定错过了什么。同时涉及的变量太多了,其中许多变量可能相互影响。所以对于这个问题,我想找到最佳的故障排除策略,使我(和其他人)能够尽可能有效地缩小连接问题的根源。更具体地说,我正在谈论通过 Ubuntu 18.04 上的桥连接的 KVM 虚拟机上的连接问题。

我意识到这个问题已经变得非常长了,所以让我澄清一下你无需阅读此处内容即可回答该问题

在下面的标题下,我提到了在解决网络问题时需要解决的最重要的不确定领域,但无需在答案中详细讨论这些领域。把它们作为可能的起点。

如果您希望以特定机器的配置作为出发点,请向下滚动到我提供此类详细信息的底部(在“我的示例”标题下)。

网络计划

在 18.04 上对此进行故障排除时遇到的一个问题是,ubuntu 改为使用netplan,这使得许多当前可用的建议变得过时。

切换到netplan本身也会引起混乱,因为,据我所知,使用netplan意味着所有网络配置都在 中完成/etc/netplan/*.yaml,而不再在 中完成/etc/network/interfaces,但是当我注释掉 中的所有内容时/etc/network/interfaces,它似乎以某种方式被写回(可能是我自己通过 Gnome 桌面上的虚拟机管理器完成的)。

看来我不是唯一一个对此感到沮丧的netplan有人建议改回ifupdown但是为了限制这个问题的范围,让我们留在 netplan 内并尝试在不切换回来的情况下修复问题。

NetworkManager 与 systemd-networkd

另一个困难是,Ubuntu 18.04 Server 和 Ubuntu 18.04 Desktop 之间至少有一个相关差异:服务器用途systemd-networkd和桌面用途NetworkManager,这需要不同的故障排除路径。更糟糕的是:如果您最初安装了服务器版本,但后来添加了 gnome 桌面怎么办?(我不记得我做了什么,但很可能这就是我所做的,因为我/etc/netplan/01-netcfg.yamlrenderer: networkdNetworkManager 似乎也在默认运行。)

修复主机或者虚拟机?

我的第三个不确定的领域是我应该修复主机还是虚拟机上的东西(或者主机上的更改是否也需要客户端上的更改)。到目前为止,我还没有太关注虚拟机,因为它运行良好,我从未更新过它(除了自动 ubuntu 安全更新)。但上次我设法修复了连接问题,我通过复制它的硬盘并创建一个新的虚拟机(在我看来是相同的)来实现的。我想这证实了虚拟机上的配置没有问题(因为虚拟机硬件是在主机上配置的),但它仍然告诉我,我可能需要更多地关注虚拟机的硬件配置。

需要重新启动才能应用更改吗?

在尝试不同的修复方法时,我也常常不确定

用户界面 (UI) 冲突?

最后,我意识到通过哪个 UI 进行某些更改可能很重要,因为他们可能会将这些更改写入不同的地方。我目前有以下用于配置我的虚拟机的界面:

  • 命令行(最常用)
  • 虚拟机管理器 (GUI)
  • 炒锅/泡菜(网络界面)
  • 我也运行着带有 Cloudmin 的 Webmin,但我的虚拟机没有显示在那里,所以我目前没有使用它。

我的例子

因此,尽管我的想法是找到一种通用的故障排除策略,但我认为从一个具体的例子开始总是一个好主意。以下是有关我当前设置的一些详细信息(如果评论中有要求,我会添加更多详细信息):

这是我当前的/etc/netplan/01-netcfg.yaml(并且该目录中没有其他 yaml 文件):

network:
  version: 2
  renderer: NetworkManager
  ethernets:
    enp0s31f6:
      dhcp4: no
  bridges:
    br0:
      interfaces: [ enp0s31f6]
      dhcp4: yes
      dhcp6: yes

我使用 NetworkManager 的唯一原因是因为我一直在努力尝试但systemd-networkd没有成功,所以我想我应该给 NetworkManager 一个机会(但我的直觉是我应该坚持使用systemd-networkd)。因此,我设置managed=true了我的/etc/NetworkManager/NetworkManager.conf,现在看起来像这样:

[main]
plugins=ifupdown,keyfile

[ifupdown]
managed=true

[device]
wifi.scan-rand-mac-address=no

virsh net-list --all给了我这个:

 Name                 State      Autostart     Persistent
----------------------------------------------------------
 br0                  active     yes           yes
 bridged              inactive   yes           yes
 default              active     yes           yes

我尝试与我的虚拟机一起使用的桥是 br0。

在此处输入图片描述

这是 br0 的配置:

在此处输入图片描述

第二座桥是尝试重新开始,简单地创建一个新的桥并将虚拟机连接到该桥,但添加桥没有效果,可能是因为虚拟机管理器似乎将其写入/etc/network/interfaces而不是 yaml 文件/etc/netplan/

这是我的/etc/network/interfaces

##auto lo br0
##iface lo inet loopback

##auto br1
##iface br1 inet dhcp
##   bridge_ports enp0s31f6
##   bridge_stp on
##   bridge_fd 0.0
##iface br0 inet dhcp
##   bridge_ports enp0s31f6
auto br0
iface br0 inet dhcp
   bridge_ports enp0s31f6
   bridge_stp on
   bridge_fd 0.0
auto br-kvm
iface br-kvm inet dhcp
   bridge_ports enp0s31f6
   bridge_stp on
   bridge_fd 0.0

请注意我是如何注释掉所有内容的(以确保该文件不会以某种方式影响我的配置),只是将它添加回底部,如上所述。

ifconfig给出了一长串网桥(大多数都以类似 命名br-a5ffb2301edc),但我不知道它们来自哪里(我想我在无数个小时的测试中不知不觉地创建了它们)。我不会在这里粘贴它们,只粘贴br0实际的以太网接口:

br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.4  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::4e52:62ff:fe09:7e59  prefixlen 64  scopeid 0x20<link>
        ether 4c:52:62:09:7e:59  txqueuelen 1000  (Ethernet)
        RX packets 806319  bytes 84505505 (84.5 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 307846  bytes 845321927 (845.3 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp0s31f6: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 4c:52:62:09:7e:59  txqueuelen 1000  (Ethernet)
        RX packets 817196  bytes 101316866 (101.3 MB)
        RX errors 0  dropped 13  overruns 0  frame 0
        TX packets 821152  bytes 876709681 (876.7 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 16  memory 0xef000000-ef020000  

这是我在虚拟机上测试网络连接的方法:

$ping 8.8.8.8
connect: Network is unreachable

编辑:这是虚拟机的内容/etc/netplan/50-cloud-init.yaml

network:
    version: 2
#    renderer: networkd
    ethernets:
        ens3:
            addresses: []
            dhcp4: true
            dhcp6: false
            optional: true

我不记得为什么几个月前我注释掉了 redererer 行(我也不知道现在假定的默认渲染器是什么),但这个确切的配置已经起作用了。

我还可以提一下,我突然想到这cloud-init可能会把我(在主机上)的事情搞乱,所以我检查了/var/log/cloud-init-output.log一下它是否在做任何事情:

Cloud-init v. 19.4-33-gbb4131a2-0ubuntu1~18.04.1 running 'modules:config' at Fri, 21 Feb 2020 02:24:08 +0000. Up 50.91 seconds.
Cloud-init v. 19.4-33-gbb4131a2-0ubuntu1~18.04.1 running 'modules:final' at Fri, 21 Feb 2020 02:24:15 +0000. Up 56.59 seconds.
Cloud-init v. 19.4-33-gbb4131a2-0ubuntu1~18.04.1 finished at Fri, 21 Feb 2020 02:24:15 +0000. Datasource DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net][dsmode=net].  Up 56.76 seconds
Cloud-init v. 19.4-33-gbb4131a2-0ubuntu1~18.04.1 running 'init-local' at Fri, 21 Feb 2020 02:59:28 +0000. Up 10.48 seconds.
Cloud-init v. 19.4-33-gbb4131a2-0ubuntu1~18.04.1 running 'init' at Fri, 21 Feb 2020 03:04:29 +0000. Up 311.21 seconds.
ci-info: +++++++++++++++++++++++++++++++++++++++++Net device info+++++++++++++++++++++++++++++++++++++++++
ci-info: +-----------+-------+------------------------------+---------------+--------+-------------------+
ci-info: |   Device  |   Up  |           Address            |      Mask     | Scope  |     Hw-Address    |
ci-info: +-----------+-------+------------------------------+---------------+--------+-------------------+
ci-info: |   br-kvm  | False |              .               |       .       |   .    | f2:7a:46:82:f9:e0 |
ci-info: |    br0    |  True |         192.168.1.4          | 255.255.255.0 | global | 4c:52:62:09:7e:59 |
ci-info: |    br0    |  True | fe80::4e52:62ff:fe09:7e59/64 |       .       |  link  | 4c:52:62:09:7e:59 |
ci-info: | enp0s31f6 |  True |              .               |       .       |   .    | 4c:52:62:09:7e:59 |
ci-info: |     lo    |  True |          127.0.0.1           |   255.0.0.0   |  host  |         .         |
ci-info: |     lo    |  True |           ::1/128            |       .       |  host  |         .         |
ci-info: +-----------+-------+------------------------------+---------------+--------+-------------------+
ci-info: +++++++++++++++++++++++++++++Route IPv4 info+++++++++++++++++++++++++++++
ci-info: +-------+-------------+-------------+---------------+-----------+-------+
ci-info: | Route | Destination |   Gateway   |    Genmask    | Interface | Flags |
ci-info: +-------+-------------+-------------+---------------+-----------+-------+
ci-info: |   0   |   0.0.0.0   | 192.168.1.1 |    0.0.0.0    |    br0    |   UG  |
ci-info: |   1   | 169.254.0.0 |   0.0.0.0   |  255.255.0.0  |    br0    |   U   |
ci-info: |   2   | 192.168.1.0 |   0.0.0.0   | 255.255.255.0 |    br0    |   U   |
ci-info: +-------+-------------+-------------+---------------+-----------+-------+
ci-info: +++++++++++++++++++Route IPv6 info+++++++++++++++++++
ci-info: +-------+-------------+---------+-----------+-------+
ci-info: | Route | Destination | Gateway | Interface | Flags |
ci-info: +-------+-------------+---------+-----------+-------+
ci-info: |   1   |  fe80::/64  |    ::   |    br0    |   U   |
ci-info: |   3   |    local    |    ::   |    br0    |   U   |
ci-info: |   4   |   ff00::/8  |    ::   |    br0    |   U   |
ci-info: +-------+-------------+---------+-----------+-------+
Cloud-init v. 19.4-33-gbb4131a2-0ubuntu1~18.04.1 running 'modules:config' at Fri, 21 Feb 2020 03:04:33 +0000. Up 315.26 seconds.
Cloud-init v. 19.4-33-gbb4131a2-0ubuntu1~18.04.1 running 'modules:final' at Fri, 21 Feb 2020 03:04:39 +0000. Up 321.85 seconds.
Cloud-init v. 19.4-33-gbb4131a2-0ubuntu1~18.04.1 finished at Fri, 21 Feb 2020 03:04:40 +0000. Datasource DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net][dsmode=net].  Up 322.15 seconds

看到它处于活动状态,我用 禁用了它sudo touch /etc/cloud/cloud-init.disabled。但我的连接问题仍然没有解决。

编辑2:这是我检查过的其他内容(基于这个帖子) 是我的虚拟机的网络接口是否仍与我的网桥关联。为了获取接口的名称,我这样做了virsh domiflist LMS(LMS 是我的虚拟机的主机名),我得到了以下信息:

Interface  Type       Source     Model       MAC
-------------------------------------------------------
vnet0      bridge     br0        virtio      52:54:00:f0:0e:f8

它已经br0在源下说明了,但我不确定这到底意味着什么,所以我使用仔细检查brctl show br0,确认vnet0与以下内容相关br0

bridge name  bridge id            STP enabled     interfaces
br0          8000.4c5262097e59    yes             enp0s31f6
                                                  vnet0

我非常希望找到丢失的 vnet0,以便可以修复它,但不幸的是,这也不是问题。

答案1

正如您所说,这是一个漫长而艰难的问题,因此我要做的第一件事就是尝试简化您的配置。

您的帖子中没有提到 iptables,这可能是导致您遇到问题的原因。您可以使用 查看当前规则iptables -vnL; iptables -t nat -vnL。或者,您可以使用以下命令将内核设置为绕过网桥的 iptables:sysctl net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0 net.bridge.bridge-nf-call-arptables=0

就我个人而言,我讨厌 netplan 的额外抽象层,而且由于可以直接使用 networkd 进行桥接,因此我会摆脱 netplan.io 和 NetworkManager,并使用 networkd 完成所有操作。您的网络显然有一个 DHCP 服务器,因此您不需要使用 networkd 或 dnsmasq 中的 DNSServer 配置。networkd 的最佳 wiki 是https://wiki.archlinux.org/index.php/Systemd-networkd- 完整阅读它,因为其中有一些技巧,但是一旦你理解了它们,你可以将这些知识转移到其他主要发行版。

一旦掌握了窍门,排除网络故障也就不那么糟糕了:

journalctl -xe | grep networkd

或者进行完整调试:

mkdir /etc/systemd/system/systemd-networkd.service.d
echo -e "[Service]\nEnvironment=SYSTEMD_LOG_LEVEL=debug" >> /etc/systemd/system/systemd-networkd.service.d/override.conf

从那里,您可以进行故障排除,tcpdump -nni br0以确保您的虚拟机确实在发送和接收流量,如果 virtio 驱动程序运行不正常,则可能并非如此。e1000 驱动程序似乎在任何地方都运行良好。

相关内容