ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CentOS 7/RHEL 7内核升级实战:ELRepo安装与grubby切换指南

CentOS 7/RHEL 7内核升级实战:ELRepo安装与grubby切换指南

1. 为什么 CentOS 7 / RHEL 7 用户需要认真考虑“换内核”

CentOS 7 / RHEL 7 系列默认自带的内核是 3.10 分支,这个版本在当年足够稳,但拿到今天来看,已经非常老旧了。3.10 内核诞生于 2013 年前后,它对现代硬件(NVMe 固态、新网卡、新显卡、PPS 时钟同步设备)的兼容性非常有限,对新文件系统特性(比如更高性能的整理策略、更完整的 Btrfs 修复能力)支持也比较弱。更关键的是,老内核漏洞积累很多,虽然官方有安全补丁,但很多功能性问题并不会因为打补丁而改善。

“换内核”这件事,很多运维同学一听就觉得慌:系统跑得好好的,没事动内核干嘛?万一起不来,机器全完。这个担心合理,但我们可以用一套成熟、可回滚、可管理的流程,把风险控制到最低。这套流程的核心思路就八个字:不动默认启动项,留好回滚路径。

实际操作中,我们不是去“删除”旧内核,而是先让新内核和旧内核并存。安装好之后,编辑默认启动项指向新内核,重启验证。如果一切正常,再把旧内核清理掉,释放磁盘空间。这个流程里,旧内核一直在硬盘上留存,相当于给自己留了一张安全网。

这篇文章就来完整走一遍:怎么换源、怎么安装新内核、怎么在 GRUB 里切换默认启动项、怎么验证新内核生效、怎么安全删除旧内核,以及我在生产环境里踩过的一些坑。整套操作适用于 CentOS 7 和 RHEL 7,网上那些“默认内核太老”的机器基本都能用这套思路解决。

适合读者:用 CentOS 7 / RHEL 7 跑服务、跑虚拟化、跑数据库,但感觉内核太老、硬件或性能受限的同学。有一定的 Linux 基础就行,不需要对内核编译有深入了解。VPS、物理机、虚拟机都能操作,唯一建议是在操作前确保自己有控制台或 VNC,别把远程 SSH 当唯一通道。

2. 动手前先干三件事:评估现状、留出空间、想好回滚策略

2.1 先搞清楚机器当前在用什么内核

任何内核升级流程,第一步永远不是“装”,而是“看清楚现状”。我在处理类似需求时,通常会一次性收集四类信息:

# 当前内核版本 uname -r # 当前系统大版本 cat /etc/redhat-release # 当前 GRUB 默认启动项,注意看带内核版本号的那个 grubby --default-kernel # 机器上有哪些已安装的内核 rpm rpm -qa | grep ^kernel

第一和第二条用于判断现状,第三和第四用于确认应用启动项的位置。很多新手栽在这:明明看到新内核装上了,重启后却还是旧内核,原因就是 GRUB 默认项是旧的,或者新内核条目排在菜单最下面。

第二步要顺带看一眼/boot分区剩余空间。内核 vmlinuz 文件本身不算大,但加上 initramfs、System.map、config 这些配套文件,每个内核版本大约会占 150MB 到 300MB。如果/boot分区只有 200MB 可用空间,装一个新内核可能就会导致空间写满,进而让grub2-mkconfig生成配置文件失败。建议在操作前把空间余量确认好:

df -h /boot

如果你用的是 LVM 布局,/boot一般独立分区;如果是云镜像,情况可能不同。空间不足时,先把旧的、明显不用的内核清理掉再继续,但清理动作要等到新内核验证成功之后做,这里不要顺序颠倒。

2.2 升级前必做的备份工作

内核升级本质上是替换系统最底层的核心组件。虽然我们走的是“安装新、切换、验证、清理旧”四步流程,风险已经在可控范围,但备份仍然是职业道德。不同场景的备份策略不一样:

  • 虚拟机和云主机:最省事的方式是打一个快照。如果云平台支持自动快照,建议操作前打一份,整个操作完成并稳定运行几天后悔删快照。
  • 物理机:没有快照可用,就备份/boot、/etc里与 GRUB 相关的配置。核心是grub.cfg,但更好的做法是直接把grub.cfg、grubenv完整复制到一个安全目录:
