Ubuntu 24.04 LTS 原地升级 26.04 LTS:4 台 N100 节点实战踩坑与必查清单
本文最后更新于:2026年10月9日 晚上
前言
终于等来了国庆长假!宅在家折腾自己的 HomeLab、 K8s、 NAS 服务器集群的感觉真爽!这次长假真的是折腾了好多东西,感兴趣的读者请期待后续的爆更,等不及的话也可以直接看我的 repo - east4ming/homelab2 的 PR 和 Commits。
Homelab 里那 4 台 N100 小主机跑着 K3s + Rook Ceph,一直待在 Ubuntu 24.04 LTS(Noble Numbat)上。26.04 LTS(Resolute Raccoon)出来之后,手痒得不行 —— 毕竟 24.04 的支持周期眼看着一天天往前走,早升晚升都得升。
📝声明:
- 本文不是 “官方升级指南翻译”,是 4 台节点实打实滚了一遍之后的复盘
- 通用教程里那些
do-release-upgrade然后reboot就完事的说法,在带 Ceph 的集群上是不够用的
真正让我决定写这篇的,是升级完之后那一串 “看起来无关、其实一条链” 的故障:/etc/sysctl.conf 被删 → inotify 限制回退 → fwupd 每小时失败 → KubeVirt virt-handler CrashLoopBackOff;外加一个 Ceph OSD 卡在 down + out,根因居然是 mon Secret 里一个过期的 fsid。
这次升级为什么拖了这么久?
根据 Canonical 的官方发布节奏,Ubuntu 26.04 LTS 及其首个点版本 26.04.1 的发布时间如下,而 24.04 LTS 用户的升级通道确实延迟了一个多月。
📅 各版本发布时间
- Ubuntu 26.04 LTS (Resolute Raccoon):2026 年 4 月 23 日 正式发布。
- Ubuntu 26.04.1 LTS:2026 年 8 月 27 日 发布。作为首个点版本,它整合了自 4 月初始发布以来的安全更新和错误修复。
- 24.04 LTS → 26.04.1 LTS 升级通道:2026 年 9 月 29 日 正式启用。国庆放假刚好赶上,完美!
⏳ 升级延迟的原因
尽管 26.04.1 在 8 月底发布,但 Canonical 并未立即为 24.04 LTS 用户开启自动升级。从 8 月 27 日到 9 月 29 日,升级通道延迟了约 33 天。
这种延迟是 Canonical 为确保升级稳定性而采取的标准策略,具体原因有以下几点:
-
等待首个点版本 (Point Release):按照 Ubuntu 的长期支持(LTS)策略,从上一个 LTS 版本(如 24.04)到新 LTS 版本(如 26.04)的自动升级路径,通常不会在初始版本发布时立即开启,而是会等到第一个点版本(即 26.04.1)发布后。这为 Canonical 留出了数月时间,用以修复初始版本中发现的严重问题,确保跨版本升级的可靠性。
-
额外的关键回迁 (Backports):这是导致本次升级通道没有在 26.04.1 发布日立即开启的直接原因。Canonical 的工程师 Oliver Reiche 在邮件列表中解释,他们需要在开启自动升级前,部署一些额外的 “回迁” 修复。这些修复主要针对
rust-coreutils这个用 Rust 重写的核心系统工具集,旨在解决其近期版本中出现的 “回归”(即之前正常的功能被破坏)问题。核心系统工具的稳定性至关重要,因此 Canonical 选择先修复这些潜在风险,再向广大 24.04 用户推送升级。 -
分阶段推送:即使在升级通道正式启用后,Canonical 也会在几天内逐步向用户推送升级通知,以避免服务器过载并允许早期用户反馈问题。
总的来说,这次延迟是技术性的,且以稳定性为首要目标。对于生产环境而言,等待官方推荐的升级路径是更为稳妥的选择,因为 Ubuntu 24.04 LTS 的标准安全维护将持续到 2029 年 5 月,用户并不需要急于升级。
升级路径:别想跳级
先把路径说清楚,这块没有花活:
| 当前版本 | 能否直接升 26.04 LTS | 说明 |
|---|---|---|
| 24.04 LTS | ✅ 可以 | 24.04 是 26.04 的直属升级基线,一步到位 |
| 22.04 / 20.04 | ❌ 不行 | 必须先升到 24.04 LTS,再升 26.04 |
| 25.10 | ✅ 可以 | 非 LTS 走正常升级通道 |
26.04 LTS 支持到 2031-04,也就是说这 4 台节点未来 5 年可以不用再动系统大版本,这点对 Homelab 很重要。
升级通道方面,do-release-upgrade 只在 Prompt=lts 时才提供 LTS → LTS 升级。如果它还是告诉你 “没有可用的新版本”(比如首个 point release 还没进常规通道),那就用:
1 | |
📝Notes:
-d是走 devel 通道,会给你还没正式进入常规升级通道的版本。自己家里折腾无所谓,生产环境请等 point release。
升级前:把能保护的东西先保护住
核心思路一句话:节点本身可以丢,etcd 和集群数据不能丢。 配置全在 Ansible + GitOps 仓库里,节点重装都行;但 etcd 快照和 Ceph 数据没有第二份。
集群侧我做了三件事:
1 | |
节点侧,先把 24.04 升到最新并重启一次,再开始跨版本升级。升级顺序是逐台滚动,先 worker,后 control-plane,一台一台来 —— 每台等节点 Ready、Pod 稳定之后,再动下一台。
通用升级步骤
1 | |
⚠️ 先别急着 apt autoremove --purge
这条必须单独拎出来说,因为它和通用教程的建议是反的。
本仓库的节点上,linux-firmware 的依赖关系是被刻意改造过的 —— 装的是一个空壳 linux-firmware-minimal(这又是另一个故事了,敬请期待)。这意味着你随手来一发 apt autoremove --purge,有相当的概率把 i915 / Wi-Fi 固件一起带走,然后就是重装或者插网线的故事。
真要做清理,先确认保留的固件包已经被标记为 manual:
1 | |
升级后必查清单
下面是升级完之后实际出现的问题,不是 “可能会遇到”。我按严重程度排了序。
1️⃣ /etc/sysctl.conf 被直接删除(最坑)
Ubuntu 26.04 的 procps 把 /etc/sysctl.conf 标记成了 remove-on-upgrade。升级时直接删掉,哪怕你改过、哪怕你选了 “保留当前版本”。
后果是任何把内核参数写进这个文件的 Ansible 任务,升级后全部静默失效:
| 参数 | 升级前 | 升级后(回退到默认) | 影响 |
|---|---|---|---|
fs.inotify.max_user_instances |
8192 | 128 | fwupd.service / fwupd-refresh.service 每小时失败 |
net.ipv6.conf.all.forwarding |
1 | 0 | IPv6 转发失效 |
net.ipv6.conf.all.accept_ra |
2 | 1 | RA 接受行为变化 |
inotify 这条还牵出了一个连锁反应:KubeVirt 的 virt-handler 在 inotify 实例被耗尽的节点上启动阶段就 fatal 退出,表现为 CrashLoopBackOff,日志里是 Failed to create an inotify watcher。
正确姿势:参数落到 /etc/sysctl.d/ 下的独立文件,比如 90-homelab-prerequisites.conf。修好之后把 CrashLoop 的 virt-handler Pod 删掉,它自己就起来了。
📝Notes: 别去
sysctl.conf里 “补回来”,升级一次删一次。/etc/sysctl.d/才是正路。
2️⃣ 第三方 apt 源被清空成注释
do-release-upgrade 无法把第三方的一行式 .list 迁移成 deb822 格式的 .sources。它的处理方式是:把原文件清空成一行注释,原内容挪到同名的 .disabled。
本次 Tailscale 源就是这么没的,而且升级工具顺手把 tailscale 判成了 “废弃包”。
恢复时注意 suite 要换成新代号 resolute,并且先确认上游确实发布了该 suite—— 不然 apt update 会直接报错。
3️⃣ logrotate 因重复 conffile 整体失败
选择 “保留当前版本” 之后,release 升级删掉的 conffile 会被留下,于是两个包各留一份、glob 又相同,logrotate 判重复然后整体失败:
1 | |
这是 Launchpad #2152107。处理方式很简单:把 /etc/logrotate.d/cloud-init 改名加 .disabled(logrotate 会忽略这个后缀)。
4️⃣ netplan gateway4 弃用告警
netplan.io 1.2 仍然接受 gateway4,但每次 netplan generate 都会告警:
1 | |
新装机模板我已经改成 routes: 了。但已经在跑、网络正常的节点,不要为了消这个警告去改 cloud-init 生成的 netplan—— 收益为零,风险不小。
5️⃣ 集群组件逐项确认 + 一个 Ceph OSD down + out
集群侧我逐项过了一遍:systemctl --failed 期望为空、k3s 状态、节点全 Ready、非 Running / Completed 的 Pod、ceph -s、KubeVirt virt-handler。
结果 n100-cheshi-0 的 osd.1 一直 down + out。具体修复见上一篇文章。
升级交互项怎么选
顺手记一下我这次的选择,供参考:
- 是否继续:
y - 自动重启服务:Yes(选 No 的话每个服务都要单独确认,而且很容易漏)
- 本地修改过的配置文件:保守选 “保留当前版本”,但必须逐个 diff
- Remove obsolete packages:
y
4 台节点的升级日志都在 /var/log/dist-upgrade/(apt-term.log、main.log),排查遗留问题时这是第一手证据。
IaC 侧要同步的适配点
具体代码见:https://github.com/east4ming/homelab2/commit/e7044ced769a43cc2d28fa5bd7c98c15a729574d
节点可丢弃的前提是仓库跟得上。本次需要同步的:
pxe_server/defaults/main.yml:ISO 与 netboot.xyz squash 资源的 tag / 校验和ubuntu.ipxe.j2:新增resolute菜单项与:resolute_amd64/:resolute_arm64分支user-data.j2:libpcre3/libpcre3-dev在 26.04 已移除(PCRE1 被放弃);dnsutils过渡包也没了,改用bind9-dnsutils—— 不改这里,全新 PXE 装机在packages:阶段就会失败;netplangateway4→routesprerequisites/tasks/main.yml:sysctl 落到/etc/sysctl.d/scripts/firmware-slim与文档里的 24.04 版本描述
总结
跨 LTS 升级这件事,通用教程讲的是 “怎么把系统升上去”,而真正花时间的部分在 “升上去之后集群还活着吗”。这些检查里,第 1 项和是我觉得最值得单独记一笔的:一个是被静默删除的配置文件引发的故障链,属于 “不看日志根本想不到” 的类型。
📝Notes: 结论其实很朴素 —— 节点可以丢,数据不能丢。所以升级前 etcd 快照和
ceph -s存档是底线动作,升级后逐项确认比 “看起来没报错” 可靠得多。
长江后浪推前浪,一代更比一代强。系统版本会更替,把该留的证据留住、把该落 /etc/sysctl.d/ 的参数落对位置,就够了。