CentOS装双网卡,十个运维有九个都踩过“流量不走对的网卡”这个坑。明明内网口接了交换机,外网口接了宽带,系统重启之后,外网流量偏偏跑去挤内网口,导致业务通不了。这事儿说大不大,说小能把人逼疯。我做了多年运维,给内部团队排障时,这类“双网卡优先级混乱”的问题占了网络类故障的三成以上。后台看路由表,两条默认路由都在,Metric值还一模一样,谁能想到Linux选路这么“耿直”。
这篇东西就是给正在被双网卡折磨的朋友看的。不管是新装的服务器,还是接手别人配过的老机器,只要你想让多块网卡按你的意图走流量,都得搞清楚路由优先级这套底层逻辑。我会把原理拆开揉碎,再贴出完整可用的配置步骤,最后聊聊我踩过的坑。不想让内网外网互相打架,往下看就对了。
1. 双网卡“分身乏术”的根源:路由表决定流量方向
1.1 网卡多没用,关键看系统怎么选路
很多人有个直觉:服务器上有两块网卡,一块配了内网IP,一块配了外网IP,系统自然会各走各的,互不干扰。这个想法只对了一半。网卡只是物理出口,真正决定数据包从哪里出去的是内核里的路由表,也就是常说的 FIB(Forwarding Information Base)。
我用个生活里的例子解释一下。你家住的小区有两个门,一个南门通向城市主干道,一个北门通向单位方向。你出门之前会先想走哪个门更顺路。操作系统也一样,发一个数据包前,先看路由表,找一条最匹配的路径。问题在于,当系统意识到目标地址不在任何一个已知网段时,它就走默认路由。默认路由通常由网关配置生成,如果两块网卡都配了网关,就等于小区里立了两块写着“出门右转”的指示牌,而且指向相反的方向。
这时候优先级就上场了。规则很简单:Metric 值小的胜出。就像两个导航软件同时报不同路线,系统更信任那个“距离更短”的方案。实际工作中,绝大多数双网卡选路乱走,根子都在默认路由和 Metric 值配置上,而不是网卡本身有问题。
1.2 网卡命名变来变去,坑了多少人
聊优先级之前,还得先把一个更容易踩的坑摆出来:网卡名字。老运维习惯了eth0、eth1那套命名,CentOS 7 开始换成了ens33、ens160、eno1这种基于 BIOS 位置或总线信息的名字。你看着像乱码,其实里面藏着“物理位置顺序”的编码。
这跟优先级有什么关系?关系大了。很多一键安装的脚本或者手敲的配置,会把“第一块网卡”当成“内网网卡”,写死在/etc/sysconfig/network-scripts/ifcfg-eth0里。结果换了新机器,原来的eth0现在叫eno16777736或者ens256,配置文件里的DEVICE=eth0根本找不到对应设备,等于没配。
更麻烦的是,如果你有两块网卡,系统按什么顺序分配名字,取决于 PCI 总线枚举顺序,而这个顺序有时候会跟物理插槽对不上号。你明明把内网线插在 1 号口,系统却把这个口识别成第二块网卡。所以做任何优先级配置前,第一步永远是先确认哪块网卡对应哪个接口,用ip link一眼看清 MAC 地址,再跟交换机端口上的标签对一对,避免对着空气配置。
2. Metric 优先级机制:选路规则的底层逻辑
2.1 路由表里到底存了什么
Linux 的内核路由表可以简单理解成一张 Excel 表格,每一行是一条路由记录。用ip route show命令能看到类似这样的输出:
default via 192.168.1.1 dev ens33 proto static metric 100 default via 10.0.0.1 dev ens160 proto static metric 200 192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.100 metric 100 10.0.0.0/24 dev ens160 proto kernel scope link src 10.0.0.100 metric 200每一行里,via是下一跳地址,dev是出口网卡,metric是这条路由的权重。数字越小,优先级越高。当系统要访问一个公网 IP 时,前两条默认路由都能用,它就会选metric 100那条,也就是从ens33出去。
这里有个细节容易被忽略:proto kernel那几条是系统配置 IP 时自动生成的直连路由,Metric 默认按网卡上配置的值来。而proto static那条默认路由,到底带多少 Metric,取决于配置来源。
2.2 为什么两块网卡会造成“抢流量”
如果你给两块网卡都配了网关,系统就会看到两个默认路由,它们会形成一个竞争关系。没有显式指定 Metric 时,CentOS 系统会根据网卡自身的某些属性自动分配一个值,但这个值的大小并不符合你的预期,导致内网流量跑到外网口去兜圈子,外网请求又从内网口出去,直接断网。
用通俗的话讲,这就是“两头都想管,结果两头都管不好”。不少刚入门的工程师会试图用route del default删掉一条默认路由来“解决”,这个操作有两个问题。第一,重启后配置丢失;第二,如果内网网卡的网关被删了,内网跨网段访问反而会失败,因为内网不同 VLAN 之间的通信也需要网关帮忙转发。
真正标准的做法不是删除路由,而是给每块网卡设定明确的 Metric 值。让系统永远优先走你指定的那扇门,另一扇门作为备用。只要路径判断规则清晰,双网卡完全可以稳定共存。
2.3 两张网关卡谁当“老大”,先想清楚业务
动手配置之前,你得先想清楚哪块网卡是“主路”,哪块是“备路”。一般有两种常见场景。
第一种,内外网隔离。ens33走办公外网,用于访问公网;ens160走机房内网,给业务系统之间互通。这种场景下,默认路由应该指向外网口,内网口只保留直连路由,不要给它配默认网关,或者说把它的 Metric 值调到很大,让它永远只承担内网段通信。
第二种,双线路冗余。两块网卡都接到两个不同运营商或者两个不同交换机上,走的是负载均衡和故障切换的思路。这种情况默认路由可以有两条,但必须保证同等的 Metric,或者用主备模式让其中一块稍高一些。
配置文件里一句话就能控制:METRIC=100。在/etc/sysconfig/network-scripts/ifcfg-对应的网卡配置文件里加上这个参数,重启网络后,内核就会按照这个值排序路由。别小看这一行,它是整篇操作里最关键的一步。
3. 手把手配置:让流量按你的意图走
3.1 先给网卡“验明正身”
我这里直接用一台 CentOS 7.9 的虚拟机做演示,系统里有两块网卡,分别为ens33和ens160。运行ip addr show能看出两块网卡的 IP 分别是192.168.1.100和10.0.0.100。先确认路由状态:
# 查看当前所有路由 ip route show # 或者用传统命令 route -n如果输出里看到两条default路由,接着往下做。找不到默认网关的直连网段,可以手动给网卡配置网关。
3.2 临时优先级配置:一条命令立即生效
如果你只是临时测试,想验证把流量切到某个网卡的效果,不用改任何配置文件,直接用ip route命令动手就行。
# 假设当前默认路由走了 ens160,想切到 ens33 # 先加一条高优先级默认路由,metric 100 sudo ip route add default via 192.168.1.1 dev ens33 metric 100 # 再把原来那条默认路由的 metric 改成 200,作为备用 sudo ip route replace default via 10.0.0.1 dev ens160 metric 200 # 确认结果 ip route show这里有个小细节:ip route add如果发现已经存在同样条件的默认路由,会报RTNETLINK answers: File exists的错误。我习惯用ip route replace来覆盖旧记录,这样不用先删再加,少一步操作。
命令生效后,立刻用ping验证一下出口方向。ping -I ens33 8.8.8.8指定从ens33口发测试包,确认公网能通。再ping -I ens160 10.0.0.2验证内网口没问题。这种“指定出口”的 ping 方式是排查双网卡问题的神器,比普通 ping 更直观。
3.3 永久配置修改:重启也不丢
临时命令只能撑到下次重启,真正要落库的内容写在网卡配置文件里。进入/etc/sysconfig/network-scripts/,编辑两块网卡的 ifcfg 文件。
先看ifcfg-ens33,这是外网口:
TYPE=Ethernet BOOTPROTO=static NAME=ens33 DEVICE=ens33 ONBOOT=yes IPADDR=192.168.1.100 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 METRIC=100再看ifcfg-ens160,这是内网口:
TYPE=Ethernet BOOTPROTO=static NAME=ens160 DEVICE=ens160 ONBOOT=yes IPADDR=10.0.0.100 NETMASK=255.255.255.0 # 不配置 GATEWAY,或者配置一个很大的 METRIC METRIC=200关键点就在这:内网口不要写GATEWAY=,只保留METRIC=200。如果你给内网口也写了默认网关,系统就会生成两条默认路由,哪怕 Metric 分开了,某些情况下数据包也可能因为策略路由规则走得乱七八糟。
保存后重启网络服务:
sudo systemctl restart network重启完再执行ip route show,看看默认路由是不是只剩一条。正常情况下,走公网的那条应该排在最前面,Metric 100。内网口的路由表里只有直连的 10.0.0.0/24 网段和备用默认路由,优先级低,平时不参与选路,但链路出问题时会自动接管。
3.4 NetworkManager 参与时多留个心眼
CentOS 7 及以上的版本里,NetworkManager 是否在运行,直接决定了 ifcfg 文件改完管不管用。默认安装的 CentOS 7 虽然桌面版带 NetworkManager,但服务器版多数还是用 network 脚本。你可以在修改完配置文件后运行:
systemctl status NetworkManager systemctl status network如果 NetworkManager 是 enabled 状态,它有自己的连接管理逻辑,跟你手改的 ifcfg 文件之间偶尔会打架。我遇到过一次诡异情况:明明ifcfg-ens33里写了METRIC=100,重启后路由却变成了metric 0。查了半天,发现 NetworkManager 接管了网卡配置,自动生成了新的连接配置。
遇到这种情况要么直接禁用 NetworkManager,让 network 脚本完全接管:
systemctl stop NetworkManager systemctl disable NetworkManager systemctl restart network要么在 NetworkManager 的 nmcli 里显式设置 route-metric:
nmcli connection modify ens33 ipv4.route-metric 100 nmcli connection up ens33两种方案任选一种,尽量别混着用。老运维普遍偏爱关闭 NetworkManager 的朴素方式,统一由 network 命令控制,排查问题也少绕弯子。
4. 策略路由进阶:比 Metric 更细粒度的控制
4.1 同一个包里既要内网又要外网怎么办
Metric 只能解决“默认路由走哪”的问题,但很多真实业务场景比这个复杂。比如服务器要访问10.10.20.0/24的内网开发环境,同时又要上公网下载软件包。如果内网口和外网口都配了网关,光靠 Metric 很难让特定网段总走内网口。
这时候需要引入策略路由。通俗地说,Metric 是给所有流量定一个默认方向,而策略路由是给特定流量画一条“专属路线”。
CentOS 里策略路由主要通过两个文件实现:/etc/iproute2/rt_tables和/etc/sysconfig/network-scripts/rule-这一类规则文件。老手习惯直接在/etc/iproute2/rt_tables里加一行自定义路由表:
200 inernet然后在 rc.local 或专门的脚本里写入:
# 添加独立路由表内容 ip route add 10.10.20.0/24 via 10.0.0.1 dev ens160 table inernet # 从特定网段来的流量查找这张表 ip rule add from 192.168.1.100/32 table inernet这样凡是源地址为192.168.1.100的数据包,都会优先查找inernet路由表;找不到匹配项回退到主路由表。这种“按来源选路”的方式比纯 Metric 更精细,适合多网卡、多网段混布的环境。
4.2 什么时候该用策略路由,什么时候用 Metric 就够
这是我的经验判断:如果只是上下级网络环境的简单隔离,比如一台机器既要连办公网又要连测试网,Metric 足够。配置量小,排障也直观,一眼能看懂。
但服务器还要承担多个网段的互通,或者你有多块网卡都有流量进出需求,比如防火墙、负载均衡器这类设备,建议尽早规划策略路由。不同的业务网段走不同的出口,这也是生产环境最常见的姿势。
策略路由的配置要更小心,出错的影响范围也更大。我建议先在测试机上把规则完全调通再上生产。别在生产环境验证,这个锅我背过。
5. 实测排障:双网卡配置的那些坑
5.1 内网ping通,外网不通
症状:两块网卡都配了 IP,内网互访正常,公网请求超时。排查ip route show,发现默认路由走了内网口。原因十有八九是ifcfg-ens160里写了GATEWAY=10.0.0.1,系统拿着这个网关去公网,结果被设备挡了回来。
解决办法很简单,把内网口的网关删掉,或者像上文一样,给两块网卡设置不同 Metric。内网通信走直连路由也能通,不依赖默认网关。如果业务要求内网必须跨网关访问其他 VLAN,那么就单独为那个 VLAN 添加静态路由,而不是给整块网卡配默认网关。
ip route add 172.16.0.0/12 via 10.0.0.254 dev ens160这条命令只影响 172.16.0.0/12 网段的流量,不会干扰默认路由选择。
5.2 改了配置文件重启网卡,路由没变化
这类问题一般分三种情况。第一,network服务其实没有真正重启,systemctl restart network有时候因为配置错误只报个警告就退出,不会重读路由。用journalctl -xe看看 network 服务日志。
第二,NetworkManager 又偷偷接管了。上文已经给了禁用方法,关键是先确认 NetworkManager 状态。
第三,也是最容易忽略的,ifcfg 文件名跟网卡实际名称不匹配。你编辑了ifcfg-ens33,但系统里那块网卡实际叫ens33f0。这种情况network脚本启动时会报Device ens33 does not seem to be present。用ls /etc/sysconfig/network-scripts/核对文件名,再用nmcli dev或者dmesg | grep eth找到真实的设备名。
5.3 DNS 解析慢,感觉流量没走该走的网卡
双网卡配置完成后,网络通是通了,但访问外网偶尔卡顿。这时候别急着怀疑路由,先检查/etc/resolv.conf。这个文件在配置 DHCP 或 NetworkManager 时会被自动重写,可能把内网 DNS 地址和外网 DNS 地址混在一起。如果内网 DNS 对外网域名解析失败,解析过程就会卡到超时。
我的做法是把内网 DNS 只放在内网口对应的网卡配置里,外网口只保留公网 DNS。具体操作是在 ifcfg 文件里设置DNS1=223.5.5.5(外网),内网口则只放内网 DNS。CentOS 的 network 脚本会合并所有网卡的 DNS 配置写入 resolv.conf,顺序就是网卡启动顺序。多块网卡的 DNS 互相挤占导致查询超时,这个问题排查起来相当隐蔽,值得记在速查本上。
5.4 不知道哪块网卡对应哪个物理接口
实际机房环境里,服务器上一排网口,系统里的ens33、ens160到底对应哪一个?拿网线和手电筒去机房对照是办法,但太慢。
更好的办法是用ethtool命令让网卡灯闪烁:
ethtool -p ens33 10执行后ens33对应的物理网口灯会闪烁 10 秒,肉眼直接识别。这是我最常用的物理定位手段,比拔线测试高效得多。如果ethtool没安装,先yum install ethtool。
5.5 MAC 地址配置错误引发的启动失败
给新网卡配置时,直接复制了旧配置文件,结果忘了改HWADDR或MACADDR行,导致网卡服务启动报错。系统会提示配置里的 MAC 跟设备实际 MAC 不一致。
如果你配置的是静态网卡,HWADDR这一行可以删掉,或者改成对应网卡真实 MAC。一般安装系统后,ifcfg 文件里会自动生成正确的 MAC,除非你手动编辑时改乱了。我遇到过不少人直接把 uuid 和 mac 复制了一遍,结果系统启动后串到另一块网卡上,路由表也跟着错。每次编辑 ifcfg 文件,第一件事就是核对 DEVICE、NAME、MAC 三者一一对应。
6. 备份与回滚:改配置前先留一手
双网卡配置的改动看似简单,实际出错时可能直接导致 SSH 断开。你在远程改路由表的时候,一旦把默认路由指向了不通的网关,当前连接立马断掉,人还没在机房,那就真的只能喝西北风了。
我的习惯是动手之前先备份关键文件。最省事的方式:
cp -a /etc/sysconfig/network-scripts/ /root/network-scripts.bak.$(date +%F) cp -a /etc/iproute2/rt_tables /etc/iproute2/rt_tables.bak改完后测试通过,备份文件留两三天再删,以防后续调到别的服务时回溯。
如果远程改了路由瞬间断开,短时间内系统会重新拨号或启动脚本恢复?基本没戏。所以强烈建议涉及默认路由的操作,临时命令用ip route replace之前,先确保当前控制台还开着,或者有一个稳定的带外管理口,比如 iLO / iDRAC / IPMI,别让手里没有救命稻草。
我自己还习惯把每次变更记录到~/.bash_history之外的单独笔记里,不是为了给老板看,纯粹是因为半年后你根本记不得当时为什么把 Metric 设成 300。
7. 双网卡优先级速查表
给到一个快速参考,实际配置时对照着检查一遍,能少踩不少坑。
| 检查项 | 目标状态 | 常见错误 |
|---|---|---|
| 网卡识别 | MAC 与物理接口对应 | 复制配置文件导致 MAC 混乱 |
| 默认路由 | 只留一条优先的 default | 两块网卡都配 GATEWAY 导致两条默认路由 |
| Metric 值 | 主网卡小于备用网卡 | 没写 METRIC 导致系统默认值抢占 |
| NetworkManager | 与 network 脚本冲突 | 两者同时生效造成路由不复位 |
| DNS 配置 | 外网口只放外网 DNS | 内外网 DNS 混排堵塞解析 |
| 策略路由 | 按 needs 自定义 table | 简单场景误用复杂策略 |
表中每一条都是实际故障里常见的诱因,排查时从上往下过一遍,绝大多数双网卡的问题都能定位出来。
再提一件事,配置完成后,可以用ip route get 1.1.1.1直接查看系统为某个目标 IP 选出的路径。这个命令会告诉你数据包实际会走哪块网卡、哪个网关,是验证优先级配置是否生效的最快方式。
双网卡场景下的优先级控制,说到底是操纵系统对“默认出口”的认知。Metric 是基础,策略路由是进阶,NetworkManager 是个隐藏变量,三者叠加在一起才组成完整的选路逻辑。按文章里的步骤走一遍,先确认网卡身份,再设置 Metric,必要时上策略路由,配完记得用ip route get验证。这套流程我用了好多年,不管新机器还是老机器,都能稳稳控制住流量的走向。