mkdir -p /root/boot-backup cp -a /boot/grub2/grub.cfg /root/boot-backup/ cp -a /boot/grub2/grubenv /root/boot-backup/

这样如果后续 GRUB 配置写坏了,可以直接手动恢复文件,再重新生成一次配置。

  • 如果是生产数据库、核心业务机,操作前看一下当前内核版本对应的 initramfs 是否完好,顺手记录一下旧内核的版本号。这样就算切换后遇到问题,也能快速定位回滚内核。

2.3 内核来源选型:kernel-lt 还是 kernel-ml?

CentOS 7 默认仓库里没有新内核可用,因为发行版的稳定策略决定它不会轻易滚动升级内核版本。我们需要借助第三方仓库,目前最常用的是 ELRepo。

许多文章会直接让大家装kernel-ml(mainline 主线版),这个版本内核版本号很新,功能也是最新的,但它的定位是“尝鲜”。生产环境我更推荐kernel-lt(long term support 长期支持版),它的版本号可能比kernel-ml低,但它维护周期长、更新节奏更稳妥,和新硬件驱动的兼容性经过更多回归测试。

这里用一个表格把两者的区别梳理一下:

对比项kernel-mlkernel-lt
版本定位主线最新版,快速跟进上游长期维护分支,版本推进保守
内核版本号通常较高当前长期维护版本,比新版本略低
更新频率频繁,新特性第一时间进入相对低频,以修复和安全更新为主
适用场景需要体验新硬件支持、新特性生产环境求稳,兼容新硬件的同时尽量少折腾
安全引导兼容性部分版本未签名,可能需要关闭安全启动签名情况以官方发布为准

我第一次给生产服务器换内核,选的是当时最新的kernel-ml,结果三天之内收到了它的一个小版本更新,更新完重启一次,虽然没出问题,但那种无谓的运维压力和隐忧,我觉得没必要。后来我学乖了,稳定环境一律kernel-lt,只有测试机才敢用kernel-ml。

实际选型时还应该结合自己的业务需求,比如如果你恰好需要一块较新网卡的驱动支持,而主线和长期支持版之间差异较大,就得具体看驱动版本。

3. 配置 ELRepo 仓库并安装新内核

3.1 安装并导入 ELRepo 仓库

ELRepo 是一个面向 RHEL 系发行版的第三方软件仓库,重点提供内核、驱动、文件系统相关的长期支持包和主线包。它的使用流程非常简单:先导入 GPG 密钥,再安装仓库 rpm,最后通过 yum 安装我们需要的 kernel 包。

# 导入仓库官方 GPG 密钥 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org # 安装 elrepo-release rpm(版本号以官方页面为准,通常为 7.0-x 形式) rpm -Uvh https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm

注意,这个安装动作只是把 yum 仓库配置文件和公钥装进系统,它不会动系统已有的内核。装好之后可以用下面命令确认仓库状态:

yum repolist | grep elrepo

你应该会看到elrepo和elrepo-kernel两行。如果只看到elrepo而没看到elrepo-kernel,说明仓库配置里子仓库没有启用,这时需要手动检查/etc/yum.repos.d/elrepo.repo文件里的配置,确认elrepo-kernel分区的enabled是否为 1。

提示:如果你所在的网络环境访问 CentOS 官方源较慢,或者直接访问 ELRepo 官方源超时,建议先配置好国内可用的 yum 镜像源,再执行上述命令。但注意镜像源的地址要以你实际环境中稳定可达的为准,不要随意照抄网络上的配置。

3.2 安装 kernel-lt

仓库配置没问题之后,开始安装新内核:

yum --enablerepo=elrepo-kernel install kernel-lt

