离线环境CentOS内核rpm本地升级完整指南与回退策略
发布时间:2026/10/20 7:07:23 锦皓数字建站

去年有一批内网服务器被安全扫描标记原因是内核版本过旧某个已知漏洞需要升级内核才能封堵。问题在于这批机器都在隔离网段不能连外网yum源也不允许为了升级内核就顺手做一次全量系统更新——那会把生产环境改到不可控。当时网上查了很多资料大部分教程只写了yum update kernel或者源码编译搬过来根本走不通。最后我选的路子就是标题里写的这种提前把内核rpm包准备好拷进内网用rpm本地更新的方式升级CentOS内核。这篇就把整个过程包括选型理由、操作细节和踩坑教训完整记录下来给同样在离线环境里折腾内核的运维一个可落地的参考。我默认看这篇文章的读者已经有一台CentOS机器需要动内核知道rpm、yum的基本用法但可能没系统梳理过本地更新内核这条路到底怎么走、哪些地方容易翻车。下面所有步骤都是我在实际环境里验证过的按顺序来就行。1. 为什么偏要选rpm本地更新这条路1.1 三种常见内核升级方式的取舍拿到升级内核这个需求的时候大多数人的第一反应是直接yum update kernel。这种方式本身没有错它会自动解析依赖、自动生成引导项、自动更新grub菜单体验确实顺畅。但它有个硬前提机器必须能访问可用的yum源。而且yum update kernel在操作时往往会把与kernel关联的其他软件包一并带起来比如kernel-tools、systemd的某些组件升级面比预期大很多。对于我只想换内核、其余一律不动的运维场景这条路径的副作用偏大。源码编译是另一条路。下载内核源码、make menuconfig配置、make -j编译、make modules_install、make install一套下来时间成本很高对机器上的编译工具链也有要求。更麻烦的是回退逻辑源码安装的新内核会覆盖到/boot和/lib/modules一旦新内核出了问题你没有一个rpm记录可以快速删除只能手动清理文件、手动修grub生产环境里这是很大的负担。rpm本地更新恰好站在两者中间。它不要求目标机器有外网只要求你手里有对应的内核rpm包它不会自动把无关软件一起升级变更面非常小它由rpm包管理器统一记录装了什么、删了什么一清二楚出了问题可以像卸普通软件一样把内核卸掉回退路径做得比别人干净得多。1.2 本地方案的适用边界什么情况下该选它从我自己的实践看rpm本地更新并不适合所有场景它有明确的适用区间。最典型的情况就是内网隔离环境——机器上不了外网yum源不可用但安全通告又催着必须换内核。这个时候提前在外网机器上把内核rpm包下载下来拷贝到目标机器上用rpm安装几乎是唯一兼顾效率和可控性的方式。还有一种场景是版本锁定。有些业务软件对内核版本有隐式依赖比如某个数据库或者某个硬件驱动只在本版本内核上验证过贸然升级到最新内核会带来不必要的兼容性风险。rpm本地更新允许你精确指定某个内核版本安装而不是被动接受源里的最新版。如果你的机器明明有完整外网源、也没有版本锁定要求那直接用yum update kernel就好没必要绕一圈做本地安装。本地方案最大的价值在于离线和精确两个词缺一个它的优势就不明显了。2. 动手前先摸清楚现状环境确认与内核包准备2.1 确认系统引导模式和分区空间很多人刚拿到机器就急着下载内核包结果装到一半才发现/boot分区满了或者引导模式判断错误。我的习惯是先花五分钟把机器现状摸一遍命令不多但每一条都是在为后面的操作排雷。# 当前运行的内核版本 uname -r # 系统发行版版本 cat /etc/redhat-release # 已安装的内核包一览 rpm -qa kernel # /boot 分区剩余空间 df -h /boot # 判断是UEFI还是BIOS启动 [ -d /sys/firmware/efi ] echo UEFI || echo BIOSuname -r告诉你现在跑在哪个内核上rpm -qa kernel告诉你机器上一共装了哪些内核。后面做回退方案时这两条信息直接决定了你要保留什么、可以删除什么。df -h /boot这条很多人容易漏后面我会专门讲为什么它那么重要这里先记住一个原则/boot里每多装一个内核大约要占用 100MB 到 200MB 的空间分区太小的话第二个内核还没装完就没地方了。UEFI和BIOS的差异主要体现在grub配置文件的路径上。BIOS机器grub配置文件在/boot/grub2/grub.cfgUEFI机器一般在/boot/efi/EFI/centos/grub.cfg发行版不同目录名会有差异。这个差异不影响rpm包的安装但影响你后面运行grub2-mkconfig时输出的目标路径所以现在确认清楚能省不少事。2.2 内核rpm包从哪里获取明确要装的内核版本之后下一步是准备rpm包。最稳妥的做法是在一台能联网、且CentOS版本和目标机一致的机器上用yumdownloader把内核包连同依赖一起拉下来。# 安装yum-utils工具包 yum install -y yum-utils # 建立存放目录 mkdir -p /tmp/kernel-rpms # 下载内核及其配套包--resolve会自动拉取依赖 yumdownloader --resolve --destdir/tmp/kernel-rpms kernel kernel-devel kernel-headers如果打算从社区维护的第三方内核仓库获取新版本内核逻辑也差不多先在联网机器上安装该仓库rpm包再用yumdownloader下载对应内核包。这类仓库通常会提供长期维护版和主线最新版两个系列生产环境我一般偏向长期维护版本它稳定性更好、补丁周期长不至于装上之后没多久就要再次升级。需要注意一点kernel、kernel-devel、kernel-headers三个rpm包的版本号必须一致否则后续编译第三方模块时头文件版本对不上会报各种奇怪错误。如果你只是想单纯换内核、不打算在新内核上编译任何外部模块kernel-devel可以不要但我仍然建议把它一起拷过去多一个文件不影响什么真到要用的时候你会发现它无比重要。2.3 离线依赖梳理别只搬一个kernel文件回家rpm工具的设计哲学和yum不同yum会自动解析并补齐依赖rpm -ivh遇到缺依赖直接报错退出。这意味着离线环境下你必须在源机器上就把依赖带全。这里有一个我在实践中碰到的教训最初我以为内核包只需要kernel一个rpm文件结果在目标机器上rpm -ivh时报出缺elfutils-libelf的依赖整个安装流程卡住。后来回到联网机器上重新用yumdownloader --resolve拉完整套文件才把事情理顺。# 查看下载目录里的文件清单 ls -lh /tmp/kernel-rpms/拷贝进内网机器的手段就因地制宜了能走跳板机scp最方便不能走就U盘。本质上这就是本地安装的字面含义——所有安装动作都基于机器上已经存在的rpm文件不依赖任何网络通道。如果你需要批量更新多台机器同一个目录的rpm文件可以直接复制到每台机器上反复使用这也是本地方案在批量场景下的隐藏红利。3. 安装与引导变更的完整操作每一步都讲清楚为什么3.1 包安装顺序与依赖处理把所有rpm包拷贝到目标机器进入存放目录执行安装。我通常在CentOS 7上这样操作cd /tmp/kernel-rpms # 一次传入多个rpm让rpm一次性解析它们的共同依赖 rpm -ivh kernel-*.rpm这里的kernel-*.rpm会匹配到kernel、kernel-devel、kernel-headers等所有以kernel开头的包。一次传入多个rpm和逐条执行的区别在于rpm会在安装前统一分析所有这些包的依赖关系而不是装完一个再单独看下一个能减少一部分装完A才意识到B互相冲突的情况。如果执行过程中报依赖缺失不要拿到--nodeps就硬上。--nodeps会让rpm跳过依赖检查但缺失的依赖会在系统里埋雷——轻则某个工具运行异常重则以后每次执行yum操作都会报同样的依赖错误。正确做法是记录下报错信息里的缺失包名回到联网机器上用yumdownloader --resolve下载对应包再拷贝过来安装。在某些离线环境里还有一个更顺滑的变体把准备好的所有rpm文件放到一个目录用createrepo把这个目录做成一个本地文件源然后写一个repo文件指过去再用yum localinstall -y kernel-*.rpm完成安装。这种方式的好处是yum仍然在工作依赖解析和安装日志都由yum统一管理比裸rpm -ivh的可视化更好。缺点是你需要额外安装createrepo工具并且多几步配置。如果机器数量少、只是临时装一次内核直接用rpm -ivh就够了没必要为一次性操作搭建本地源。安装完成后立刻检查内核文件是否落位# 查看/boot下的新内核文件 ls -lh /boot/vmlinuz-* # 确认新内核出现在rpm列表中 rpm -qa kernel正常情况下/boot目录下会多出一整套新版本文件vmlinuz-新版本、initramfs-新版本.img、System.map-新版本、config-新版本。其中initramfs是安装rpm包时自动生成的它负责在启动阶段加载根文件系统所需的模块不需要我们手动干预。如果你发现新内核文件都在但缺了initramfs那就要警觉说明安装过程中某一步没走完整后面我会讲怎么补救。3.2 引导加载器配置不改默认启动项等于白装这是整个升级流程里最容易翻车的地方。原因是很多人想当然地以为内核rpm装好了重启自然就进新内核了。实际完全不是这样。CentOS的多内核机制里新内核只是被加入到了grub菜单中系统当前的默认启动项仍然是旧内核。不改默认项重启一百次都还是老内核。首先要让grub识别到新内核的菜单项# BIOS引导的机器 grub2-mkconfig -o /boot/grub2/grub.cfg # UEFI引导的机器输出路径根据具体发行版目录调整 grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg这条命令会扫描/boot里的所有内核文件重新生成完整的grub启动菜单。执行完之后新内核的菜单项已经存在了但系统默认项还没变。接下来用grubby设置新内核为默认启动项# 查看当前默认内核 grubby --default-kernel # 查看所有启动菜单项 grubby --infoALL # 将默认启动项设置为新内核 grubby --set-default /boot/vmlinuz-新内核版本号 # 再次确认默认项是否切换成功 grubby --default-kernel在CentOS 7上grub2-set-default也是可用的方案但grubby在CentOS 7、8、9上都能通用用一套命令就能覆盖不同版本的环境我自己更习惯用它。关键判断点是最后一步grubby --default-kernel输出的路径必须是你刚安装的新内核否则说明这一步操作没有生效需要回头检查内核路径是否写对。这里补充一句为什么要手动改默认项、为什么发行版不帮我们自动切因为有相当多运维场景要求装好内核但暂时不重启开发者会把默认项留在旧内核上等业务低峰期再手动切过去。这种设计本身是给运维留余地的但也意味着如果不主动修改默认项升级就是无效的。3.3 重启与归属验证确保你已经跑在新内核上确认默认启动项已经指向新内核之后就可以安排重启了。重启前我习惯再做一次快速检查grubby --default-kernel的输出、/boot里的新内核文件都在、磁盘空间足够三个条件满足就执行reboot。重启回来后验证动作不多但必须做# 确认实际运行的内核版本 uname -r # 查看本次启动的时间 uptime -s # 检查已加载的内核模块数量是否正常 lsmod | wc -l # 查看启动日志里有没有明显报错 dmesg | grep -iE error|fail | head -20uname -r是最直接的验证输出必须等于你安装的新内核版本号。如果发现重启后还在旧内核上基本可以断定是上一步默认启动项没设置成功不用慌重新执行grubby --set-default再重启一次就好。这里我要多提醒一句如果操作的是远程服务器重启之前务必确认机器有带外管理通道或者可以进机房。因为新内核可能导致某个驱动没有正常加载网络接口甚至可能起不来一旦 ping 不通你唯一能做的就是去物理控制台处理。这个场景我经历过结论是在远程机器上动内核之前评估如果网络掉了怎么办比评估新内核有多快重要一百倍。4. 回退兜底设计给生产环境留一条保命的后路4.1 为什么同时保留两个内核rpm包安装新内核并不会覆盖旧内核系统会同时保留新旧两套内核文件grub菜单里也会同时出现两个入口。这不是bug是Linux发行版的刻意设计——多内核共存是系统稳定性的最后底线。我在处理生产机器时从不在升级当天删除旧内核。至少要等新内核跑几天、确认业务无明显异常、驱动加载无告警之后再考虑清理。保留多个内核的成本不过是/boot里几百MB空间和grub菜单里多一行项这点代价换一次失败的保险太划算了。你可以用下面命令确认当前系统和已安装内核的状态# 列出已安装的内核 rpm -qa kernel # 查看当前运行的内核 uname -r # 查看当前默认启动项 grubby --default-kernel对比这三个输出你能清楚看到当前运行的和默认启动项分别指向哪个版本。正常情况它们应该一致如果发现不一致说明之前设置默认项时操作有误要及时修正。4.2 新内核启动异常时的回退操作新内核出问题分不同严重程度回退方式也分三种情况。第一种系统能进、命令行能敲、但业务跑不起来或者某些驱动报错。这种情况最友好直接把默认启动项切回旧内核重启即可grubby --set-default /boot/vmlinuz-旧内核版本号 # 确认已切回 grubby --default-kernel # 重启进入旧内核 reboot第二种新内核启动过程中直接卡住根本进不了系统。这时重启机器在grub菜单出现时用方向键选择旧内核的菜单项回车启动。进入系统后按第一种情况里的方式把默认项改回旧内核避免下一次开机又自动往新内核里撞。第三种grub菜单本身都异常了比如升级过程中grub配置写坏、启动项全丢。这种情况最麻烦常见思路是进入故障救援模式或者用启动介质引导后再修复grub配置。处理逻辑是先恢复一个可用的系统入口再重新生成grub菜单。这种场景不太常见但如果你负责的机器很重要最好提前在测试机上演练一遍救援介质的使用流程真到用的时候不至于手忙脚乱。4.3 稳定运行后的旧内核清理时机与操作新内核稳定运行几天后清理就提上日程了。清理的目的是释放/boot空间、减少grub菜单里的杂质项。我的习惯是保留当前运行的新内核和一个最旧的备用内核中间那些历史版本一次性清掉。# 列出所有已安装的内核 rpm -qa kernel # 以rpm命令删除指定旧内核 rpm -e kernel-旧内核版本号 # 用yum删除也可以 yum remove -y kernel-旧内核版本号删除时务必仔细核对版本号我见过有人手滑把当前运行的内核也删了导致系统虽然还在运行但rpm库里已没有对应内核记录下次更新或重装组件时各种连环依赖错误。稳妥起见删除前先跑一次uname -r确认当前内核然后和rpm -qa kernel的输出比对只删那些既不是当前运行、也不是默认启动项的旧版本。清理完旧内核后重新执行一次grub2-mkconfig让菜单跟实际文件保持一致。这一步可以避免grub菜单里残留指向已删除内核的灰色启动项。5. 实操中真正容易踩的坑与自救思路5.1 /boot分区爆满最容易翻车的环境问题前面我反复提到/boot空间不是无限的因为这是我在实际环境里被绊倒过的点。某台机器原本已经装了三个内核我下载好新内核包后直接rpm -ivh结果在写入阶段报no space left on device。一看df -h /boot分区已经占满。处理这类问题没有捷径就是先腾空间再装。把最旧最没用的内核删掉一两个释放出空间然后重新执行安装命令。这个坑虽然不难解决但它发生的时机非常尴尬——通常是在你满心以为马上要完成的时候所以我把检查/boot空间提到流程最开始就是希望你不要在最后一步被它卡住。5.2 驱动模块与新内核匹配网络掉线的检查思路一个让人记忆深刻的案例是升级内核后某台机器的网卡驱动直接失效网络掉线因为是远程操作我只能让现场同事去物理控制台处理。事后排查发现那台机器用的是某硬件厂商提供的闭源网卡驱动模块它并没有随新内核自动编译适配。这个问题的预防思路其实不难升级前先用lspci -k看看网卡、存储卡这些关键硬件当前用的是哪家驱动确认是内核自带模块还是厂商闭源模块。升级后进入新内核再用lsmod检查对应模块是否加载成功# 查看内核模块是否加载 lsmod | grep 模块名 # 查看具体硬件走的驱动 lspci -k | grep -A2 -i ethernet如果发现模块确实没有加载就要考虑找厂商要适配新内核版本的驱动包重新安装或者通过dkms机制在新内核上重新编译模块。这块工作最好在升级前就评估好而不是先升级再发现问题。5.3 依赖冲突与本地源绕行方案离线环境下rpm -ivh报依赖错误是家常便饭。常见的是某个.so动态库文件缺失或者是某个包对版本有硬性要求。这时候不要硬着头皮忽略依赖最体面的解法是回到联网机器上用yumdownloader --resolve把报错里提示的依赖包拉下来按依赖链逐个装好再回来装内核。如果机器数量多、以后还要反复装包更推荐做一个本地文件源把所有rpm放进一个目录用createrepo生成索引写一个repo文件指向该目录之后所有离线安装都可以走yum localinstall。这个方案的前期工作量稍大但后期省心不是一点半点。还有一个容易忽略的坑是版本锁。有些系统管理员为了防止意外升级在yum里配置了版本锁定把kernel包固定在某个版本号上。这种情况下即使rpm包就摆在你面前yum localinstall也可能被版本锁拦截。排查时可以用yum versionlock list看一眼有锁就先解除装完再重新锁上。5.4 特殊引导环境带来的隐藏问题最后说两个相对低频、但遇到了会很头疼的问题。第一个是UEFI环境下开启了Secure Boot。如果新内核rpm包没有在机器信任密钥里注册启动时会被固件拒绝。处理办法是用mokutil导入对应公钥或者在确认安全的前提下暂时关闭Secure Boot。这方面不同的主板、不同的发行版表现差异很大处理时建议以硬件厂商的文档为准不要照搬通用步骤。第二个是根文件系统使用了LVM或磁盘加密的机器。正常情况下rpm包安装内核时会自动生成对应的initramfs但特殊存储配置偶尔会让initramfs不包含必要的持久化模块导致新内核启动时找不到根设备。如果你怀疑是这种情况可以手动重新生成当前运行内核的initramfsdracut -f /boot/initramfs-$(uname -r).img $(uname -r)我处理这类问题时的经验是先用文档记录、再用测试机复现最后才动生产机器。尤其是涉及Secure Boot、磁盘加密这类和环境强相关的特性生产环境和测试环境不一致往往就是踩坑的根源。这批机器后来都顺利完成了内核切换。我个人的习惯是内网环境升级内核心思花在留后路上比花在装得快上有价值得多。每次动内核前我都会确认三件事rpm包版本清晰、默认启动项改对了、旧内核还留着。只要能随时回退剩下的故障都是可接受的。如果你也正好在离线环境里折腾CentOS内核希望这篇能让你少走几个弯路。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。