一台服务器上插了两块网卡,一块连着办公网,一块连着业务专网。刚装好系统的时候一切正常,但重启了几次服务之后,业务方突然说“外网不通了”。我登上机器一看,ping网关、ping公网IP都能通,但业务就是访问不了。最后查出来,问题出在默认路由上——流量全从专网那张网卡出去了,办公网那张网卡虽然也有默认路由,但优先级不对,压根没被选中。
这种“多网卡导致路由优先级混乱”的故障,在运维、虚拟化、办公网部署里太常见了。解决办法也很固定:调整网卡的路由metric(路由度量值),让系统明确“走哪扇门出去”。metric这个概念,表面上只是个数字,但搞懂它背后怎么生效,比单纯敲几条命令重要得多。这篇文章就把我这些年调metric踩过的坑、验证过的方法一次性写清楚,覆盖Ubuntu、openEuler、Windows和VMware虚拟机这些常见环境。
1. 多网卡上流量为什么总走“错门”——metric到底解决什么问题
1.1 一个真实到大家都遇过的现场
先说个我在200人规模企业里实际处理过的场景。一台Ubuntu 22.04服务器,双网卡,eth0接办公网(网关192.168.1.1),eth1接业务专网(网关10.10.10.1)。服务器上跑着一个内部系统,办公网里的同事要访问它,但它又要访问专网里的数据库。
配置的时候,两个网卡都设了默认网关。结果系统一重启,内部系统就间歇性抽风:有时候办公网的人能访问,有时候不能。看路由表,发现ip route输出里两条default路由都在,但实际出去的流量全走了metric值更小的那条——也就是专网。办公网的人访问服务器,请求从eth0进来,但服务器回包时从eth1出去,连接根本建不起来。这就是典型的非对称路由。
原因很简单:Linux内核在选择默认路由时,不看网关通不通,只看路由的优先级(metric值)。谁的metric小,默认路由就归谁。系统不会聪明到“自动检测哪条网关是通的”,它严格遵守路由表的“最优匹配”规则。
1.2 metric的“越小越优先”到底怎么理解
metric的全称叫路由度量值,不同系统里叫法不一样,Linux的route命令显示为Metric,Windows里叫“接口跃点数”(Interface Metric),路由协议里也称“开销”(Cost)。但核心规则高度统一:数值越小,优先级越高。
可以把它想象成一个十字路口的指示牌优先级:两个指示牌都写着“前方所有目的地”,但系统只会看牌子左上角的数字,数字小的那个牌子被优先采纳。这不是说大数字的牌子就完全没用,只有当小数字那条路由不可达、被删除或失效时,系统才会去瞅大数字的路由。
metric值的来源通常有两类:
- 手动配置:管理员在静态路由或网卡配置里显式指定。
- 自动生成:DHCP分配的网关、NetworkManager、systemd-networkd会根据接口类型(有线、无线、虚拟网卡)自动赋一个默认值,比如DHCP默认的
metric=100。
理解这一点,就能解释很多“明明我改了路由表却不生效”的怪现象:可能是DHCP客户端或网络管理工具在你重启网络服务时,把默认值重新写回去了。
1.3 路由选路逻辑:系统不是随机挑网卡出门
Linux内核选路由的顺序大致是这样的:先根据目标IP查找路由表,如果有精确匹配的主机路由、子网路由,直接走;如果都没有,才轮到默认路由(0.0.0.0/0)。当存在多条默认路由时,内核会比较它们的metric,选最小的一条。
这里有个容易忽略的点:默认路由是全局性的,但也受源地址影响。所谓源地址,就是你本机访问外部时,用什么IP作为“发件人”。同一个服务器可以有两个IP,系统发起新连接时,内核会根据路由表反向决定源IP——选中的是哪个网卡的网关路由,源IP就取那个网卡的地址。这就意味着,调metric不光是改一条路由的优先级,本质上是在告诉系统“这台机器的对外身份用哪个IP”。
所以,在多网卡场景里,合理设置metric的意义不只是“让流量走对门”,还直接影响到对外通信的源地址、访问日志里的来源IP、以及基于IP的防火墙策略是否匹配。我见过不少团队在防火墙上配了规则,却因为源IP经常“变脸”导致权限时好时坏,最后发现就是metric没固定住。
2. 动手前先看清现状:网卡优先级排查三板斧
调整之前,一定要先看清楚当前状态。没有这一步,很多配置会改错方向,甚至把原本能用的网络改坏。
2.1 看一眼当前路由表长什么样
最直接的办法:
ip route show这行命令会列出所有路由。重点关注带default字样的行,例如:
default via 192.168.1.1 dev eth0 proto static metric 100 default via 10.10.10.1 dev eth1 proto dhcp metric 10metric 10和metric 100一眼就能看出优先级。上面这个例子里,eth1专网那个网关的metric更小,所以当前默认路由走得是eth1。
如果两条default路由的dev一样,比如都是eth0,那就说明你在同一块物理网卡上配了多个网关或VLAN,这种情况要额外留意,往往是网关冲突,需要先理清哪个是真网关,再谈metric。
查看更详细的策略路由规则:
ip rule show默认状态下会输出类似这样的内容:
0: from all lookup local 32766: from all lookup main 32767: from all lookup default一般场景用main表就够了,除非你有过ip rule add的需求,否则先别动策略路由。
2.2 从/proc/net/route里读原始数据
ip route输出的是格式化好的信息。有时候我想确认系统底层的原始数据,或者写脚本判断优先级时会看这个文件:
cat /proc/net/route输出是十六进制格式的,第一列是网卡名,第二列是目标地址,第三列是网关,后面依次是Flags、RefCnt、Use、Metric等。Metric那一列就是这个接口的度量值,注意它是十六进制显示,比如64代表十进制100。
这种直接读内核数据结构的方式,适合排查“为什么ip route看起来正确但实际流量不对”的疑难情况。我自己遇到过Netfilter规则或策略路由导致路由表显示正常、实际走法异常的案例,看原始表能帮助判断内核到底维护了什么。
2.3 确认你的网卡现在处在“几路同时可用”的状态
检查两块网卡的物理链路状态:
ip -br link showUP状态表示网线插着,DOWN或者NO-CARRIER说明链路断开,一般情况下内核会移除这条链路上的路由。如果你发现路由表里还有对应条目,但物理链路已经DOWN,那可能是路由配置问题,也可能是有线网卡没检测到载波。
还要看IP地址是否配置正确:
ip addr show重点确认:网卡名、MAC地址、IPv4地址、子网掩码是否和预期一致。VMware虚拟机里常见的坑是两块网卡都拿到了相同网段的IP,但网关不同,这种环境下调metric意义不大,得先改IP规划。
这三板斧做完,基本能判断出当前网络处在什么状态:哪条网卡是主用、哪条是备用、当前默认路由是谁。接下来改metric才有据可依。
3. Linux下修改metric:临时生效、持久化配置、以及systemd-networkd的坑
Linux发行版多,网络管理工具也杂。但metric配置的思路是一致的:要么改路由表本身,要么改“生成路由表的上层配置”。我建议先学会手动改路由表验证效果,再落到配置文件里固化。
3.1 临时改法:手改路由表,适合验证不重启
验证metric调整是否有效,最快的办法是ip route replace:
# 把到192.168.1.1的默认路由metric改成50 sudo ip route replace default via 192.168.1.1 dev eth0 metric 50这里有几个关键点:
replace和add不一样,add在已有同网段(to default)路由时会报“RTNETLINK answers: File exists”;replace会把同目的已有路由替换掉。- 必须有
dev eth0参数,否则系统找不到出口网卡。 - 改完之后立刻验证:
ip route show别忘了再用ip route get 8.8.8.8(或任意外网IP)看实际走向:
ip route get 8.8.8.8输出里会明确显示dev eth0还是dev eth1,这个命令判断实际选路非常好用,比单纯看路由表直观得多。
临时改法的问题在于重启网络或执行systemctl restart NetworkManager后失效,所以它只适合验证方案,不适合生产环境固化。
3.2 Ubuntu 22.04 netplan一条yaml改完
Ubuntu 22.04默认用netplan管理网络,配置文件一般放在/etc/netplan/目录下,名字可能是01-network-manager-all.yaml或00-installer-config.yaml。先看看你机器上用了哪个:
ls /etc/netplan/要调整metric,打开对应的yaml文件,在网卡的routes里加metric:
network: version: 2 renderer: networkd ethernets: eth0: dhcp4: true dhcp4-overrides: route-metric: 50 eth1: dhcp4: true dhcp4-overrides: route-metric: 200如果用的是静态IP,就在routes下加:
network: version: 2 renderer: networkd ethernets: eth0: addresses: - 192.168.1.10/24 routes: - to: default via: 192.168.1.1 metric: 50 eth1: addresses: - 10.10.10.10/24 routes: - to: default via: 10.10.10.1 metric: 200这里说几个容易踩的坑:
dhcp4-overrides里的route-metric只对DHCP获取的默认路由生效,如果你同时写了静态routes,静态的优先级会覆盖DHCP自动路由的行为。- 修改yaml后一定要跑
sudo netplan try,这个命令会先试应用配置,如果一段时间内没确认(比如网络断了),会自动回滚,防止把远程连接的机器改到失联。 - yaml文件的缩进非常严格,一个空格错位就会应用失败。我见过太多人把
routes写成网卡平级,导致netplan直接报错。
应用成功后,用ip route show看效果,两条default路由的metric应该就是你设定的值了。
3.3 openEuler/兼容RHEL系:nmcli和ifcfg文件两种走法
openEuler和CentOS系常见的网络管理工具是NetworkManager,它也支持纯ifcfg文件配合network.service。先说怎么用nmcli改metric。
假设网卡连接名是eth0,把它作为默认出口,metric改成50:
# 查看当前连接名 nmcli connection show # 修改eth0连接的默认路由metric sudo nmcli connection modify eth0 ipv4.route-metric 50 # 重新激活连接让它生效 sudo nmcli connection up eth0如果不用默认路由,而是想针对某条静态路由设metric,可以这样:
sudo nmcli connection modify eth0 +ipv4.routes "192.168.100.0/24 192.168.1.254 metric=20"ipv4.route-metric是“这个接口上所有自动/默认路由的metric基础值”,和+ipv4.routes的metric是两回事,别混为一谈。
如果你偏爱传统的ifcfg文件方式,直接编辑/etc/sysconfig/network-scripts/ifcfg-eth0:
TYPE=Ethernet BOOTPROTO=none DEVICE=eth0 ONBOOT=yes IPADDR=192.168.1.10 PREFIX=24 GATEWAY=192.168.1.1 METRIC=50注意:
GATEWAY指定默认网关后,METRIC控制这个网关在路由表里的优先级。- 如果两个网卡都写了
GATEWAY,METRIC较小的那个会成为主默认路由。 - 修改完需要
systemctl restart network或nmcli connection reload(取决于系统是否启用了network服务),不是改完立即生效。
openEuler默认启用了NetworkManager,但在一些无桌面服务器上可能同时存在network.service。如果两个服务同时在管同一块网卡,容易产生路由表混乱。我的建议是:用nmcli管理连接,就停用network.service;用ifcfg,就禁用NetworkManager,避免“两个包工头管一个工地”。
3.4 别忽略DHCP给你偷偷追加的metric
这里有个非常常见的坑:当你手动设置了metric,重启网络后发现路由表里的metric值变了——不是你设的那个数。原因多半是DHCP客户端(如dhclient、systemd-networkd)下载路由时给网关加了一个“自动metric”。
在Ubuntu 22.04的netplan里,就有一个dhcp4-overrides的选项,专门用来控制DHCP分配的路由metric。如果不设置,systemd-networkd会依据接口类型给默认值:有线网卡通常是100,无线网卡通常是600左右。这意味着你即使手动加了静态事件,如果DHCP也同时在下发,两者之间会互相覆盖,最终哪个生效取决于先后顺序和协议优先级。
排查思路很简单:如果配置了metric但路由表显示值不对,先看是不是DHCP在捣鬼,用cat /var/lib/dhcp/dhclient.leases(如果用的是dhclient)能看到有没有routers和interface-mtu这些字段。另外,NetworkManager的管理范围里,你还可以在“连接”级别上设定自动获取IP时是否应用DHCP下发的路由:
nmcli connection modify eth0 ipv4.ignore-auto-routes no但更靠谱的做法是:显式指定metric,让它成为静态路由的一部分,别指望DHCP自动生成的metric能稳定。
4. Windows、VMware虚拟机里的metric配置没那么复杂
很多人以为只有Linux要调metric,其实Windows多网卡场景一样会遇到。而且VMware虚拟机里配双网卡,底层逻辑也绕不开metric。
4.1 Windows图形化改metric和PowerShell改法
Windows网卡的metric叫“接口跃点数”。桌面场景最常见的需求是:笔记本同时连着Wi-Fi和有线网,希望优先走有线。Windows默认会自动计算跃点数,有线一般比无线低,但偶尔会被自动计算搞出相反的优先级。
图形化改法:
- 打开“网络连接”窗口(
ncpa.cpl)。 - 右键目标网卡,选择“属性”。
- 选择“Internet协议版本4 (TCP/IPv4)”,点击“属性”。
- 点击“高级”按钮,勾掉“自动跃点”,在“接口跃点数”里填入数字,比如5。
- 确定保存。
PowerShell改法更快:
# 查看所有网卡接口和当前跃点数 Get-NetIPInterface -AddressFamily IPv4 | Select-Object InterfaceIndex, InterfaceAlias, InterfaceMetric # 把指定接口的metric改成5 Set-NetIPInterface -InterfaceIndex 12 -InterfaceMetric 5InterfaceIndex怎么找?Get-NetIPInterface输出里第一列就是。这里要留意:Windows的metric同样越小越优先,所以想“让有线优先”,有线的metric设小值,无线的设大值或不改,让它自动算出一个稍大的数值。
改完之后验证:
route print -4命令输出里的Metric列可以看到每个网段对应的跃点数。
4.2 VMware虚拟机双网卡和物理机多网卡的同与不同
VMware虚拟机里的双网卡,本质上是虚拟网卡连接到了不同的虚拟网络。常见组合是:一个NAT网卡(vmnet8)用来访问外网,一个Host-Only网卡(vmnet1)只和宿主机互通。理论上两块网卡同时挂上,虚拟机系统内部的路由选择和物理服务器完全一致——还是要看metric。
但有个特殊点:VMware虚拟网卡默认情况下,可能会自动生成一个“默认网关是宿主机虚拟网卡”的路由。比如NAT网卡的默认网关一般是vmnet8的网段地址(通常为192.168.x.1或192.168.x.2),Host-Only网卡没有默认网关,或者也会生成一条到宿主机网络的路由。如果两块网卡都配了默认网关,虚拟机内部就会面临“到底走哪个网关”的抉择,这同样靠metric解决。
我在VMware里调metric的步骤和前面Linux方法完全通用,但有个细节比物理机更常见:虚拟机的两块网卡可能在同一个网段。这时候改metric没有意义,因为进程访问同一网段时直接ARP广播,根本不用默认路由。必须先保证两块虚拟网卡属于不同的子网,再谈网关优先级。
另外,ESXi环境里,如果虚拟机使用了多个端口组(如不同iSCSI存储网络),也建议把存储网络的网卡metric设得比业务网络低,避免vMotion或备份流量占用业务带宽。实际配置在虚拟机操作系统内部改,和物理机没有区别。
5. 实战案例:一台服务器同时连办公网和业务专网的部署记录
这个案例比较典型,我完整走一遍配置过程,可以直接抄作业。机器环境:openEuler 22.03,双网卡,eno1连办公网,eno2连业务专网。
5.1 需求描述与拓扑
- eno1:办公网,192.168.1.20/24,网关192.168.1.1。办公网同事需要通过这个IP访问服务器上的协同办公服务。
- eno2:专网,10.10.10.20/24,网关10.10.10.1。服务器需要访问专网里的数据库、文件服务等资产。
- 要求:默认情况下,办公网和专网都能访问,但主动外访的默认出口必须是办公网,专网只用于访问专网内部资源。因为业务方希望在办公网防火墙上做策略,不希望服务器以专网IP主动访问公网。
这个需求如果用一句话说就是:把办公网的metric调小,专网的metric调大,但两个网络都要通。
5.2 初始状态、问题表现
刚装好系统时,我在两个网卡的ifcfg文件里都写了GATEWAY,重启网络后查看路由表:
default via 10.10.10.1 dev eno2 proto static metric 100 default via 192.168.1.1 dev eno1 proto static metric 101专网网关的metric比办公网小1,系统把专网当成了默认出口。结果就是服务器主动访问公网时源IP是10.10.10.20,这在办公网防火墙上直接被抓为“来自未知来源”,好多服务被拦。办公网用户访问服务器倒是可以通,但服务器去连接公网接口时经常出现超时。
这个metric为100和101的差异,是NetworkManager根据网卡名称排序生成的,不是人为指定,非常“随缘”。生产环境不能依赖这种自动分配的顺序。
5.3 配置过程、验证步骤
第一步,修改eno1对应的ifcfg文件,把metric改成10:
sudo vi /etc/sysconfig/network-scripts/ifcfg-eno1在文件里加入(或修改)METRIC=10。同时确保BOOTPROTO是none或static。eno2的metric设置为200,让专网变成次选:
sudo vi /etc/sysconfig/network-scripts/ifcfg-eno2 # 加入 METRIC=200第二步,重启网络服务。如果用的是NetworkManager:
sudo nmcli connection reload sudo nmcli connection up eno1 sudo nmcli connection up eno2如果用的是传统的network服务:
sudo systemctl restart network注意,如果两个管理服务同时存在,务必确认当前生效的是哪个。我建议在openEuler上只保留NetworkManager,因为network.service和NM对ifcfg-METRIC的支持程度不太一样,容易白改一场。
第三步,查看路由表:
ip route show default via 192.168.1.1 dev eno1 proto static metric 10 default via 10.10.10.1 dev eno2 proto static metric 200办公网排在最前,符合预期。
第四步,验证默认出口:
ip route get 8.8.8.8 # 输出中应显示 dev eno1访问专网内部资源时,因为目标10.10.10.0/24有直连路由,根本不会走default,所以直接访问数据库没问题。
第五步,验证办公网同事访问服务器:在办公网一台PC上ping 192.168.1.20,以及尝试访问业务端口。关键是反向流量路径:服务器从eno1收到请求,回包时看路由表,因为源IP是192.168.1.20,而ip rule默认main表里对这个数据的查表顺序一致,最终也走eno1返回,避免了非对称路由。
这里有个细节值得多说一句:当服务器只有一张网卡有默认网关时,入站请求从哪个网卡进来,回包也大概率从哪个网卡走(因为目标IP是办公网段,走直连路由)。但当两个网卡都有默认网关且有非对称路由风险时,光调metric不一定能解决所有回包问题。更稳的思路是给回包流量加策略路由,不过那是另一个话题,大多数人其实用不到,先不展开。
配置完成后,跑了三天,办公网防火墙的拦截日志里再也没有出现来自10.10.10.20的公网请求,整体稳定。
6. 排查技巧与常见问题速查表
改metric这件事,操作不复杂,但出问题时排查链比较长。我把实际运维中遇到的高频问题整理成一张速查表,照着查能省不少时间。
| 现象 | 可能原因 | 排查/解决办法 |
|---|---|---|
| 改了配置文件,路由表不变 | 网络服务没重启或管理工具冲突 | 确认是NetworkManager还是network.service在管,执行对应的reload/restart |
| 路由表改了,但实际流量不从预期网卡走 | 存在更小的metric路由或策略路由规则 | ip rule show;ip route get 目标IP看实际选路 |
| 两块网卡同网段,metric不起作用 | 同网段是直连路由,不查default | 改网络规划,确保不同网卡在不同子网 |
| 重启后metric被重置 | DHCP客户端覆盖 | 在netplan里用dhcp4-overrides.route-metric显式锁定 |
| 改metric后办公网网民无法访问服务器 | 非对称路由 | 确认回包路径,必要时加策略路由按源地址选路 |
| Windows改跃点数后不生效 | DHCP仍然在下发路由 | 在高级设置里勾掉“自动跃点”并手动填数值;检查是否有多个网卡竞争 |
| VMware里两块虚拟网卡,外网时通时不通 | 两块网卡都设了默认网关 | 保留一个网关,另一个网卡只配IP不加GATEWAY,或调低其metric |
几条实战心得,都是踩过坑才总结的:
- 改metric别贪心,差一个数量级足够。比如办公网设10,专网设100,优先级已经非常明确。设成1和2虽然也可以,但一旦需要往后插新网卡,你会发现自己没有足够数字空间了。
- 改完一定要验证实际选路,不只停留在看路由表。
ip route get是必做的验证步骤。有些场景下策略路由优先级高于路由表,光看ip route会误导你。 - 不要再手动改
/etc/iproute2/rt_tables这种底层文件了,除非你有明确的策略路由需求。正常情况下metric配置完全够用,动策略路由表反而容易把系统搞到网络全断。 - 备份配置文件再动手。netplan和ifcfg的语法容错率极低,改之前
cp一份原文件,改完发现不对立刻cp回去,比重新写快得多。
至于“改完网络断了怎么办”这种情况,尤其是远程服务器,我强烈建议先写好一个自动回滚脚本,或者至少确认有一个带外管理通道(比如IPMI)能进去。等手头有可以随时物理接入的机器,再放心大胆地改。真实生产里因为调metric导致SSH断连、人不在机房、最后只能让同事跑一趟的教训,我都见过不止一次。
metric这个东西,你说它简单吧,命令就那么几条;说它复杂吧,牵扯到系统选路、DHCP行为、网络管理工具策略,任何一环不对都会出幺蛾子。但把原理捋清楚、验证步骤养成习惯之后,它反而是多网卡服务器里最可控、最容易定位的配置项之一。我自己现在每配一台双网卡机器,第一件事就是检查默认路由的metric,把优先级明确写进配置里,然后顺手把验证命令记录到交接文档里。这个习惯帮我少处理了不知道多少“网络时好时坏”的工单。