这条命令会从elrepo-kernel仓库拉取kernel-lt包并安装。注意,安装完成后它会自动生成/boot/vmlinuz-版本号、/boot/initramfs-版本号.img等文件,同时会更新 GRUB 菜单配置,把新内核追加到条目列表,但它不会自动修改默认启动项。

安装完成后,先验证文件是否齐全:

ls -lh /boot/vmlinuz-* /boot/initramfs-* /boot/System.map-*

正常情况下新内核版本号对应的几个文件都会出现。别急着重启,下一步手动指定默认启动项。

3.3 依赖问题与常见异常

有一些机器在安装中新版本内核时会出现依赖冲突,比如file工具版本过老、内核头文件与开发工具链不匹配。遇到这种输出,先别慌,逐步排查:

# 查看与内核相关的依赖情况 yum deplist kernel-lt

如果提示缺少某个库或依赖包,一般思路是先把系统基础工具链更新到仓库里可用的最新版,再回来重试:

yum update file elfutils-libelf yum --enablerepo=elrepo-kernel install kernel-lt

另外,如果你是 RHEL 7 且订阅状态异常,yum 可能会拒绝更新。这个场景下需要先确认订阅服务和仓库状态,否则ELRepo即使安装了,也可能报“无法解析依赖”的错误。

4. 切换默认内核:用 grubby 而不是手动改配置文件

4.1 grubby 是什么,为什么用它

CentOS 7 / RHEL 7 默认使用 GRUB2 引导,传统手动编辑/etc/default/grub可以设置GRUB_DEFAULT,但不够直接,尤其当系统里有多个内核条目时,编号非常容易算错。更准确的做法是用grubby工具,它直接面向内核版本号操作,不关心菜单顺序和 grub.cfg 里的具体行号。

先列出现有启动项的内核列表:

grubby --info=ALL | grep -E "^kernel=\"|^index="

这里会输出每个启动项对应的内核路径和索引号。然后直接以内核文件名作为目标来设置默认项:

# 假设新内核版本为 5.4.xxx(以实际安装为准) grubby --set-default /boot/vmlinuz-5.4.xxx

使用文件名而不是索引号的优势是:不管以后 GRUB 菜单怎么加条目,只要内核文件还在,命令就不会误指向别的项。这个习惯我从实践里总结出来,强烈推荐。

设置完默认内核后,执行下面命令让 GRUB 配置重新生成,并确认默认项:

# 生成新 grub.cfg grub2-mkconfig -o /boot/grub2/grub.cfg # 查看当前默认内核 grubby --default-kernel

输出应该是/boot/vmlinuz-5.4.xxx这样的路径。

如果你用的是 UEFI 引导,部分机器上的配置文件路径是/boot/efi/EFI/centos/grub.cfg,生成命令稍有不同:

grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

怎么判断自己是 UEFI 还是 BIOS?很简单:

