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-ml | kernel-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 权限
- 已经拍摄快照或备份关键配置
确认无误后重启:
reboot4.3 重启后验证新内核是否真的生效
很多人重启完就急着看uname -r,但你看到的版本号是多少,取决于是否真的进入了新内核。正确的验证命令:
uname -r如果输出是你安装的新版本号,说明默认启动项生效。如果还是旧版本号,说明 grubby 设置没有生效,或者重启时你手动选择了旧项,又或者是启动项配置指向存在问题。另外别忘了一条命令:
uptimeuptime输出会包含系统启动时间,确认它是你本次重启的时间点,避免误以为切到了新内核其实是从未重启过,这个低级错误我见过不只一次。
更细致的验证是:
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的文件,记录每次换内核的时间、当前版本、默认内核路径、是否验证重启、旧内核版本。这个习惯让我在处理几个月前的历史故障时省了大量时间,因为你永远不可能记住每台机器上次动内核是在什么时候、改了什么。整个过程总结下来就四个字:稳、准、留、验。稳定源,准确切换,留下回滚底线,验证完再清理。做到这四点,换内核就是一件可预测、可回滚的日常运维操作。