KVM虚拟机网卡绑定网桥修复指南
在日常维护宿主机网络(特别是 Ubuntu / Debian 环境下使用 NetworkManager 或 netplan)时,如果我们重启了网络服务(例如执行 systemctl restart NetworkManager 或 netplan apply),可能会导致系统中已有的网桥(如 bridge0)被重置或重建。
此时,由 libvirt(KVM)动态生成的虚拟机网卡(例如 vnetX 虚拟接口)会被宿主机网络管理器从网桥中踢出,导致虚拟机突然断网。
本文档详细记录了在不重启虚拟机的情况下,将掉线的虚拟机网卡重新绑定回 bridge0 网桥的具体排查与修复流程。
1. 确认掉线的虚拟机及其网卡接口名
首先,我们需要知道目标虚拟机当前分配到了哪个 vnet 接口。
通过 virsh 命令可以列出所有虚拟机:
virsh list --all
假设我们发现 DSM 和 fq 两台虚拟机处于运行状态。接着检查它们对应的网卡接口名:
# 查看 DSM 虚拟机的网卡接口
virsh domiflist DSM
# 预期输出中,第一列的 Interface 就是接口名(例如 vnet5)
# Interface Type Source Model MAC
# ------------------------------------------------------------
# vnet5 bridge bridge0 virtio 02:11:32:21:3a:5a
# 同样查看 fq 虚拟机的网卡接口
virsh domiflist fq
# 预期输出(例如 vnet9)
# Interface Type Source Model MAC
# ------------------------------------------------------------
# vnet9 bridge bridge0 virtio 52:54:00:02:db:63
2. 检查网桥当前的绑定状态
获取到虚拟机的接口名称(如 vnet5 和 vnet9)后,需要确认它们是否真的从网桥中掉线了。
可以使用以下命令查看 bridge0 当前绑定的所有接口:
bridge link show
如果输出中只包含了物理网卡(如 enp1s0f0),而没有 vnet5 和 vnet9,则说明它们确实已被移出网桥。
也可以通过 ip link show 查看特定网卡的归属(如果没显示 master bridge0,即未绑定):
ip link show vnet5
3. 手工将虚拟机网卡重新绑定到网桥
使用 ip link set 命令可以非常方便地将虚拟网卡重新挂载到目标网桥(bridge0)上。命令格式如下:
# 将 vnet5 挂载到 bridge0
ip link set dev vnet5 master bridge0
# 将 vnet9 挂载到 bridge0
ip link set dev vnet9 master bridge0
4. 验证绑定结果与网络恢复状态
执行完绑定命令后,再次查看网桥状态进行确认:
bridge link show
此时的输出应该包含我们刚刚添加的 vnet 接口,且状态会经历从 learning 到 forwarding 的转变(通常需要十几秒钟):
3: enp1s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master bridge0 state forwarding priority 32 cost 100
43: vnet5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master bridge0 state learning priority 32 cost 2
52: vnet9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master bridge0 state learning priority 32 cost 2
等待片刻后,状态会变成 forwarding,此时虚拟机的网络通信就完全恢复了。
📌 补充说明(关于配置持久化)
在 libvirt 的虚拟机配置文件(XML)中,网卡部分通常已经包含了对网桥的映射:
<interface type='bridge'>
<mac address='02:11:32:21:3a:5a'/>
<source bridge='bridge0'/>
...
</interface>
因此,这种网卡掉线的现象仅会在宿主机运行时强行重启宿主机网络服务时发生。在正常情况下(例如重启宿主机、或将虚拟机正常关机再开机),libvirt 都会在虚拟机启动时自动读取 XML 配置,并将新生成的 vnet 接口正确挂载到 bridge0 上,不需要每次都手动执行绑定操作。