ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CentOS 7 内核升级指南:yum更新与源码编译两种方法

CentOS 7 内核升级指南:yum更新与源码编译两种方法 1. 为什么还要折腾 CentOS 7 的内核升级CentOS 7 出厂自带的内核版本停留在3.10.x这条线上这个版本号从 2014 年发布一直维护到 2024 年生命周期结束。很多人在生产环境或者实验环境里跑着跑着就会撞墙新买的网卡驱动装不上、Docker 要求更高版本的内核特性、某些编译工具链提示内核头文件太老、BPF 相关的调试工具打开就报错。这时候摆在面前的路其实就两条——要么换系统要么把内核升上去。换系统的成本太高尤其是那些跑了多年、配置文件堆成山的机器所以升级内核成了最现实的选择。我前后在十几台 CentOS 7 机器上做过内核升级踩过的坑从 GRUB 配置写错导致进不去系统到编译到一半磁盘满了被迫重来基本能踩的雷都踩过一遍。这篇文章就把两种主流方法——yum 更新和内核编译——从选型逻辑、具体步骤到排错经验完整拆开讲。适合正在维护 CentOS 7 的运维同行、需要特定内核特性做开发的同学以及想搞懂 Linux 内核加载机制的爱好者。全程用大白话讲清楚每一步在干什么、为什么这么干尽量让你抄作业就能跑通。先说一个核心认知内核升级不是把旧文件删掉换新文件这么简单而是新旧内核并存、通过引导程序选择启动哪个的模式。这个机制决定了后面所有操作的安全性——只要旧内核还在升级失败了还能回退。理解了这一点你操作时心里就有底了。2. 升级前的必修功课摸清家底再动手动手之前有一套固定动作必须先做完这步省掉的话后面出问题会非常被动。2.1 当前内核与硬件环境核查先确认你现在跑的是什么内核、系统架构是什么、有没有特殊硬件依赖。几个命令配合着看uname -r # 当前运行的内核版本 uname -m # 架构一般是 x86_64 cat /etc/centos-release # 系统版本 lscpu | grep -i model # CPU 型号 lsblk # 磁盘分区布局 df -h /boot /usr # 关键分区剩余空间uname -r在 CentOS 7 上通常返回类似3.10.0-1160.el7.x86_64的结果后面带el7就是 CentOS 7 的标记。特别注意/boot分区很多人在装系统时只给/boot分了 200MB 到 500MB而每一个内核版本连同 initramfs 镜像大概占 100MB 到 200MB。如果你准备装新内核/boot至少要留出 500MB 以上的空闲否则安装过程会直接失败我就遇到过/boot只剩 80MB 硬着头皮装结果 yum 报错退出的情况。/usr分区同样要留意内核模块安装后会写到/usr/lib/modules/下面一个完整的内核模块集轻松占掉 500MB 到 1GB。编译方式还会额外占用源码目录的空间/usr/src下面放一套解压后的内核源码加编译产物两三个 GB 是常态。2.2 数据备份与快照策略这一步我要重点强调因为教训太深刻。物理机操作的话把重要业务数据、/etc目录、数据库导出文件先备份到别的地方。如果是虚拟机直接给整机打一个快照出问题一键回滚这是成本最低的保险。我自己的习惯是快照命名带上日期和操作内容比如before-kernel-upgrade-20240612一周后确认稳定再删掉。备份完之后还要确认一件事你能不能接受停机。内核升级后需要重启才能生效重启过程业务中断是必然的。生产环境要提前和业务方约好维护窗口别在业务高峰期操作。曾经有同事在下午三点给一台跑着订单服务的主机升内核重启直接被投诉到部门这个坑大家别踩。2.3 引导方式确认BIOS 还是 UEFICentOS 7 时期两种引导方式都有判断方法很简单[ -d /sys/firmware/efi ] echo UEFI启动 || echo BIOS(legacy)启动这个判断为什么重要因为GRUB 的配置方式不一样。BIOS 引导用grub2-mkconfig -o /boot/grub2/grub.cfgUEFI 引导用grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg。写错了路径新内核根本不会出现在启动菜单里重启进去还是老内核白忙一场。2.4 记录回退路径动手前把当前运行的完整内核版本号记下来写在小本子上或者终端标签里。升级后如果新内核有问题在 GRUB 菜单里选择旧版本进去然后卸载新内核包就行。回退能力决定了你的操作上限心里有回退路径操作起来才敢大胆。提示/boot空间不足是最常见的升级失败原因动手前务必确认剩余空间大于 600MB。3. 方法一yum 更新法最省心的主流选择对于绝大多数人来说yum 更新法是首选。它不编译、不折腾、十几分钟搞定稳定性也有社区维护背书。这个方法的核心思路是引入第三方内核仓库最常用的是 ELRepo然后像装普通软件一样把新内核装进来。3.1 为什么选 ELRepo 而不是默认源CentOS 官方源里的内核始终停留在 3.10.x版本号最多升到3.10.0-1160这种更新主版本号不会动。而 ELRepo 这个社区仓库专门提供两个系列内核系列说明适合场景kernel-ltLong Term 长期支持版稳定优先生产服务器、求稳环境kernel-mlMain Line 主线版特性最新开发测试、需要新特性选哪个取决于你的诉求。要稳定性就上kernel-lt它对应的是上游 LTS 版本比如 5.4 或 6.1 系列。要新特性比如更新的文件系统支持、新的网络协议栈就上kernel-ml。我一般给生产机装kernel-lt测试机装kernel-ml。3.2 引入 ELRepo 仓库的完整操作先导入仓库的签名公钥再装仓库包# 导入公钥 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org # 安装 ELRepo 仓库CentOS 7 对应 el7 yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm如果机器不能连外网这条命令会失败。内网环境需要提前把 rpm 包下载好传进去用yum localinstall安装。装完之后ELRepo 的配置会写到/etc/yum.repos.d/elrepo.repo你可以打开看看默认两个仓库elrepo-kernelml 系列和elrepo-kernel-ltlt 系列是关闭状态的需要手动指定才生效。3.3 查看可选内核版本并安装不要急着装先看看有哪些版本可选# 查看 ml 系列可用版本需要启用仓库 yum --disablerepo* --enablerepoelrepo-kernel list available | grep kernel # 只看 lt 长期支持版 yum --disablerepo* --enablerepoelrepo-kernel-lt list available | grep kernel确认有合适的版本后开始安装。装长期支持版yum --enablerepoelrepo-kernel install kernel-lt -y如果还想把对应的开发头文件一起装上方便以后编译驱动模块再加一个yum --enablerepoelrepo-kernel install kernel-lt-devel -y安装过程会自动下载、解包、生成 initramfs 镜像、更新 GRUB 条目。整个过程注意观察输出如果最后提示Installed就成功了。这一步不会删除旧内核新旧共存这点可以放心。3.4 让新内核默认启动新内核装完了但 GRUB 默认还是从旧内核启动。有两种方式切换默认项。第一种是查菜单序号然后设置# 查看所有内核启动项及序号 awk -F\ $1menuentry {print i : $2} /etc/grub2.cfg输出会列出 0、1、2 这样的序号新装的通常是序号 0。然后设置默认grub2-set-default 0第二种更省事直接用grubby工具它会自动找到最新的内核grubby --set-default /boot/vmlinuz-5.4.xxx.el7.elrepo.x86_64后面的版本号换成你实际装的。设置完可以用grubby --default-kernel确认一下当前默认内核路径。最后重新生成 GRUB 配置注意根据引导方式选路径# BIOS 引导 grub2-mkconfig -o /boot/grub2/grub.cfg # UEFI 引导 grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg3.5 重启验证与旧内核清理重启机器reboot重启后第一时间uname -r确认版本已经变成新内核。确认一切正常网络、存储、业务服务都起来了之后可以清理旧内核释放空间。不过我的建议是先别急着删观察个三五天确认新内核稳定再清理。清理旧内核用yum remove kernel-3.10.0-1160.el7.x86_64但要小心别把正在运行的内核或者唯一的救援内核删了。至少保留一个能正常启动的旧版本作为后路。yum在删除内核时有installonly_limit参数控制保留数量默认是 3一般不用改。注意升级完内核后那些依赖旧内核编译的第三方驱动比如某些 RAID 卡、网卡厂商驱动会失效需要针对新内核重新编译安装。升级前先确认你的硬件有没有这类依赖。4. 方法二内核编译法掌控一切的硬核路线当你需要开启特殊的编译选项、打上自定义补丁、或者目标环境连不了外网又必须用特定内核版本时源码编译就是唯一出路。这条路费时费力但掌控力拉满。4.1 编译环境的依赖准备先把编译工具链和依赖库装齐缺任何一样到后面都会中断yum groupinstall -y Development Tools yum install -y ncurses-devel elfutils-libelf-devel openssl-devel \ bison flex bc dwarves zlib-devel逐个说明这些依赖的用途。Development Tools是套件包含 gcc、make、binutils 这些基础工具。ncurses-devel是给make menuconfig图形化配置界面用的没它菜单界面出不来。elfutils-libelf-devel用于处理内核模块的 ELF 格式。openssl-devel是内核签名和加密相关编译需要的。bison和flex是内核构建系统用的语法分析器。bc处理构建脚本里的浮点计算。dwarves提供 pahole 工具新版内核的 BTF 特性需要它。我吃过一次亏编译到中途才报缺openssl-devel只能重新清理再编白白浪费半小时。所以依赖一次装齐别偷懒。4.2 下载与解压内核源码内核源码从 kernel.org 官方站下载选长期支持版本比较稳。以 6.1 系列为例cd /usr/src # 下载源码包版本号以官网实际为准 wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.90.tar.xz # 解压 tar -xf linux-6.1.90.tar.xz cd linux-6.1.90源码包几百 MB解压后大概 1.2GB 左右。再次确认/usr/src所在分区有至少 15GB 空闲因为编译产物.o目标文件、vmlinux、模块文件加起来会再吃好几个 GB。4.3 以现有配置为基础做最小改动新手常犯的错误是从零开始一项一项配置。正确做法是基于当前运行内核的配置来改这样能保留系统原有的硬件支持只针对你的需求调整。当前内核配置一般在/boot/config-$(uname -r)拷过来用cp /boot/config-$(uname -r) .config但新内核版本比旧的高很多有些配置项已经变了需要先做一次对齐# 用默认值填充新增的配置项保留原有选择 make olddefconfig这一步会检查.config里哪些选项已经不存在、哪些是新增的然后自动处理。处理完再进入图形界面细调make menuconfigmenuconfig的操作逻辑方向键移动Enter 进入子菜单或切换选项空格键在三态空、*编译进内核、M编译成模块之间切换Y是编进内核、N是排除、M是模块。改完按 tab 选 Save 保存再 Exit 退出。4.4 关键编译选项取舍对大多数升级需求主要关注这几类选项我列个表说清楚配置路径选项建议说明General setupLocal version自定义后缀比如-custom方便区分Processor type处理器家族按实际CPU选影响优化指令集Device Drivers网卡/存储驱动保留原有漏掉会导致网卡不认File systemsext4/XFS编进内核根文件系统必须内置Enable loadable module support模块支持必须开否则驱动没法加载配置的核心原则是根文件系统相关的驱动、启动必需的驱动必须编译进内核Y其余不常用的编译成模块M。如果你的根文件系统是 XFS那 XFS 驱动一定要 Y不能是 M否则内核起来后找不到根分区直接内核恐慌。这个坑我见过太多人踩。另外把Local version设成-custom这种自定义后缀好处是uname -r能一眼认出哪个是自编译内核和发行版内核区分开。4.5 编译过程与并行度设置配置好后开始编译这是最耗时的环节。用-j参数开启并行编译数字一般设成 CPU 核心数或者核心数加一# 查看核心数 nproc # 开始编译J 后面替换成你的核心数 make -j8一台 4 核的机器编一个完整内核大概要 40 分钟到 1 个半小时取决于配置大小。8 核以上会快不少。编译过程磁盘 IO 和 CPU 都会拉满如果要在这台机上跑业务最好挑业务低峰期。编译中途如果报错仔细看错误信息常见的是缺依赖或者配置冲突。改完配置再编时最好先make clean清理上次产物避免旧产物干扰。不过make clean后下次是全量重编如果只是想微调用make增量编译也行。4.6 安装模块与内核编译成功后按顺序执行三步# 1. 安装内核模块到 /lib/modules/ make modules_install # 2. 安装内核镜像、System.map、配置文件到 /boot make install # 3. 注意老版本源码树可能需要手动跑新版本 make install 会自动调make install这一步会自动把vmlinuz、System.map、config拷到/boot同时调用 GRUB 工具添加启动项。如果它没自动添加就手动更新 GRUBgrub2-mkconfig -o /boot/grub2/grub.cfg4.7 重启与自编译内核验证重启之前在/boot里确认新内核文件确实存在ls -lh /boot/vmlinuz-6.1.90-custom存在再重启reboot重启后uname -r应该显示6.1.90-custom这种带自定义后缀的版本。然后检查关键功能dmesg看有没有报错、ip a看网卡、mount看文件系统、lsmod看模块加载。有一样不对就重启回到旧内核排查。提示自编译内核最怕的就是某个必需驱动没编进去导致起不来。保持旧内核可启动是第一安全网其次是在 GRUB 里给新内核预留一个可编辑的救援入口。5. 两种方法横向对比与选型建议讲了这么多把两条路放在一起对照选起来就清楚了。对比维度yum 更新法内核编译法操作耗时10-20 分钟1-3 小时技术门槛低会敲命令就行中高要懂配置版本可控性受仓库版本限制完全自由定制能力无用现成的可打补丁、改选项稳定性风险低社区维护取决于你的配置离线环境需提前准备 rpm源码可离线升级回退简单yum 卸载需手动清理推荐场景90% 的日常需求特殊硬件/离线/定制我的经验判断是能 yum 就别编译。除非你有非常明确的理由——比如目标内核版本仓库里没有、需要特定编译参数优化性能、硬件驱动只有源码形式必须一起编进内核——否则 yum 更新的稳定性和省心程度完全值得选它。编译这条路用的频率很低但作为能力储备必须会关键时刻能救命。6. 升级过程中的常见故障与排查实录这部分是我踩坑记录里最值钱的部分整理成速查形式遇到问题直接对号入座。6.1 系统起不来GRUB 找不到新内核现象是重启后还是进旧内核或者卡在grub提示符。原因通常是 GRUB 配置没生成对或者grub2-set-default设了但没重新生成配置。排查顺序先看/boot/grub2/grub.cfg里有没有新内核的menuentry段落没有就重新执行grub2-mkconfig并检查引导方式对应的输出路径是否正确。UEFI 机器如果写成了 BIOS 的路径配置就白生成。6.2 内核恐慌VFS Unable to mount root fs最典型的一类报错屏幕上一堆VFS: Cannot open root device之类的信息然后停机。根因是根文件系统驱动或者磁盘控制器驱动没有正确编译进内核。解决办法是重启回旧内核在menuconfig里确认根分区文件系统ext4 或 XFS和对应的存储控制器驱动都设成*编进内核重新编译安装。6.3 新内核下网卡不见了ip a只剩一个lo回环接口业务网络全断。这多半是网卡驱动没编译进去或者是模块名变了。回旧内核后lspci查网卡型号在menuconfig的Device Drivers - Network device support里找到对应驱动设成模块或编进内核。企业级服务器常见的 Broadcom、Intel 网卡驱动要特别留意。6.4 yum 安装报 no space left on device十有八九是/boot满了。先清掉旧内核释放空间# 查看已安装内核 rpm -qa | grep kernel # 卸载不再使用的旧内核 yum remove kernel-3.10.0-957.el7.x86_64清理时务必保留至少一个可启动的版本。如果/boot实在太小可以永久扩容或者把新增内核装到别处但扩容涉及分区调整风险也不小。6.5 编译中途内存不足被 OOM 杀掉编译并行度过高时每个编译任务都吃内存8 核机器开-j8如果内存只有 4GB很容易触发 OOM Killer 把编译进程干掉。解决办法是把并行度降下来-j4甚至-j2用时间换内存。或者开交换分区临时救急但速度会慢很多。另一个坑是磁盘满了编译 IO 密集编译前一定要df -h确认空间。6.6 自编译内核后树外模块失效升级内核后之前针对旧内核编译的第三方模块DKMS 管理的或者手动编译的驱动全都不认了。这是因为内核模块和内核版本绑定modprobe时会校验版本。解决办法是针对新内核重新编译这些模块DKMS 管理的模块用dkms autoinstall -k 新版本重建手动编译的就得重新走一遍make make install。6.7 常见问题速查表故障现象可能原因快速处理重启进旧内核GRUB 默认没改对grub2-set-default 重生成配置内核恐慌挂载根失败根文件系统驱动没内置menuconfig 里设为编译进内核无网络接口网卡驱动缺失补编对应网卡驱动yum 安装失败提示空间/boot 分区满清理旧内核释放空间编译被 Killed内存不足降低并行度或加 swap模块加载失败版本不匹配针对新内核重编模块找不到新内核菜单引导路径写错按 BIOS/UEFI 选对路径7. 我个人在多次升级中沉淀下来的实操心得说说那些文档里不会写、只有亲手干过才知道的细节。第一升级前用yum update把系统整体更新一遍尤其是grub2、dracut这些引导和镜像生成工具老版本的工具处理新内核时偶尔会出兼容问题先更新能规避掉一部分诡异故障。第二新内核装好后重启前养成一个习惯——手动检查/boot里新内核的initramfs文件是否存在生成失败的话重启就是灾难宁可多花 30 秒确认。第三关于/boot分区大小如果你的机器还没上线、可以重装建议分区时直接给/boot分 2GB一劳永逸。已经上线的机器就靠定期清理旧内核维持。第四编译内核时别追求配置齐全能编成模块的全编成模块只有启动必需的才编进内核这样内核镜像体积小、编译快、出问题概率也低。第五无论用哪种方法保留旧内核至少一周再考虑清理稳定性的问题往往在运行几天后才暴露比如某些硬件在高负载下才报驱动的毛病。还有一个容易被忽略的点升级内核后/etc/default/grub里的GRUB_DEFAULT如果写的是saved配合grub2-set-default才生效如果写的是数字0那grub2-set-default就白设了得直接改这个文件里的数字。我就在这个问题上耗费过半小时反复设置默认项都不生效最后发现是GRUB_DEFAULT的值不对。这类配置层叠的坑排查时要顺着工具链一层层往上找别只盯着一个地方。最后再分享一个批量运维时的技巧如果你要在几十台机器上做同样的内核升级把整个流程写成脚本从仓库引入、安装、设默认、重生成配置一条龙然后配合ssh批量执行。但脚本里必须加上前置检查——磁盘空间、当前内核版本、引导方式——不满足条件就退出报警避免在空间不足的机器上批量失败。脚本升级完之后一台一台重启验证确认没问题再推进下一批。这样即使某一台出问题影响面也是可控的。内核升级这事稳永远比快重要。
返回列表