
虚拟机里那台 Ubuntu 昨天还好好的今天一开机右上角网络图标变成一个小问号终端里 ping 什么都回不来——这个场景我遇到过不下十次。有的发生在系统更新之后有的发生在宿主机换了 WiFi 之后还有一次是同事把虚拟机整个目录拷到另一台机器上打开网卡名字直接从ens33变成了ens34配置文件里的名字对不上网络自然就没了。虚拟机里的 Ubuntu 连不上网听起来原因五花八门但真正排查下来八成集中在三个地方虚拟网络模式没配对、系统这一侧的网卡没被管起来、地址拿到了但 DNS 或路由指向不对。这三件事分属不同层次混在一起看只会越查越乱——你会一边怀疑虚拟机软件设置有问题一边又去改 netplan最后两个地方都改乱了反而丢了原始状态。我把这些年的排查经验按层重新梳理了一遍从最外层的虚拟网络设置到系统里的 netplan 与 NetworkManager 的归属关系再到 DNS 和路由表。每一层都给能直接照着敲的命令、判断依据和典型症状前面几节偏诊断后面几节偏修复和固化。刚接触虚拟机的朋友可以把它当排错手册按顺序走一遍用过一段时间的人应该也能从中找到几个自己以前没注意过的细节。1. 先判断卡在哪一层别急着改配置1.1 三条命令看清现状我见过太多人一发现没网就打开配置文件开始改这是最坏的习惯。配置改乱了原本能复现的问题就变成了改了也不对改回去也不对。进系统之后第一件事是看清楚现状三条命令足够ip addr ip route cat /etc/resolv.confip addr告诉你网卡有没有起来、有没有拿到地址ip route告诉你数据包打算往哪儿走cat /etc/resolv.conf告诉你域名要向谁去问。这三条输出组合起来基本能锁定问题在哪一层。判断逻辑可以整理成下面这张表我平时排查时脑子里过的就是这个流程现象最可能的原因下一步该看什么只有lo或网卡只有inet6 fe80::地址网卡未启用 / DHCP 未响应ip link看状态检查虚拟网络设置地址是169.254.x.xDHCP 请求发出去了但没人应答虚拟网络的 DHCP 服务有正常地址但ip route没有default via默认网关缺失netplan 的 routes 配置有地址有默认路由ping 网关通、ping 公网 IP 不通出口不通NAT 或上游有问题虚拟网络模式、宿主机网络ping 公网 IP 通、ping 域名不通DNS 配置问题/etc/resolv.conf、resolvectl这张表不是万能的但它能把完全没头绪变成先看哪一项排查效率差别很大。我特别想强调第三行和第四行的区别很多人一看到上不了网就直接去查 DNS其实如果连公网 IP 都 ping 不通DNS 再怎么配也没用那是更底层的通路问题。1.2ip addr输出里两个容易看错的细节ip addr的输出信息量很大但新手最容易忽略的是接口状态那一行。你会看到类似这样的内容2: ens33: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc fq_codel state UP尖括号里的UP和LOWER_UP是两个不同的东西。UP表示这块网卡在系统层面被启用了管理员没有把它 down 掉LOWER_UP表示链路层检测到对端有信号也就是网线插上了。这两个状态分离正是排查的关键点有UP没有LOWER_UP系统这边没问题是对端没接上。在虚拟机场景里这通常意味着虚拟机设置里的已连接复选框被取消了或者虚拟网络适配器在宿主机上被禁用。两个都有state却是DOWN网卡被手动关闭过sudo ip link set ens33 up就能恢复。两个都没有网卡压根没被虚拟化层暴露出来去虚拟机设置里确认网卡设备是否存在。这个区分能省掉大量时间。有一次我在笔记本上排查ip addr里网卡名字在、没有地址我下意识以为是 DHCP 问题盯着虚拟网络编辑器看了半天。后来注意到尖括号里少了LOWER_UP才反应过来是宿主机休眠唤醒之后虚拟网卡掉线了在宿主机网络连接里禁用再启用一次就好了跟配置毫无关系。1.3 逐跳验证把不通切成四段确认网卡状态正常之后用四个 ping 把链路切成四段逐段排除。这个方法的思路是让每一跳都变成一次可以下结论的测试ping -c 4 127.0.0.1 # 协议栈自身 ping -c 4 192.168.56.1 # 网关换成你自己的实际网关 ping -c 4 223.5.5.5 # 公网 IP换成任意公共 DNS 地址都行 ping -c 4 archive.ubuntu.com # 域名解析第一跳不通说明网络协议栈本身有问题这种情况极少见通常伴随lo接口异常第二跳不通但第一跳通说明问题在虚拟网络内部虚拟交换机或者宿主机侧第三跳不通而第二跳通问题出在 NAT 转换或宿主机的外网出口第四跳不通而第三跳通就是纯粹的 DNS 问题。这里有个实操细节值得说ICMP 在某些网络环境里会被拦截ping 不通不代表真的不通。如果第三跳失败但第二跳正常别急着下结论用curl -I或者nc -zv再验证一次走 TCP 端口往往更可靠。我在一个朋友的办公网络里就遇到过ping 公网 IP 全部超时但浏览器和curl一切正常纯粹是 ICMP 被掐了。当时如果只信 ping 的结论就会一路往 NAT 里查白费几个小时。2. 虚拟网络模式选不对后面的排查全是白费2.1 四种模式各自解决什么问题绝大多数虚拟机连不上网的根因在这一层。主流虚拟机软件提供的网络模式就那么几种理解它们的差别比背配置命令重要得多模式虚拟机能否访问外网宿主机能否访问虚拟机局域网其他设备能否访问典型用途桥接能能能需要被局域网其他机器访问的服务NAT能能不能除非做端口映射日常开发测试最省事仅主机不能能不能纯隔离环境内部组网实验自定义/内部网络看配置看配置不能多台虚拟机之间互联日常开发我基本只用 NAT。原因很直接桥接模式下虚拟机会从局域网的 DHCP 服务拿地址占用一个真实的局域网 IP公司网络的网段往往有数量限制而且换了 WiFi 环境 IP 就变了之前写死的连接地址全部失效。NAT 模式下虚拟机的地址完全由虚拟化软件自己管理跟宿主机在哪个网络毫无关系换咖啡馆、换家里、换公司都不用动配置。判断自己当前用的是什么模式最直接的办法是看虚拟机设置里的网络适配器选项另一条路是看虚拟机拿到的地址段。NAT 模式通常是一个固定的私有网段桥接模式则跟宿主机的 IP 在同一个网段。比如宿主机是192.168.1.x虚拟机也是192.168.1.x那基本可以确定是桥接。2.2 桥接模式最常踩的坑物理网卡选错用桥接模式的人遇到的第一个问题几乎都是这个。宿主机上有多块网卡——有线、无线、虚拟网卡、蓝牙网络适配器桥接设置里如果选的是自动虚拟化软件有时会挑错一块尤其是宿主机同时连着有线和无线的时候。症状很有辨识度虚拟机拿到了地址但这个地址跟宿主机不在同一个网段或者地址看起来正常但完全 ping 不通任何东西。这时候去对比一下宿主机的ipconfigWindows或ip addrLinux/macOS和虚拟机的地址网段对不上就说明桥到了错的网卡上。修复方法是在虚拟机设置的网络适配器里手动指定桥接到具体的那块物理网卡别用自动。改完之后虚拟机会重新走一次 DHCP等几秒地址就过来了。另一个不太常提的坑桥接到无线网卡经常不稳定。无线接入点通常只允许一个设备占用一个 MAC 地址虚拟机桥接之后相当于多了一个 MAC有些路由器或企业级接入点会直接拒绝表现就是虚拟机偶尔能通、偶尔不通或者完全拿不到地址。我遇到这种情况直接换回 NAT省事得多——桥接无线网卡本来就不是个可靠方案。2.3 NAT 模式DHCP 服务没起来、虚拟网卡被禁用NAT 模式看似配置一次永远不管但它依赖两个东西在宿主机侧正常工作虚拟网络对应的虚拟网卡处于启用状态以及负责地址分配和地址转换的后台服务在运行。这两样任何一个出问题虚拟机这边看到的现象都是拿不到地址。宿主机是 Windows 的时候打开网络连接面板能看到多出来的虚拟网卡。如果它显示为灰色已禁用虚拟机一定上不了网右键启用即可。这个状态会在一些系统清理工具、安全软件、或者系统大版本更新之后被意外改掉我遇到过两三次。后台服务的问题更隐蔽。虚拟化软件安装时会注册若干系统服务负责 NAT 和 DHCP。安全软件有时会把这些服务拦下来或者设为手动启动结果就是重启之后服务没跑虚拟机拿不到地址。检查方法很简单在宿主机的服务管理里找与虚拟化软件相关的服务项确认它们处于运行状态启动类型是自动。如果确认服务和网卡都正常虚拟机还是拿不到地址最后一招是在虚拟网络编辑器里点还原默认设置。这个操作会把虚拟网络配置重置回出厂状态代价是之前自定义的端口映射、地址池全部清空但换来的是一个干净的起点比一点点查配置快多了。我在写过一堆端口映射之后误点过一次这个按钮那次的教训是改虚拟网络配置之前先把规则截图存下来。3. Ubuntu 这侧的网卡为什么没被管起来3.1 netplan 配置文件缩进错一格整份配置被静默忽略Ubuntu 从 17.10 开始用 netplan 管理网络配置文件放在/etc/netplan/下YAML 格式。YAML 这门格式最大的特点是对缩进极度敏感且绝不允许 Tab 字符。用编辑器补全或者从网页复制配置时带进来一个 Tab整份文件就会解析失败。network: version: 2 ethernets: ens33: dhcp4: true上面这份是最小可用配置两空格缩进层级关系一目了然。ens33是网卡名要换成你自己实际的接口名用ip link或ip addr都能看到。改完配置之后不要直接netplan apply先用sudo netplan generate检查语法。这一步只校验不生效有错会直接把行号和原因打出来。确认没问题再应用。更稳的做法是用sudo netplan try它会尝试应用配置并给 120 秒的确认窗口如果你因为配置错误把自己 SSH 断了超时后会自动回滚到之前的配置。这个功能在只有远程连接、不能开控制台的环境下几乎是必需的。还有一个很多人不知道的约束/etc/netplan/下的配置文件权限不能太开放。如果文件权限是 644 甚至 777netplan会给出警告并拒绝应用理由是这个文件可能包含凭据信息。正确权限是 600用sudo chmod 600 /etc/netplan/*.yaml一次性改掉。这个警告信息不太显眼容易被当成正常输出忽略过去然后困惑于为什么改了没效果。3.2 克隆或迁移虚拟机之后网卡名从ens33漂移到ens34这是我认为最值得单独拿出来讲的一个坑因为它伪装得特别好——所有配置看起来都对但就是不生效。Ubuntu 的网卡命名规则会根据网卡的 MAC 地址生成稳定名字。你把一台虚拟机克隆一份或者把整个虚拟机目录复制到另一台机器上打开虚拟化层会给新机器分配一个新的 MAC 地址系统检测到硬件变了就会生成一个新的接口名。原来是ens33克隆之后可能变成ens34而你 netplan 里写的还是ens33配置自然匹配不到任何设备网卡就处于未管理状态。识别方法很直接ip link列出所有接口跟你配置文件里写的名字一对比对不上就是这个问题。dmesg | grep -i eth也能看到系统在启动时重命名网卡的记录。修复有三种思路我按推荐程度排一下第一直接改配置文件里的网卡名把ens33改成实际的ens34。最直接但下次再克隆还会出同样的问题。第二用match按 MAC 地址匹配。netplan 支持先匹配再配置MAC 地址写死之后无论接口名怎么变配置都能落到正确的网卡上。缺点是 MAC 地址本身在克隆后会变所以这一招更多用于同一台虚拟机重启后名字漂移的场景。第三让系统不再按新 MAC 分配新名字。克隆场景下清空/etc/machine-id和/var/lib/dbus/machine-id再重新生成能解决一部分问题但网卡名的判断依据在 udev 规则里这条路不是每次都灵。我自己的习惯是克隆虚拟机之后第一件事就是打开终端看ip link确认网卡名然后直接改 netplan 里的名字。这个动作花不了两分钟但能省掉后面半小时的困惑。3.350-cloud-init.yaml和你的自定义配置打架/etc/netplan/目录下如果有多个 yaml 文件netplan 会按文件名的字母顺序依次读取并合并。很多云镜像或者定制镜像里自带一个50-cloud-init.yaml由云初始化工具自动生成。你自己新建的配置如果叫99-custom.yaml理论上会覆盖前面的设置但如果两份配置针对同一个网卡写了互相冲突的字段实际生效的结果可能跟你预期的不一样。更麻烦的是这类自动生成的配置文件可能会在每次开机时被重写你手动改的内容下次启动就没了。症状很好认改完当时好了重启又不行反复几次。想让自己的配置说了算有两个办法。一是直接禁用云初始化对网络的管理创建/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg内容写network: {config: disabled}二是把自动生成的那份文件删掉或者改名让它排在最后。我更倾向第一种因为文件本身还在出问题时有据可查。改完之后别忘了sudo netplan apply然后重启一次验证配置是否真的持久。只在当前会话里生效的修复不算修复这个道理在虚拟机环境里格外成立——毕竟虚拟机的使用方式就是反复开关。3.4 桌面版显示未托管nmcli里看不到设备Ubuntu 桌面版默认使用 NetworkManager 管理网络而 netplan 只是配置的上游最终执行者是 NetworkManager 或者 systemd-networkd。这两套东西如果职责没划清楚就会出现配置写对了、命令也执行了但网络图标上显示未托管的诡异状态。诊断命令是nmcli device status。正常情况下列表里应该能看到你的网卡状态是connected或disconnected。如果显示unmanaged说明 NetworkManager 主动放弃了对这块网卡的管理。原因通常是 netplan 配置里指定了renderer: networkd却跑在桌面版上——桌面版期望由 NetworkManager 接管网络两边都不管网卡就悬空了。修复方法是在 netplan 配置的对应网卡下加一行renderer: NetworkManager或者干脆全局指定。反过来如果服务器版上误配了 NetworkManager也会出现类似问题只是没有图形界面提示更难发现。还有一处容易忽略/etc/NetworkManager/NetworkManager.conf里的[ifupdown]段落有一个managedfalse选项。某些系统里它默认是 false意思是不管理那些已经在/etc/network/interfaces里配置过的接口。改它为 true然后重启 NetworkManager 服务网卡就能被正常接管了。4. 地址有了却打不开网页路由表和 DNS 的锅4.1 ping IP 通、ping 域名不通八成是/etc/resolv.conf这是最经典的一类。ping 223.5.5.5秒回ping archive.ubuntu.com提示Temporary failure in name resolution说明物理链路、路由、NAT 全程畅通唯一卡住的是域名解析这一步。Ubuntu 上的/etc/resolv.conf现在基本不是个普通文件而是一个软链接指向 systemd-resolved 的运行时文件。你如果直接编辑它短期有效重启或者服务重载之后就被覆盖回去了。这个行为坑过很多人改完发现当时好了第二天又不行来回折腾。排查用resolvectl status看当前实际生效的 DNS 服务器和每个接口的解析状态。如果显示Current DNS Server为空或者指向一个不可达的地址那就是配置源头的问题。正确的修改位置在 netplan 配置里加nameservers段落network: version: 2 ethernets: ens33: dhcp4: true nameservers: addresses: [223.5.5.5, 119.29.29.29]这两个地址只是举例换成任何你能访问的公共解析地址都行。如果用的是 DHCP 自动获取路由器一般会下发 DNS 地址多数情况下不用手动指定只有当路由器下发的地址不可用或者你想绕开本地解析时才需要手动写。还有一种情况值得提DNS 服务器地址填对了但解析仍然超时。这时候用dig 223.5.5.5 archive.ubuntu.com直接向指定服务器发查询绕开系统的解析缓存和链路。如果这条命令能出结果而系统解析不行问题就在 systemd-resolved 这一层重启服务或者清缓存sudo resolvectl flush-caches通常能解决。4.2 双网卡抢默认路由流量走错门虚拟机加了第二块网卡之后突然上不了网这个现象很有意思。典型场景是主网卡用 NAT 上网第二块网卡用仅主机模式做管理通道两块网卡都通过 DHCP 拿到了地址也各自都下发了默认网关。系统会从两条默认路由里挑一条 metric 更小的走如果恰好挑中了那块没有外网出口的管理网卡所有外网流量都往死胡同里跑。判断方法不是看ip addr而是看ip route。如果输出里出现两条default via就中招了ip route # default via 192.168.56.1 dev ens33 proto dhcp metric 100 # default via 192.168.200.1 dev ens37 proto dhcp metric 200ip route get 223.5.5.5能直接告诉你某个目标地址实际会走哪条路由、从哪个接口出。这条命令比对着路由表推演快得多我排查路由问题时基本第一反应就是敲它。修复思路是让管理网卡不参与默认路由的竞争。netplan 里可以给这块网卡加上dhcp4-overrides: use-routes: false这样它仍然会拿地址用于局域网内部通信但不会往路由表里插默认网关。或者反过来给有外网出口的那块网卡设一个更小的 metric明确优先级。两种做法效果一样看个人习惯。4.3 拿到的地址是169.254开头的说明 DHCP 根本没应答169.254.x.x这个网段有个专门的名字叫链路本地地址系统在 DHCP 请求超时后会给自己分一个这样的地址含义非常明确网线通了但对端没有给我发地址。这个现象的排查方向跟前面说的 NAT 服务、虚拟网卡禁用是重合的但我还想补充一个容易忽略的情况虚拟机软件自带的 DHCP 地址池可能跟宿主机的网段冲突。比如地址池配的是192.168.1.100-192.168.1.200而宿主机所在的局域网也是192.168.1.0/24两边打架分配出来的地址在宿主机上不可达。这种情况在咖啡馆、酒店这类公共网络里特别容易出现因为对方的网段你无从预知。解决办法是在虚拟网络编辑器里把 NAT 网段改成一个不常见的私有段比如192.168.77.0/24。改完之后虚拟机会重新拿地址配置里的网关也要跟着改。我现在的习惯是固定用几个冷门网段避免每次换网络环境都要重新调。5. 一次完整的排查记录从图标打叉到网卡名漂移5.1 现象描述和最初的三个假设前段时间帮人看一台 Ubuntu 虚拟机症状是开机后桌面右上角的网络图标直接打叉终端里ping 127.0.0.1正常ping任何外部地址都是Network is unreachable。这台机器之前一直好用中间做过的唯一操作是把它从一台笔记本拷贝到了另一台机器上继续用。我当时的三个初始假设按可能性排序一是虚拟机的网络适配器在拷贝过程中被设成了未连接二是网卡名因为 MAC 变化漂移了配置没跟上三是宿主机侧的虚拟网卡被禁用。5.2 逐层排除的时间线第一步看虚拟机的网络适配器设置勾选状态正常已连接和启动时连接都勾着排除假设一。第二步在宿主机上看网络连接面板虚拟网卡存在且处于启用状态对应的后台服务也在运行排除假设三。到这里假设二成了唯一的可能。第三步回到虚拟机内部ip link输出里只有lo和一块叫ens34的网卡状态是DOWN。而/etc/netplan/下的配置文件里写的是ens33。假设二成立。有意思的是ens34状态是DOWN而不是UP这说明系统不仅名字变了新网卡连启用都没做——因为它没有匹配到任何配置netplan 不会去动它。这解释了为什么ping提示的是Network is unreachable而不是Destination Host Unreachable系统压根不知道往哪儿发包。5.3 修复动作和后续的固化措施修复动作本身很简单把配置文件里的ens33改成ens34sudo chmod 600保证权限sudo netplan apply然后ping验证。整个过程不到三分钟。真正有价值的是后面做的事。为了避免同样的问题再出现一次我做了三件事把网卡配置从固定名字改成配置与直觉一致的形式同时在文档里记下克隆或迁移虚拟机后第一件事是确认网卡名。这条经验后来帮了至少两个人。在那台虚拟机上把网络配置和软件源配置单独打包备份了一份。虚拟机最容易丢的就是这类手写的配置装一次系统不难把配置回忆起来才费时间。把这次的排查路径写成了一张纸贴在显示器边上——三条命令看出状态四个 ping 分段定位最后才动手改配置。顺序很重要先诊断后动手能避免把简单问题复杂化。6. 让这类问题不再反复的几个习惯6.1 动网络配置之前先打快照虚拟机最大的好处就是快照但很多人不用。网络配置有个特点改错之后很可能连不上网也就没法在线搜索解决方案只能凭记忆硬扛。快照是唯一能让你在三十秒内回到改之前状态的手段。我的习惯是每次要动/etc/netplan/或者虚拟机网络设置先在虚拟机软件里打一个快照名字写成网络配置正常-日期。快照占不了多少空间但能把一类改乱了自己都不知道改了什么的事故彻底消灭。要是虚拟机本身不方便快照至少把配置文件复制一份改名带日期成本一样低效果差一点但聊胜于无。6.2 静态 IP 该写在哪里很多人给虚拟机配静态 IP 会直接改系统里的配置但更稳妥的做法是先看虚拟化软件自己的地址分配机制。NAT 模式下虚拟机软件通常支持按 MAC 地址绑定固定 IP在虚拟网络编辑器里配置。这样操作系统侧保持 DHCP 不变IP 由虚拟化层固定分配好处是换系统、重装、克隆都不用重新配——配置文件可以一直沿用 DHCP 的默认写法。如果确实需要在系统内配置静态地址注意 Ubuntu 版本的语法差异较老的版本用gateway4指定网关22.04 之后这个字段被弃用改用routes下的to: default写法。配置文件里混用新旧语法经常出现应用没报错但网关没生效的情况。network: version: 2 ethernets: ens33: dhcp4: false addresses: - 192.168.77.10/24 routes: - to: default via: 192.168.77.1 nameservers: addresses: [223.5.5.5]写完先sudo netplan generate校验再sudo netplan try试运行。静态地址最容易犯的错是网关和网段不匹配比如地址是192.168.77.10/24却把网关写成192.168.1.1配置能通过校验但永远通不了检查ip route输出就能发现端倪。6.3 一份随身带的诊断清单最后把这套排查里最常用的命令整理成一份清单出问题的时候从上往下敲一遍基本能定位到具体层次ip link # 网卡是否存在、是否 UP ip addr # 是否拿到地址、地址是否合理 ip route # 默认路由是否存在、几条 ip route get 223.5.5.5 # 实际走哪个接口 cat /etc/resolv.conf # 解析指向 resolvectl status # 实际生效的 DNS nmcli device status # 是否被 NetworkManager 接管 ping -c 4 网关 # 二层到三层 ping -c 4 223.5.5.5 # 三层到出口 ping -c 4 archive.ubuntu.com # 域名解析一个补充技巧ss -tuln能看本机监听的端口curl -I能看 HTTP 层的连通性这两个在 ICMP 被拦截的环境里比 ping 更可信。还有如果一切配置都对但某个特定服务连不上别急着怀疑网络先试试date看系统时间——虚拟机休眠恢复后时间偏移太大会导致一些基于证书的连接直接失败现象看起来特别像网络问题实际上是时间问题。我在实际使用中最深的一个体会是虚拟机网络排错的成本绝大部分不在修复本身而在于搞清楚到底是哪一层出了问题。上面这些命令和判断逻辑说到底就是帮你把一个大问题切成四个小问题。切得足够细每个小问题都有明确的判断依据剩下的就是照方抓药。改之前先看一眼现状改完重启验证一次是否持久——这两个动作坚持下来大部分反复出现的网络问题都能一次解决掉。