资讯详情

资讯详情

Ubuntu重启后丢失网络配置?详解netplan排查与永久修复方案

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.1DNS用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节点时一直用这个习惯好几次帮我在出问题后半小时内就完成了恢复。希望这篇内容能帮你少走一些弯路。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →