首页 游戏 软件 排行 专题

云服务器换内核版本,我漏了dkms这一步网卡就失联

来源: 本站整理 日期:2026/11/11 9:21:34

去年年底有一台跑 PHP 项目的云服务器,我给它把内核从 5.10 换到了 6.1。当时的想法很简单:6.1 的网络栈更稳,官方安全补丁也多,顺手升一下不亏。结果重启完机器就失联了控制台里能进系统,但网卡就是起不来,业务中断了将近四十分钟。那四十分钟里我才真正搞明白,云服务器上换内核这件事,最难的不是编译,而是那些"编译的时候根本不会报错"的东西。

如果你手上的机器需要自己掌控内核版本,或者正在琢磨给 VPS / 独立服务器做一次底层升级,先看看这几家的硬件规格和技术说明再动手:spartanhost(全球云服务器,VPS 与独立服务器)升级内核前先把机器的网卡型号、虚拟化类型和 RAID 卡型号查清楚,比在编译阶段返工要省事得多。

一、先分清你要的是"发行版内核包升级"还是"源码编译"

这两件事的操作路径完全不同,踩坑点也不一样。发行版包升级就是跑 apt upgrade 或者 yum update kernel,由官方仓库把预编译好的内核包、配套模块和 initramfs 一起送到你机器上;源码编译则是自己下载内核源码,配一份 config,跑 make -j、make modules_install、make install,最后还要手动生成 initramfs 和改引导项。

绝大多数人一开始会低估后者。云厂商的镜像(AlmaLinux、Rocky、Ubuntu LTS 这些)都做了定制,厂商的监控agent、备份agent、云盘挂载脚本、甚至某些安全加固策略都跟发行版那个特定内核版本绑死了。你用源码编译换掉它,agent 可能直接不工作,云盘可能挂不上,网络可能因为模块路径变化而失联。所以在动手之前,先问自己两个问题:

第一,我到底是为了修什么?是为了某个 CVE、为了某个新硬件的驱动、还是只是"听说新版本快"?如果只是后者,我劝你省下这个周末,因为在大多数场景下,瓶颈根本不在内核。第二,这台机器上有没有必须由特定内核版本承载的东西,比如定制内核模块、闭源网卡驱动、或者某个只支持旧内核的 agent。

二、虚拟化环境下的第一个坑:dkms 不会自动帮你编译新内核的模块

这是我在那台机器上真正卡住的地方。dkms 这个机制的作用是,当内核版本变化时,自动重新编译那些不在内核源码树里的第三方模块闭源网卡驱动、RAID 卡驱动、zfs 之类。它的工作方式很简单:内核版本一变,它就去找对应的驱动源码,重新编译一遍,把 .ko 文件塞到 /lib/modules/新版本号/ 下面。

但问题是,它需要能拿到驱动源码。而虚拟化环境里,virtio 网卡驱动是内核自带的,压力倒是不大;真正麻烦的是宿主机上透传下来的那些东西SR-IOV 网卡的 ixgbevf、ipu6 驱动的 i40e、还有各种半虚拟化 SCSI 卡。我那台机器用的是某款老网卡,厂商驱动在旧内核下是 dkms 装的,升到 6.1 之后 dkms 自动编译失败了,错误日志里写的是缺少某个头文件,但不影响安装过程包装完了,模块没生成。

坑在于,这个失败在重启之前完全不影响你。apt 那边显示一切正常,grub 里也能看到新内核的启动项,uname -r 在当前会话里甚至还显示旧版本,一切看起来都对。只有真正重启之后才会暴露:initramfs 里找不到对应模块,系统找不到 rootfs,直接卡在 initramfs 阶段。如果你的机器是远程的,那就只能靠 IPMI 或者云厂商的 VNC 控制台进去了。

所以升级前必须做的第一件事是:dkms status,把现有模块列出来,逐个确认它们在新内核下编译成功。升级后再执行一次,确认状态还是 OK。如果某个模块不支持新内核,那就得考虑回到旧内核,或者做 KABI(内核 ABI 稳定)兼容处理。

三、第二个坑:GRUB 默认启动项没改,重启还是跑老内核

这个坑比想象中常见,而且它不会造成故障,所以更隐蔽。安装新内核包之后,/boot 下会同时存在多个版本的 vmlinuz 和 initrd.img,GRUB 的启动菜单里也会多出新的条目,但默认选中的那个仍然是旧内核。

很多人装完就 reboot,结果重启完发现 uname -r 还是老版本,kernel-devel 这些开发包倒是升上去了,就很困惑。检查 GRUB 引导配置的时候有个细节:CentOS 系是 grub2-editenv list 看 saved_entry,Debian 系是 grep menuentry /boot/grub/grub.cfg 找 default 那一行,还要确认 GRUB_TIMEOUT 设成了 5 以上,不然菜单一闪而过你根本选不了。另外很多云镜像的 GRUB 菜单是隐藏的,得在启动时按住 Shift 或者 Esc 才能看到条目。

还有一种更隐蔽的情况:你以为重启进新内核了,其实进了新内核,但旧内核的模块还在 /lib/modules/ 下面占着,空间一直涨。这时候用 uname -r 和 ls /lib/modules/ 对一下就知道哪些是历史遗留。清理旧内核的时候一定要确认当前运行的不是它,否则 rm -rf 下去直接系统起不来。

四、第三个坑:initramfs 里没打进去关键模块

initramfs 是内核启动最初阶段加载的那个"临时根文件系统",它负责挂载真正的根分区、加载存储驱动、拉起 LVM 或者 RAID 组,然后才把控制权交给系统的 init。你的根盘如果是 RAID、如果是 LVM、如果是 iSCSI 或者 FCoE 目标存储,那么对应的模块必须被打进 initramfs,否则内核起不来。

大多数发行版的 dracut 会自动探测,但源码编译的时候如果你自己 make install,这一步经常被漏掉,或者生成的 initramfs 是用了一个精简 profile。验证方法很直接:lsinitrd /boot/initramfs-新版本.img | grep 模块名,或者 dracut --print-cmodules /boot/initramfs-新版本.img。老一点的机器(CentOS 7 时代)还会因为 dracut 版本老、fstab 里写了 UUID 但新内核识别慢而翻车。

五、第四个坑:Secure Boot 和模块签名

开了 Secure Boot 的机器上,未经签名的内核和模块一律加载不了。发行版仓库里的内核都签好了,自己源码编译的就得自己搞定签名这摊事:生成密钥、把密钥导入 UEFI 的 MOK 列表、用 sbsign 签内核、用 certutil -S 签模块。这套流程在实体机上麻烦,但在大量云厂商的实例上反而不存在这个问题它们用的是自己的引导方案。真正要注意的是那种"裸金属"或者自己组装的机器,BIOS 里那个 Secure Boot 开关要先确认状态。

六、第五个坑:升上去了,业务行为却变了

内核升级从来不只是换个版本号。6.x 相比 5.10,有一批默认行为和参数变了:cgroup v2 逐步成为默认、内存回收策略调整、部分内核参数默认值变化、BPF 相关的行为也有差异。很多服务你以为它能跑,升级后可能莫名其妙 OOM 或者变慢。这类问题不表现成"起不来",而是"跑起来怪怪的",排查起来更耗人。

所以我在自己的一套检查清单里加了这么一条:升级完成后,先在新内核下跑一轮完整的业务冒烟测试,再把流量切过来。我个人的做法是保留旧内核至少两周,观察期内任何异常都能通过 GRUB 单次启动回到旧版本。

七、回滚方案必须提前准备好

我出事的那个上午,如果提前配好了回滚路径,四十分钟能缩到五分钟。常用的几种回滚方式:一是 GRUB 里选 Advanced options 进旧内核;二是 grub-reboot 设置下次启动的单次入口(grub2-reboot 在 CentOS 系上),这个对远程机器特别有用,因为不需要交互;三是把新内核的 initramfs 直接改名,让它引导失败回落到旧内核;四是最保险的,直接有云厂商的快照或者自己做的磁盘镜像。

我的那次是用云厂商控制台的 VNC 进去,在 GRUB 菜单里手动选了旧内核。之后我在所有要升内核的机器上都加了两道保险:一是升级前做快照,二是 grub-reboot 加一条定时任务,如果重启后 5 分钟内没有健康检查通过,就自动用旧内核再启一次。这个自动化后来救了我另外一台机器。

八、我的升级前检查清单

把这些逐项打勾,踩坑概率会低很多:

1. uname -r 记录当前版本,dkms status 列出所有外部模块;
2. 确认目标内核在仓库里有对应的 kernel-devel 和 headers 包;
3. 确认 initramfs 里包含了根盘、RAID、LVM 相关模块;
4. 记录 GRUB 默认启动项,并确认 grub2-mkconfig 之后的配置没被改坏;
5. 确认 Secure Boot 状态和模块签名要求;
6. 做磁盘快照;
7. 准备回滚命令,并写进定时任务做自动兜底;
8. 选低峰期操作,提前通知相关的人。

最后再补一句:内核升级本身不是"高深操作",但它是一个"牵一发动全身"的操作。它同时踩在引导、模块、驱动、参数、业务验证这五条链上,任何一环断了你都无法通过 SSH 远程自救你的网络模块本身就是被改动的对象之一。所以我会建议第一次升级一定选带 IPMI 或者带 VNC 的机器练手,别拿唯一的生产机开刀。

运维工程师在服务器控制台前执行内核升级命令

像上面这种场景,我更倾向于在备用的低配机器上先把整条流程跑一遍。真正动手前把机器规格、网卡型号这些信息摸清楚,比出事了再查要省事得多。如果是打算长期自己维护内核版本、装定制模块的那种机器,可以看看fiberstate(企业级裸机、托管与 IP 传输)这类支持独服和机房托管的方案,独享物理机的情况下你才有完整的 root 权限和引导控制权,升级内核、回滚引导项这些操作才谈得上自由。

重启后网卡指示灯熄灭的服务器背板特写

网卡起不来的原因往往不是网络配置,而是对应的内核模块压根没被编译出来。这时候再回头翻配置文件是没用的,得回到编译阶段。

内核模块与驱动文件关系的结构示意图

dkms 的作用就是在内核版本变化时自动补上外部模块的编译,但它需要驱动源码,也需要对应的开发包。任何一个环节缺失,结果都是"包装上了,模块没生成",而且不重启根本看不出来。

通过回滚旧内核恢复业务运行的机房场景

保留旧内核并且配置好自动回滚,是我觉得最值得做的一步。它花不了十分钟,但能把一次四十分钟的业务中断变成一次几乎无感的重启。

玩家留言 跟帖评论
查看更多评论
相关文章
猜你喜欢
同类下载