
CentOS7上做虚拟化网络规划往往是最容易被低估的一环。很多人觉得只要把物理网卡桥接出来虚拟机就能上网等到需要多业务隔离、链路冗余的时候才发现直接桥接的方式既浪费端口又扛不住单点故障。这篇内容就是围绕CentOS7虚拟化环境里的两个基础动作——绑定网卡和划分不同VLAN——展开的实操记录主要面向KVM/libvirt这类平台也适合准备把现有网络改造成聚合链路加VLAN隔离的读者。我之前在改造某内部虚拟化项目时四台宿主机、每台双万兆口物理交换机只给了一个trunk口业务却要拆成三套互相隔离的环境。当时落地的方案就是两个物理口先做成bondbond上面划出若干VLAN子接口每个子接口再桥接给对应的虚拟机。整个链路从物理口到虚拟网卡共四层任何一层配置错位现象都会非常诡异。下面把这套方案的原理、配置、验证和排错完整拆开讲内容都能直接照着操作。1. 虚拟化主机的网络底座bond与VLAN各自解决什么问题1.1 一块网卡不够用时的选择从直接桥接到先做绑定物理服务器的网卡数量是有限的尤其刀片机或高密度服务器常常只有两个万兆口。一开始很多人图省事把物理网卡直接桥接给虚拟机用也就是br0桥接eth0虚拟机网卡挂到br0上。这种做法的优点是配置简单但代价也很清楚一旦这块物理网卡、网线、或者交换机端口出问题依赖这个桥的虚拟机全部失联带宽方面也只有一个物理口的硬上限多块网卡之间不会自动分担流量。绑定网卡bonding就是在这个场景下出现的。它的核心价值是两个词一个是冗余一个是带宽池。把两块甚至四块物理网卡聚合成一个逻辑口外部看到的只有一个IP、一个MAC但内部流量可以按策略在主备或负载均衡模式下调度。虚拟机层面完全感知不到底层是几张网卡它只知道自己的虚拟网卡连在某个桥接设备上数据报文到达bond口之后由内核的bonding驱动决定从哪个真实物理口出去。举个例子两块千兆网卡做mode 4的bond理论上可用带宽接近两倍而且一块口断开时另一块继续兜底切换时间通常在秒级以内。对于虚拟化宿主机来说这个特性简直是为“一晚上不能断”这种需求量身定做的。前端业务、后端存储、管理通道混在同一台机器上任何一次非计划断网都会牵连一排虚拟机所以效率再高也不如先把“不会因为一块网卡掉线就全盘崩掉”这件事做扎实。1.2 为什么要在宿主机上划VLAN而不是全交给交换机VLAN这东西原本是交换机上的概念一个物理交换机端口可以属于某个VLAN也可以做成trunk口让多个VLAN的tagged帧通过。到了虚拟化场景问题变得有点拧虚拟机是软件设备它的“网口”并不直接插在物理交换机上而是插在宿主机内部的虚拟交换机或者Linux Bridge上。如果你希望不同业务的虚拟机分属不同VLAN有两种路线。第一种路线是完全依赖物理交换机。宿主机上插两块物理网线交换机的两个access口分别属于VLAN 10和VLAN 20宿主机的每个物理口各自桥接到一组虚拟机。这样物理上是隔离的但问题也很明显冗余没了bond没了一个物理口挂了那组虚拟机就断网。而且每新增一个VLAN就要多占一个物理端口机柜后面乱成一团。第二种路线就是这篇要展开的宿主机用一根trunk链路上连交换机物理口先做bond保证冗余和带宽然后在bond上创建VLAN子接口比如bond0.10、bond0.20每个VLAN子接口再桥接给对应的虚拟机。从交换机的视角看它只要把这个下行口配置成trunk允许VLAN 10、20、30通过剩下的VLAN划分动作全部在宿主机内部完成。物理链路上是带802.1Q tag的帧到了bond0.10这一层内核的VLAN模块把tag剥掉桥接到br10上的虚拟机拿到的就是干净的VLAN 10二Layer帧。这个方案的收益很明显物理端口少、冗余架构统一、VLAN的增删全部在宿主机上改配置不用反复去交换机上插拔网线。风险点也一样明显所有VLAN共享一根物理链路trunk口打满时全业务互相影响所以实际项目中要结合带宽需求评估别把几十个VLAN压在一根万兆口上还觉得万无一失。2. 绑定模式怎么选虚拟化场景中的模式权衡与交换机配合2.1 七种bond模式与虚拟机的流量特征bonding驱动提供了多种模式CentOS7上常见的有mode 0、1、2、4。很多新手第一次接触会纠结“到底用哪个”其实脱离业务谈模式是选不出来的。虚拟化宿主机的流量特征比较特殊既有虚拟机之间的东西向流量也有虚拟机访问外部的南北向流量还有管理流量和存储备份流量混杂在一起。这种多源流量叠加的局面决定了我们不希望绑定算法太“憨”也不能太激进。模式名称是否需交换机配合特点与虚拟化适用性mode 0balance-rr需静态聚合或对端配合轮流发包可能乱序重传较多不推荐生产虚拟化环境mode 1active-backup无需配合一主一备逻辑简单不提升带宽但冗余可靠保守首选mode 2balance-xor需对端聚合按MAC或IP hash分发稳定性较好但对端要支持mode 4802.3ad LACP需交换机开LACP动态协商带宽叠加虚拟化场景最推荐的常规解mode 5/6balance-tlb/alb无需配合但依赖驱动本地负载均衡双向均衡但兼容性参差生产环境见得少为什么虚拟化环境不推荐mode 0原因很直接round-robin是让报文轮流从不同物理口发出接收方看到的乱序概率会显著上升TCP对乱序很敏感一旦触发快速重传实际吞吐不升反降。别被“轮流发包”这种表面均衡骗了真实高吞吐场景下它很容易翻车。对大多数内部虚拟化项目如果交换机可控直接上mode 4最省心如果交换机老旧或者网管团队不给开LACP那就用mode 1老老实实做冗余。带宽需求真的很高时再考虑升级物理口速率而不是靠阻塞在mode 0里赌运气。2.2 mode 4的LACP协商细节不是配完就完事mode 4需要和交换机跑LACP双方协商成功后才开始转发数据。这个协商里面有大量“看起来通了实际上没通”的坑。先看关键参数。miimon100表示每100毫秒检测一次链路状态默认值比较稳妥lacp_rate1对应fast LACP即每秒发送一次LACPDU让协商收敛更快xmit_hash_policylayer34表示按IP和端口做hash这样多路流量能更均匀地打散到不同物理口上。很多人在mode 4里只写了mode4 miimon100不写hash策略默认的layer2策略在某些多虚拟机场景下会把大量流量单压到一条链路上带宽池效果出不来。LACP协商失败的首个症状是bond口始终处于down。常见原因有物理交换机的端口没有配成LACP模式或者交换机配置的是静态聚合而不是动态聚合还有一种情况是两块物理网卡的驱动版本不同导致发送的LACPDU格式或速率有细微差异个别交换机对LACP报文很挑食。实际操作里我习惯配置完先别急着开机自启手动执行ip link set bond0 up观察几秒然后去交换机上查看聚合口状态确认两个成员口都是Selected状态。如果一直是Standby几乎可以断定是协商参数不一致优先检查交换机端口的LACP mode和速率。3. 动手配置bond与VLANifcfg脚本逐行拆解3.1 清零前置状态网卡识别、NetworkManager、模块加载开始配置前先把环境状态摸清楚。第一步用ip link确认物理网卡名CentOS7里常见的有eno1、enp3s0f0、em1这类命名。如果服务器上有板载网卡和PCIe网卡混用名字会很乱一定要先明确哪块网卡对应哪个物理口不要凭感觉写进配置文件否则做完bond发现错把两块口绑在一起排错会非常痛苦。第二步处理NetworkManager。CentOS7默认启用NetworkManager它和network脚本服务同时存在时很容易出现“配置写了重启被NM接管”的情况。如果你决定用ifcfg这套传统网络配置建议直接禁用NetworkManager或者至少在网卡配置里加上NM_CONTROLLEDno。如果业务上非要保留NM那就用nmcli来管理bond别两边混着写混写的结果往往是重启后bond口没起来从属网卡却被NM拉成了独立网卡。第三步确认bonding模块是否加载。执行modprobe bonding后lsmod | grep bonding能看到模块信息。想开机自动加载就写一行到/etc/modules-load.d/bonding.conf里内容就是bonding。这一步很容易被漏掉尤其是一些精简安装的系统模块加载时机不一致可能会在network服务启动时找不到bonding驱动导致后续配置全都不生效。3.2 bond口的ifcfg写法与从属网卡约束下面是一份可以直接照抄的bond配置。假设服务器有两块物理网卡eno1和enp3s0f0要绑成bond0模式取mode 4先创建/etc/sysconfig/network-scripts/ifcfg-bond0DEVICEbond0 NAMEbond0 TYPEBond BONDING_MASTERyes BOOTPROTOnone ONBOOTyes MTU9000 BONDING_OPTSmode4 miimon100 lacp_rate1 xmit_hash_policylayer34接着改从属网卡的配置。用ifcfg-eno1举例DEVICEeno1 NAMEeno1 TYPEEthernet BOOTPROTOnone ONBOOTyes MASTERbond0 SLAVEyes NM_CONTROLLEDnoenp3s0f0的配置同理只是DEVICE和NAME换成它自己的名字。这里有一个新手常犯的错有人会在从属网卡上顺手配一个IP哪怕只是作为备用地址也会扰乱路由。从属网卡的所有IP都应该收敛到bond口或bond的VLAN子接口上从属口就是纯粹的“搬运工”越干净越好。至于MTU9000要结合交换机实际是否支持jumbo frame来决定。如果交换机不支持或者虚拟机对端MTU保持1500就不要全局改9000否则大包直接丢MTU不一致引发的“能ping通但下载卡住”是最难排查的坑之一。稳妥的做法是先保持1500跑通所有功能确认业务需要再统一调整。配置写完后重启网络服务或者执行systemctl restart network。然后用cat /proc/net/bonding/bond0查看聚合状态重点看MII Status是否为upActive Slave是否正常。3.3 VLAN子接口与Bridge的联动bond口起来之后开始划分VLAN。这里的思路是每个VLAN对应一个bond0.X子接口再对应一个Linux Bridge最终把虚拟机网卡挂到Bridge上。链路结构是物理网卡 → bond0 → bond0.10 → br10 → vnet0虚拟机创建/etc/sysconfig/network-scripts/ifcfg-bond0.10DEVICEbond0.10 VLANyes VLAN_ID10 PHYSDEVbond0 BOOTPROTOnone ONBOOTyes BRIDGEbr10如果这个VLAN子接口在宿主机上只需要做管理地址不需要接虚拟机可以把BRIDGEbr10去掉在BOOTPROTOstatic的情况下配上IPADDR、NETMASK。但如果是业务虚拟机的接入VLAN就必须配合Bridge。对应的桥配置文件是/etc/sysconfig/network-scripts/ifcfg-br10DEVICEbr10 TYPEBridge BOOTPROTOnone ONBOOTyes STPno为什么桥要单独占一个ifcfg文件因为Bridge本身是一个二层交换设备它的状态需要独立管理。STP默认写作no这是CentOS7的默认行为通常在单宿主机单桥且没有物理冗余链路时是安全的如果存在一条物理链路经过交换机还跑到另一台桥接设备上形成二层环路就必须开启STP否则广播风暴会教做人。重复这套模式可以配出bond0.20对应br20bond0.30对应br30。值得注意的是每个VLAN子接口的MAC地址默认继承bond0的MAC这对业务侧是透明且有利的。编号上不要用bond0.1VLAN 1往往是交换机的native vlan默认不打tag和预期行为经常不一致建议业务VLAN从10或100开始规划。4. 让虚拟机按VLAN入网libvirt桥接与trunk思想的落地4.1 虚拟机XML里bridge网络怎么填宿主机上的br10建好之后KVM虚拟机接入就变得非常自然。创建虚拟机时在XML里定义网络接口设备interface typebridge source bridgebr10/ model typevirtio/ /interface如果虚拟机已经存在想热添加一块网卡可以用virsh attach-interface 虚拟机名 bridge br10 --model virtio --live --config也可以编辑XML后virsh define重新加载。热添加的场景里我要特别提醒一句部分旧版本libvirt只支持附加到相同bridge的接口跨bridge操作最好在停机状态下改XML免得出现网卡已经出现在虚拟机里但始终看不见链路的情况。背后的转发逻辑是这样的虚拟机发出的原始以太网帧没有VLAN tag它进入br10后被桥交换逻辑转发到bond0.10这个上游口内核VLAN模块看到这个口对应VLAN 10就给帧打上802.1Q tag 10然后再从bond0的某个物理口发出去最后由物理交换机trunk口接收。反过来也一样trunk口收到带tag 10的帧从bond0进到内核VLAN模块剥掉tag帧出现在bond0.10上然后被br10转发给对应虚拟机。整个过程对虚拟机完全透明。如果不用libvirt纯qemu命令行方式也可以用-netdev bridge,brbr10,idnet0配合-device virtio-net-pci,netdevnet0原理一致只是少了libvirt的管理层和DHCP地址的自动关联能力。生产环境还是推荐libvirt毕竟虚拟机的生命周期管理不止是网络这一块。4.2 隔离与广播不同VLAN/不同Bridge之间的边界有人问虚拟机A挂在br10虚拟机B挂在br20它们之间到底隔不隔离答案是隔离的。因为Linux Bridge是独立的二层设备br10与br20之间没有任何转发关系广播、组播、ARP请求都不会跨桥传播。这比传统物理交换机还要安全毕竟物理交换机上如果配置失误还能串VLAN两个独立Bridge之间连配置失误的机会都没有。但这不代表万事大吉。如果两个VLAN之间需要通信就必须走三层路由。常见做法是用宿主机作为路由器在bond0.10和bond0.20上分别配置IP然后开启内核IP转发或者在上游交换机上做VLAN间路由。你在规划时倾向哪种都行但千万别为了省事把两个Bridge用veth对连起来那样等于在二层把两个VLAN硬打通隔离性瞬间归零。还有一种场景如果你希望虚拟机自己处理VLAN tag比如要在虚拟机里再划分多个子VLAN那就不适合用Linux Bridge接bond0.X而应该考虑把trunk口直接交给虚拟机。这种模式在KVM里可以用macvtap的VEPA模式或者Open vSwitch配合仿真办法但配置复杂度会上升一个台阶。我的建议是除非有明确的虚拟化内部再划VLAN的需求否则优先在宿主机层面拆分子接口这样对虚拟机的网络配置最友好也最容易理解和排错。5. 验证链路与VLAN是否真的按预期工作5.1 从宿主机侧看bond与VLAN状态配置完成之后验证这步千万别省。先看bond状态cat /proc/net/bonding/bond0重点看MII Status和Link Failure Count。如果两块从属网卡都是up而且Bonding Mode是802.3ad说明LACP协商成功。再看VLAN子接口ip -d link show bond0.10输出里能看到vlan protocol 802.1Q id 10说明VLAN子接口已经创建。此时在宿主机上ping一下网关确认三层通了。但这里有个容易误判的点宿主机能ping通只能说明bond0.10和交换机端的配置没问题不代表虚拟机也能通。因为虚拟机到br10这段还有一层桥接需要单独验证。查看桥接状态bridge link show这条命令会列出所有Bridge以及挂在上面的接口包括bond0.10和各个虚拟机的vnetN。如果发现某个Bridge下只有bond0.10而没有虚拟机接口那说明虚拟机网卡没有正确挂载问题大概率在libvirt的XML配置。5.2 从虚拟机侧观察访问与隔离进入虚拟机先确认网卡状态然后用同VLAN的另一台虚拟机做ping测试。如果ping不通回到宿主机上用tcpdump定位tcpdump -i br10 -e -n icmp在br10上抓包应该能看到ICMP请求和应答而且帧头没有VLAN tag。这符合预期因为br10内侧已剥离tag。如果你想确认出去的帧确实带了VLAN 10的tag就去物理口上抓tcpdump -i eno1 -e -n ether proto 0x8100这里能直接看到802.1Q header里的vlan id。如果物理口上是EtherType 0x0800的普通IP帧而没有0x8100说明tag没有打上链路里某个环节的VLAN配置失效了。隔离性测试也建议做一下从VLAN 10的虚拟机ping VLAN 20的虚拟机预期是超时收到应答反而是出了严重问题。很多师傅测到这里就满足了但我还会多测一步广播用arping从一个VLAN发起对另一个VLAN的探测确认二层广播完全被隔断。这一步在安全要求高的环境里格外重要防止出现VLAN间串扰这类隐蔽问题。6. 踩坑实录bond起不来、VLAN不通、桥接丢包的排查线索6.1 bond口没接管物理网卡配置像被“吞”了这是我在虚拟化环境里见过最多的问题。现象是配置文件全写了systemctl restart network也执行了但ip link show里物理网卡还是独立的根本没有slave状态。怀疑的第一对象往往是NetworkManager它会在network服务之前或者之后抢占网卡控制权导致ifcfg脚本里写的MASTERbond0被忽略。解决方式前面说过要么停掉NetworkManager要么给网卡配置加NM_CONTROLLEDno。另一个容易被忽略的原因是网卡配置文件的NAME字段和DEVICE字段不一致某些情况下扫描脚本处理异常。建议每个配置文件里DEVICE和NAME保持完全一致不要凭兴趣填别名。还有个别服务器板载网卡有biosdevname或net.ifnames命名规则干扰如果物理网卡名里带有奇怪的.或:字符可以先统一改名为eth0、eth1这种简单样式再继续。6.2 VLAN tag在桥中消失为什么抓包看不到VLAN标签遇到虚拟机流量不通在br0上抓包能看到帧能到桥但物理口侧抓不到VLAN标签这种情况多半是链路没有按照预期经过VLAN子接口。我排查时先看桥的成员端口命令是bridge link show如果发现某个桥的上游口直接是bond0而不是bond0.10那么VLAN子接口根本没有参与转发自然不会有tag。还有人会把虚拟机的vnet口和物理口同时加入同一个Bridge中间没有子接口形成“全二层直通”。这时候VLAN的划分在整个链路里实际不存在流量会以untagged形式穿过交换机端如果trunk口设置了native vlan帧还可能会被归到默认VLAN里表现就是虚拟机莫名其妙能通一部分网络另一部分完全不通非常玄学。6.3 其他常见问题快查表症状可能原因排查命令或检查点bond口一直downLACP协商失败、从属网卡MAC地址冲突、模块未加载cat /proc/net/bonding/bond0、交换机聚合口状态虚拟机不通但宿主机通虚拟机网卡未正确挂到Bridgebridge link show、libvirt XMLVLAN ping通过但大包不通MTU不一致对比物理口、bond、虚机接口MTU重启后bond配置丢失NetworkManager接管检查网卡是否存在NM连接文件禁用NM两个VLAN互相能通Bridge配置串连、veth搭线查看Bridge成员断开多余连线广播风暴Bridge环路且未开STPbridge link show确认路径唯一必要时开STP最后再补一个我自己的习惯。改任何网络配置都要先把改动拆成最小单元每两步验证一次别一口气把bond、VLAN、Bridge全写完再重启否则任何一环出错排查半径会大到你怀疑人生。尤其在生产环境里我都是先当场用命令把bond拉起来验证再回写配置文件持久化。网络这块最怕的就是“看起来通了其实没通”而bond加VLAN的组合恰恰是把这种忽悠人的假象放大到极致的一种配置。希望这份记录能帮你少踩几个坑至少让这两个词不再成为半夜事故的主角。