Ubuntu重启后丢失网络配置
做运维和玩Linux的老哥们,大概都遇到过这么一档子窝火事:Ubuntu服务器或者开发机上一套网络配置好不容易调通了,什么静态IP、网关、DNS全部就位,跑起来也稳定得很。结果某天重启了一下系统,登录进去一看,IP没了,网卡变成光秃秃的down状态,或者干脆变成了DHCP自动分配,之前的配置全部作废。群里一句话总结:Ubuntu重启后丢失网络配置。
这问题说大不大,说小不小,不解决吧,每次重启都得手动敲命令调整,尤其是手里管着一批机器的时候,那叫一个折磨。说小也不小,如果是机房里的机器重启后失联,人又不在现场,那就是运维事故了。我最早踩这坑是在一套内部测试环境上,那会儿还在用Ubuntu 18.04,后来在20.04、22.04上都见过,网上搜一圈,很多帖子写的又碎又旧,照着做反而越改越乱。这篇就把我自己实际排查和解决的过程整理出来,从原理到操作都过一遍,给同样被这个问题折腾的人做一个可以直接参考的完整方案。
先说清楚这套内容适合谁:系统管理员、运维工程师、日常用Ubuntu做开发和部署的开发者,还有踩坑之后搜到这篇文章的普通用户。如果你是刚接触Linux没多久的新手,也不用怕,我会把每一步涉及到的背景概念都拆开讲明白。
1. 问题背后的配置体系:先搞清楚Ubuntu到底在用什么管网络
1.1 netplan是绕不开的核心
Ubuntu从18.04开始,默认的网络配置管理工具换成了netplan。这个东西本质上是一个基于YAML的配置前端,它本身不直接管网卡,而是把你写的YAML配置转换成后端实际使用的配置。后端有两个选择:一个是NetworkManager,一般桌面版默认用这个;另一个是systemd-networkd,服务器版默认用这个。
很多人丢配置,根源就在于没搞明白这一个逻辑:netplan只是一个生成器,它读的是 /etc/netplan/ 目录下的YAML文件,然后把你写的东西推给后端工具去执行。
当你重启系统之后,netplan会重新读取YAML文件、重新生成配置、重新应用它。如果你发现重启之后网络配置“丢了”,那有几种可能:
- YAML文件本身没被正确加载,比如文件权限不对、文件名后缀不对。
- YAML文件加载了,但里面的配置写错了,导致应用失败,退回到默认状态。
- 配置文件被人为改过,或者被其他工具覆盖了。
- 网卡名称发生了变化,导致原来绑定的配置对不上新的接口名。
这里面每一类我都实际遇到过,后面会针对每一条给出具体的排查命令和修复方法。
1.2 别把“临时修改”当成“永久生效”
还有一个特别容易迷惑新手的点:你用ip addr add命令临时加上去的IP,重启就没了;你用ifconfig改的东西,重启也没了;甚至你用nmcli临时改的某些连接配置,如果没保存到连接配置文件里,重启同样会丢。
这就好比你在文本编辑器里输入了一堆内容但没按保存,关掉软件再打开,全没了。网络配置也是分“内存态”和“磁盘态”两层的。内存态是当前系统里正在运行的配置,磁盘态是配置文件中定义好的、重启后依然会生效的内容。排查问题前,先分清楚你改的是哪一层。
我自己在给一批机器批量改配置的时候,就吃过这个亏。当时图省事,直接写了个循环ssh进去,用ip命令加IP,但没写配置文件。机器跑了两周没事,突然一次计划内重启,所有手工加的IP全丢了,当时还以为是硬件出问题了,排查了半天才反应过来是自己偷懒没写配置文件。
1.3 云服务器场景的额外变数
如果你的Ubuntu跑在云环境里,比如各种VPS、云主机,丢网络配置还有一个非常常见的元凶:cloud-init。云镜像在首次启动时会通过网络获取元数据,然后生成对应的网络配置文件写入 /etc/netplan/。如果你手动改了配置,但cloud-init在下次启动时又跑了一遍,它可能会重新生成配置,把你改的东西覆盖掉。
这个情况我从Ubuntu 20.04和22.04的云镜像上都遇到过。表现特别明显:你在机器上手工改了 /etc/netplan/99-custom.yaml,也执行了netplan apply,一切都正常。但重启后,配置又回到原来的样子,看一下 /etc/netplan/ 目录,你的文件还在,但优先级更高的那个cloud-init生成的配置把效果给盖掉了。
2. 配置丢失的原因分层与自检:别急着改,先定位
2.1 第一层检查:YAML文件还在不在
接到“重启丢配置”这个问题,我建议的顺序是先看配置文件状态,而不是先改配置。很多你以为是“丢配置”的情况,其实是配置文件根本加载不进来。
先执行这条命令看一下当前netplan的配置情况:
netplan get这个命令会把你当前所有netplan配置合并后的结果直接打印出来,比一个个cat文件直观得多。如果你看到的配置和你预期的不一致,那说明问题出在加载层。
接着看目录里的文件情况:
ls -l /etc/netplan/正常情况下,这个目录下会有 .yaml 结尾的配置文件。Ubuntu对netplan文件名有要求,必须是 .yaml 后缀,文件名里不能有空格和特殊符号。之前我见过有人在编辑文件的时候把文件存成了.conf后缀,然后跑到论坛发帖说配置不生效,就是这个问题。
还要检查文件权限。netplan对配置文件权限有要求,特别是含密钥或敏感信息的文件,建议设成600。权限太松或者所有者不对,netplan在启动时可能会拒绝加载。一般建议:
sudo chmod 600 /etc/netplan/*.yaml2.2 第二层检查:是不是配置写错了但没发现
netplan的YAML语法对空格极其敏感,多一个空格、少一个缩进,应用的时候就是报错或者部分配置被忽略。最坑的是,netplan apply的时候如果只是“部分失败”,它不一定会弹一个巨大的错误框,而是默默跳过有问题的条目,只应用其余正常的配置。
我一再强调要先跑一遍:
sudo netplan generate这条命令只做语法级解析,不会实际改变系统网络。它会把YAML文件转换成后端配置文件,如果语法有问题,在这里就会报出来。我觉得这应该成为每次改配置后的肌肉记忆,像写代码前先跑一遍编译一样。
接下来再跑:
sudo netplan apply这条命令是真正把配置应用到这个系统上。apply执行完之后,用ip addr查看网卡信息,确认IP、网关、DNS是否都正常。如果apply之后正常,重启之后就丢了,那就说明问题不在YAML内容本身,而是在加载机制或者服务顺序上。
2.3 第三层检查:是不是被NetworkManager“截胡”了
这是Ubuntu桌面版用户最容易踩的坑。桌面版默认用NetworkManager作为后端渲染器,但如果你在YAML里写的内容生成的配置和NetworkManager的连接管理有冲突,就可能出现奇怪的问题。
判断当前系统用的是哪个渲染器,看一下YAML文件的内容就行:
cat /etc/netplan/*.yaml如果里面写着 renderer: NetworkManager,那说明netplan把配置交接给了NetworkManager来管理。这种模式下,NetworkManager自己有一套连接配置,它可能在你重启后会重置网卡状态,导致你以为配置丢了。
有一个很典型的场景:你人坐在一台Ubuntu桌面电脑前,手动改了IP,用netplan apply成功生效,但重启后NetworkManager把网卡重置为自动获取IP。这种情况我建议有两种处理方式:
方式一,把YAML里的NetworkManager这套配置完整删掉,改用systemd-networkd渲染器。
方式二,直接用nmcli来管理系统连接,不要同时用netplan和nmcli两套工具改同一个网卡,避免互相覆盖。
我自己在实际工作中更推荐方式一,因为服务器上本来就没有桌面环境,用不带图形界面的systemd-networkd更干净、更可控。当然你要是桌面版且有图形界面需求,用nmcli一条道走到黑也行,最怕的就是两套工具混合着用。
2.4 第四层检查:是不是网卡名变了
还有一类情况也比较隐蔽:你写配置的时候绑定的网卡名,在重启之后变了。这个在物理机上尤其常见,原因在于Linux的网络接口命名规则可能因为硬件探测顺序变化而改变。
比如机器上有多个网卡,之前你的内网网卡叫enp3s0,你在YAML文件里写的就是:
network: version: 2 ethernets: enp3s0: dhcp4: false addresses: - 192.168.1.100/24结果重启之后,因为PCI设备枚举顺序变了,网卡变成了enp4s0,原enp3s0配置对不上接口,自然就“丢”了。
排查方法是先用下面的命令看当前机器上真实的网卡名:
ip link show然后对比你YAML文件里写的是哪个名字。如果对不上,改YAML或者做一个稳定的interface命名规则,都能解决。
3. 实操修复全过程:从零搭一套重启不丢的配置
3.1 静态IP配置的标准写法
我拿最常见的场景来举例:一台Ubuntu 22.04服务器,需要把网卡配置成静态IP 192.168.1.100/24,网关192.168.1.1,DNS用223.5.5.5和114.114.114.114,并且保证重启后依然有效。
先备份原配置:
sudo cp /etc/netplan/01-netcfg.yaml /etc/netplan/01-netcfg.yaml.bak然后编辑配置文件。注意文件名不一定是01-netcfg.yaml,有些系统叫00-installer-config.yaml,有些叫50-cloud-init.yaml。具体文件名无所谓,关键是你放在/etc/netplan/目录下,并且配置内容正确。如果文件不存在,直接新建一个即可。
sudo vim /etc/netplan/01-netcfg.yaml写入以下内容:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: false dhcp6: false addresses: - 192.168.1.100/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: - 223.5.5.5 - 114.114.114.114写完之后,先做语法检查:
sudo netplan generate如果没有任何报错,再应用它:
sudo netplan apply然后验证:
ip addr show enp3s0 ip route show cat /etc/resolv.confip addr确认网卡上有192.168.1.100/24这个地址,ip route能看到default via 192.168.1.1这行,resolv.conf里能看到配置的DNS服务器。三步都对了,说明这套配置在内存层已经生效。
接下来是核心问题:重启之后会不会丢?如果要验证,直接reboot,然后重复上面三条验证命令。如果继续生效,说明配置文件已经被系统正常加载。
3.2 DHCP模式的正确写法
有些场景你不想用静态IP,比如公司内网有统一DHCP分配策略,你要的就是重启后自动获取IP且不丢。那配置更简单:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: true dhcp6: false注意,即使是最简单的配置,也不能把文件写得太随意。DHCP模式下的坑在于,有些DHCP服务器会下发租约,而DHCP租约过期或者网卡重启后重新请求,可能需要几秒钟。如果网络dns解析不到或者速度慢,不等于配置丢失,等一下就好。
3.3 让配置立刻恢复的兜底命令
如果你发现网卡当前状态是down或者没有IP,手头又要马上恢复网络,不用等重启系统,直接执行:
sudo netplan apply这条命令会重新读取/etc/netplan/下的所有配置文件,生成后端配置并应用。大多数情况下,如果你YAML文件本身没被破坏,执行完这一条,网络就回来了。
如果执行完还不行,再试这一套:
sudo systemctl restart systemd-networkd sudo systemctl restart NetworkManager你系统当前用哪个后端,就重启哪个。可以在/etc/netplan/的YAML文件里看renderer字段,也可以直接看服务状态:
systemctl status systemd-networkd systemctl status NetworkManager哪个服务在运行,就用哪个。
如果网卡处于down状态,手动拉起来:
sudo ip link set enp3s0 up拉到up之后再看IP分配状态。如果还是没有IP,说明配置文件加载有问题,回到上一步排查YAML。
3.4 cloud-init场景的“绝杀”处理
如果你是云服务器用户,并且确认是cloud-init在搞鬼,那除了修改netplan配置之外,还需要让cloud-init不要每次启动都覆盖你的配置。
处理方式有两种。第一种是比较温和的:检查/var/lib/cloud/instance/目录下有没有cloud-init生成的网络配置备份,然后修改/摘除对应的netplan配置文件,让cloud-init不再生成。但这种方案在不同云镜像上行为不一样,不是每次都灵。
第二种是直接在cloud-init配置里禁用网络配置管理。编辑:
vim /etc/cloud/cloud.cfg.d/99-fake_cloud.cfg写入:
network: config: disabled保存之后执行:
sudo cloud-init clean sudo netplan apply这个做法的逻辑很直接:让cloud-init在系统启动的时候不再干预网络配置。很多云厂商的Ubuntu镜像都适用。不过操作前建议先确认你当前机器的网络配置到底是谁生成的,别一上来就把cloud-init禁了,万一是其他机制在管网络,反倒弄巧成拙。
4. 常见问题与排查技巧实录
4.1 问题速查表
我把实际处理过程中最常遇到的问题整理成一个速查表,每一条都是踩过的坑或者同事踩过之后来问我的:
| 现象 | 大概率原因 | 排查命令或方法 | 解决方向 |
|---|---|---|---|
| 重启后静态IP变成自动获取 | NetworkManager接管了网卡 | grep -r renderer /etc/netplan/ | 改用networkd渲染器,或统一用nmcli管理 |
| 重启后IP完全消失 | YAML文件没被加载或格式错误 | sudo netplan generate | 修复语法、检查文件名和后缀 |
| 手动改的配置被覆盖回原样 | cloud-init重新生成配置 | ls /etc/netplan/ | 检查cloud-init配置,禁用网络干预 |
| 配置apply成功但重启后网卡名对不上 | 接口命名变化 | ip link show 对比YAML中的接口名 | 调整绑定网卡名,或用MAC地址绑定 |
| 配置没丢但dns解析失败 | DNS配置未生效或顺序错误 | cat /etc/resolv.conf | 检查nameservers字段,确认resolv.conf链接关系 |
| apply之后网络直接断了 | 配置中IP、网关、掩码计算错误 | ip addr / ip route show | 对照实际网段重写配置 |
4.2 排查思路:什么阶段看什么日志
系统出问题,第一件事就是看日志,网络配置也不例外。
如果问题是重启后立即出现,先在重启后的系统里执行:
journalctl -b 0 -u systemd-networkd --no-pager | tail -50这条命令会显示本次启动以来systemd-networkd的日志。重点关注有没有Error、Failed、Could not这样的关键词。如果使用了NetworkManager后端,则看:
journalctl -b 0 -u NetworkManager --no-pager | tail -50日志是定位问题的金钥匙,很多时候你看完日志就完全明白了,压根不需要瞎猜。
另外还有一个建议:排查之前自己先“冷静三秒”。我做运维早期,出问题就慌,各种命令乱敲,越弄越乱。后来养成习惯,遇到问题先打开日志,把所有log从头看一遍,再动手。用这种方法解决了不少看起来“玄学”的网络问题,包括好几次其他同事搞不定喊我过去看的。
4.3 一个我印象很深的实际案例
有一回,某内部项目的一台测试机器跑着Ubuntu 20.04,突然有一天管理员反馈说系统重启后网络不通了。远程连接已经是断的状态,只能让机房同事接上显示器和键盘,在本地敲命令排查。
我上去看了下 /etc/netplan/ 目录,里面有好几个YAML文件。其中一个是系统自带的00-installer-config.yaml,内容是DHCP配置;另一个是后来新增的99-custom.yaml,内容是静态IP。两者都生效,按照netplan的文件加载顺序,数字大的文件优先级更高,按道理静态IP应该能覆盖DHCP。
但问题在于,00-installer-config.yaml里面只写了dhcp4: true,没有明确写renderer。而99-custom.yaml里面写的是renderer: NetworkManager。结果系统启动后,NetworkManager接管了网卡,它按照自己的连接配置把网卡设成了DHCP,静态IP就没了。
处理起来其实很简单:把99-custom.yaml改掉,去掉renderer字段或者改成networkd,并把00-installer-config.yaml里多余的DHCP配置注释掉,统一成一套完整配置。
这案例给我的启发是:在Ubuntu上,多配置文件并存并不少见,但每一份文件之间也可能互相打架。遇到问题别只看单个文件,要把整个目录里的配置当成一个整体来分析。
4.4 如何避免一次性改动多台机器时出错
如果你手头有几十台Ubuntu机器,需要批量改静态IP,建议不要直接用ip命令临时去改。正确做法是准备一份标准的netplan YAML模板,把每台机器的IP单独填好,然后分发到对应的/etc/netplan/目录,最后逐台执行netplan apply。
批量操作之前,建议先在一台机器上测试完整流程。确认没问题了再推广到其他机器,别一次性铺开几十台,结果配置模板有硬编码错误,全网段翻车。这种事我见过不止一次,有一个同行就是批量改配置时把一个掩码少打了一位,结果几十台机器全部网络异常,最后只能一台一台手动改回来,工作量直接翻倍。
另外,批量修改前强烈建议先把所有机器的原配置备份拉一份到自己本机。万一改出问题,至少还有原始可回滚的文件。这个习惯在运维里属于基本操作,关键时候能救命。
5. 底层原理快问快答:把几个模糊概念彻底说清
5.1 netplan的apply和systemctl restart network系列
有些人会把netplan apply和老的service network restart混淆。在Ubuntu 18.04及以后,传统的/etc/init.d/networking重启方式依然存在,但netplan才是默认的管网络入口。
netplan apply做的事情是整个链路:读取YAML、生成后端配置(比如把配置写入/run/systemd/network/目录下的文件)、通知systemd-networkd重新加载、应用到实际接口。而老的service networking restart只是重启networking服务,本质上不经过netplan的YAML解析。
所以你在netplan体系下改配置文件,就得用netplan apply,不要指望service networking restart能正确加载新YAML。
5.2 为什么YAML文件这么“难伺候”
YAML本身不难,但它的缩进和符号规则对新手和一个粗心的老手来说都很容易出错。它不用花括号、不用分号,靠的是缩进表示层级,冒号后面必须有空格,列表项用短划线加空格。
netplan的YAML有两个特点:一是它对重复键非常敏感,同一个字段写了两次,直接报错;二是未知字段也会报错。这和其他很多只管“尽力解析”的配置文件不同,netplan要严格得多。
我给的建议是:不要手动去维护复杂YAML,能用模板就模板,能用工具哪怕是简单的脚本生成就生成。手写YAML多写几层嵌套很容易出错。有些编辑器装了YAML插件,可以高亮显示缩进和校验语法,用起来会稳不少。
5.3 DNS配置为什么“改了没反应”
很多人netplan里的nameservers写好了,apply也成功了,但dig解析出来的DNS还是之前那个。这是因为/ets/resolv.conf在很多Ubuntu系统里不是一个普通文件,而是一个软链接。
在systemd-networkd后端下,/etc/resolv.conf通常会链接到/run/systemd/resolve/stub-resolv.conf或者/usr/lib/systemd/resolv.conf。真正生效的DNS其实是netplan生成给systemd-resolved的那一套配置。你如果直接把/etc/resolv.conf改成普通文件,填了自定义DNS,系统一重启又会被覆盖。
如果你确实需要自定义全局DNS解析,最干净的方式还是在netplan里配置nameservers,并且确认resolv.conf保留为正确的符号链接。如果由于某些原因要手工管理resolv.conf,那就别让systemd-resolved接管,修改/etc/systemd/resolved.conf里面的DNS字段,或者干脆禁用systemd-resolved服务。不过第一种方式更符合Ubuntu当前的默认设计,也更不容易出问题。
6. 一些你没注意到但很实用的细节
6.1 多网卡场景下不要漏了路由配置
如果你机器上有多个网卡,比如一个内网网卡、一个外网网卡,并且都配置了静态IP,那路由表的配置就显得尤为重要。netplan里默认网关的配置要写在routes下面,不能简单写在gateway4这种老字段里(Ubuntu 20.04以后gateway4已经被废弃了,继续用会导致警告甚至配置不生效)。
多网卡的路由配置建议用一下这个格式:
network: version: 2 ethernets: enp3s0: dhcp4: false addresses: - 10.0.0.10/24 routes: - to: 10.0.0.0/24 via: 10.0.0.1 metric: 100 enp4s0: dhcp4: false addresses: - 192.168.1.10/24 routes: - to: default via: 192.168.1.1 metric: 10metric参数用来控制路由优先级,数字越小优先级越高。实战里有过一个场景,因为两个网卡都配了默认路由,导致流量从错误的网卡出去,明明网络看起来是通的,但外网就是访问不了。后来加上metric才恢复正常。
6.2 配置模板做好版本管理
我强烈建议把netplan配置模板纳入版本管理,不管你是用Git还是SVN,都要做到每一台机器的网络配置“可追溯、可回滚、可对比”。这不是小题大做,生产环境里网络配置改错导致的影响面比改错一行代码大得多,因为网络一断,可能连上服务器改回来的机会都没有。
我的做法是:在Git仓库里建一个deploy/netplan目录,按机器IP或者主机名分文件,每个文件对应一台服务器的网络配置。改之前先在仓库里改好、review、测试,再复制到服务器去应用。这套流程看起来笨重,实际省了我大量时间。
6.3 保留一套带外维护手段
最后多啰嗦一句:如果你在维护物理服务器或者公司内网的虚拟机,一定要保证有一个“出问题也能进系统”的通道。比如IPMI、带外管理卡、虚拟控制台、串口登录之一。因为网络配置这类操作,最容易把自己锁在门外。有一回我自己手滑写错网关,apply之后SSH直接断掉,好在机器有带外控制台,才能进去把配置改回来。要是没有带外通道,就得大半夜跑机房了,这种经历一次就长记性。
7. 关于这套排查方法,我的一些体会
我自己从被这个问题折磨过一轮之后,现在处理Ubuntu网络配置的思路变得非常固定:先看配置文件有没有被加载,再看配置内容有没有被正确应用,最后看有没有其他工具在“抢”网络管理权限。
把这套流程走完,绝大多数的“重启丢网络配置”问题都能定位到原因。它本质上是整个Ubuntu网络配置体系在你机器上的状态管理问题,而不是单纯某个命令没敲对。只要理解了netplan这一层架构,再遇到问题就不会慌。
最后再分享一个实用的小技巧:每次改完网络配置、确认没问题之后,可以顺手把当前生效的配置导出一份存到自己本机或文档库里。
netplan get > ~/netplan-backup-$(hostname)-$(date +%Y%m%d).yaml这样即使后来某天配置真的丢了,你随时可以对着存档恢复。我在维护一批Ubuntu节点时一直用这个习惯,好几次帮我在出问题后半小时内就完成了恢复。希望这篇内容能帮你少走一些弯路。