[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS

注意 UEFI 机器如果之前配置过多个引导项,务必确认默认项路径选对了,否则重启后会进入 UEFI 固件设置界面而不是系统。

4.2 重启前的最后检查

很多人在这个环节漏了一步:没有生成新的 initramfs 就重启。虽然安装 rpm 包时通常会触发dracut自动生成 initramfs,但稳妥起见还是手动生成一次,尤其是你遇到过多网卡、多磁盘、特殊文件系统这些需要额外驱动的场景。

# 手动生成对应内核的 initramfs dracut -f /boot/initramfs-5.4.xxx.img 5.4.xxx

这一步会在/boot下生成一份全新的初始 RAM 磁盘镜像,确保启动时能加载到磁盘控制器驱动、文件系统驱动等关键模块。如果你跳过它,理论上多数机器也能启动,但如果恰好你的根文件系统是很老或特殊的环境,可能会卡在开机阶段的switchroot错误。

重启前的最后检查清单:

  • grubby --default-kernel指向的是新内核路径
  • /boot空间充足
  • 已生成新内核的 initramfs
  • 手上有服务器控制台/VNC 权限
  • 已经拍摄快照或备份关键配置

确认无误后重启:

reboot

4.3 重启后验证新内核是否真的生效

很多人重启完就急着看uname -r,但你看到的版本号是多少,取决于是否真的进入了新内核。正确的验证命令:

uname -r

如果输出是你安装的新版本号,说明默认启动项生效。如果还是旧版本号,说明 grubby 设置没有生效,或者重启时你手动选择了旧项,又或者是启动项配置指向存在问题。另外别忘了一条命令:

uptime

uptime输出会包含系统启动时间,确认它是你本次重启的时间点,避免误以为切到了新内核其实是从未重启过,这个低级错误我见过不只一次。

更细致的验证是:

cat /proc/version cat /proc/cmdline

前者展示内核编译版本和编译工具链,后者展示实际启动时的内核命令行参数。如果你之前调整过 console、quiet、crashkernel 这些参数,此时检查真实启动参数是否和预期一致。

5. 关于旧内核:清理时机、清理方法与保留策略

5.1 新内核验证稳定之前,坚决不删旧内核

我把这条单独拿出来写,是因为见过太多同学新内核跑了一天没问题,就急着把旧内核删了,结果下一个业务高峰期遇到诡异 bug,想回滚已经没得回。这里的经验是:新内核至少要稳定运行一周以上,且没有出现性能回退、驱动异常、应用兼容性问题,才考虑清理旧内核。如果这是核心业务服务器,我会保留旧内核至少一个月。

清理旧内核其实非常简单:

# 先列出所有已安装的内核 rpm -qa | grep ^kernel # 删除指定旧版本(版本号根据上面列表替换) yum remove kernel-3.10.0-1160.el7.x86_64

删除完成后,内核相关的文件会从/boot移除,GRUB 菜单里的对应项也会消失。但这里有两个细节要注意:

  • 不要手动直接rm删除/boot/vmlinuz-*,要用 yum/rpm 机制删,否则 rpm 数据库里的记录和文件系统状态不一致,后续升级或清理会报错。
  • 删除旧内核时,如果它是当前运行的内核,rpm 会拒绝执行。所以清理动作只会在新内核下进行。

5.2 用 package-cleanup 自动保留指定数量内核

如果你不喜欢手动一个个删,可以装yum-utils后用自动清理:

yum install -y yum-utils package-cleanup --oldkernels --count=2

--count=2的意思是保留最近两个内核版本,其余旧版本一并清掉。这个命令比我手动删要安全,它会自动跳过当前正在运行的内核,并按照 rpm 数据库的记录逐个清理。

很多云厂商预置的镜像里已经装了yum-utils,如果没有就装一下,几十秒的事。推荐把“保留最近两个内核”作为统一策略写进运维文档。

5.3 清理后的 GRUB 恢复操作

有时你删除了旧内核,重启后发现 GRUB 菜单里残留了旧的启动条目,这通常是因为 grub.cfg 没有重新生成。删内核后执行一遍:

grub2-mkconfig -o /boot/grub2/grub.cfg

如果是 UEFI 机器,参照前面的路径。同时把默认项再确认一次,防止 grub2-mkconfig 把默认项重置为第一项。

6. 常见问题和坑:我遇到过的与值得警惕的

6.1 重启后直接进入了紧急模式或卡在 dracut

这个现象多数厂商镜像、云主机升级内核时容易遇到。原因千奇百怪,但最常见的是磁盘控制器驱动或根文件系统相关驱动没有进入 initramfs。解决思路有三种:

  • 启动时在 GRUB 菜单按e编辑当前启动项,去掉quiet,加上rd.break,进入紧急 shell,查看 dmesg 日志确认卡在哪个模块。
  • 如果系统能进入单用户模式,重新执行dracut -f生成 initramfs。
  • 如果实在起不来,重启选择 GRUB 菜单里的旧内核,进去之后检查新内核对应的 initramfs 是否完整。

核心原则:旧内核绝不能从 GRUB 菜单里消失,这也是我为什么一直强调“验证完再删”。

6.2 NVIDIA 显卡驱动和专有模块失效

CentOS 7 上跑 NVIDIA 驱动的机器很常见,升级新内核后,第三方显卡驱动模块默认不会跟着编译生效。重启后可能显示分辨率异常、图形界面起不来,或者nvidia-smi报错。

解决办法是安装与新内核匹配的 N VIDIA 驱动版本,重装或用对应驱动包的dkms机制自动重编。具体驱动安装流程和内核无关,但一定要先确认驱动包支持你当前的新内核版本。

如果在服务器上只跑 CUDA 计算,同样要检查nvidia-smi是否在新内核下正常输出。很多搞 AI 训练的同学升级内核后忘了重装驱动,GPU 直接不工作,还以为是卡坏了。

6.3 虚拟机和容器环境里经常被忽视的坑

如果你用的是 VirtualBox、VMware Workstation 这类虚拟化软件,新内核启动后,虚拟机的增强工具(Guest Additions / open-vm-tools)经常需要重装或重新编译内核模块。不重装的话,共享文件夹、剪贴板、动态分辨率和拖拽功能都会失效。

对于服务器场景,若你在生产环境用 Docker 或容器运行时,要注意新内核和 storage driver 的兼容性。老内核默认常用devicemapper或overlayfs驱动,新内核默认加载的驱动模块名可能变化,容器启动变慢或挂载异常时,优先检查dmesg输出的存储相关错误。

6.4 安全启动(Secure Boot)导致的引导失败

部分新装的内核包没有官方签名,如果在 UEFI 安全启动开启的状态下重启,可能会报 “Verification failed: (0x1A) Security Violation” 而无法进入系统。

解决办法是在固件设置中临时关闭 Secure Boot,或者使用官方文档说明的已签名版本。这里多说一句:关闭 Secure Boot 本身不影响 grub 引导流程,但会降低系统的安全启动防线,要不要关,得根据公司的安全基线具体评估。

6.5 改完 grub 配置文件后发现菜单乱码或无法识别

有些同学不习惯用 grubby,喜欢直接编辑/etc/default/grub,把GRUB_DEFAULT改成内核索引号。这种做法的问题在于:只要系统以后新增、删除过内核,索引号就会漂移,改过的配置很容易失效。

所以我强烈建议只用 grubby,它不存在索引漂移问题,因为它是根据内核路径精确匹配的。习惯的力量很强,但我还是希望你从这篇文章开始就切换过去。

7. 内核换完之后的后续运维建议

内核换成功不是终点,后续一段时间的观察和维护同样重要。新内核刚上线两周内,建议关注以下指标变化:

  • CPU 负载和 iowait:某些内核版本对 IO 调度器有较大调整,空闲和高负载时期表现会有差异。
  • 内存使用:不同内核版本对 page cache、slab 内存的管理策略不同,可用free -h对比是否出现明显变化。
  • 网络性能:iperf或实际业务流量对比,看看网卡吞吐和中断处理是否正常。
  • 内核日志:dmesg -T看看有没有持续出现的警告,特别是 lockup、task hung、NMI 报错。

新内核稳定运行一段时间后,建议把内核安全相关的 yum 更新纳入常规巡检。ELRepo 的kernel-lt出安全更新时,可以直接通过:

yum --enablerepo=elrepo-kernel update kernel-lt

完成安全更新。不需要再次重复整篇流程,也不用手动改 GRUB,因为更新过程会保留你当前使用的默认内核项。

最后说一个我自己的使用习惯:不管测试还是生产,我都会在/root下放一个名kernel-switch-notes.txt的文件,记录每次换内核的时间、当前版本、默认内核路径、是否验证重启、旧内核版本。这个习惯让我在处理几个月前的历史故障时省了大量时间,因为你永远不可能记住每台机器上次动内核是在什么时候、改了什么。整个过程总结下来就四个字:稳、准、留、验。稳定源,准确切换,留下回滚底线,验证完再清理。做到这四点,换内核就是一件可预测、可回滚的日常运维操作。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进