做运维这些年,系统升级做过不少,但内核升级始终是那个“不做不行、做了心惊”的活儿。Anolis OS(龙蜥操作系统)这几年在服务器端的出镜率越来越高,一方面是因为它跟CentOS生态兼容性好,另一方面是社区的更新节奏确实跟得上。不过内核升级这件事,很多朋友要么不敢动,要么上来就一把梭,结果启动直接进不了系统。这篇文章我就把Anolis OS内核升级从查询到配置的完整流程拆开揉碎讲一遍,包括各种查询命令、升级方式、引导配置、回滚机制,以及我踩过的坑,希望你看完能少走弯路。
文章适合谁看?主要是正在使用或准备迁移到Anolis OS的运维工程师、开发环境管理员,以及那些被CentOS停服搞得不得不换系统的朋友们。读懂这篇文章,你能搞清楚一件事:内核升级不是玄学,是一套有迹可循的标准化操作,关键是把每一步的“为什么”弄明白。
1. 升级前先摸清家底:内核版本查询与现状评估
1.1 当前内核版本查询的几种姿势
先说最基础的:怎么知道当前系统跑的是哪个内核版本。这个命令大家应该都熟,就是uname -r,但实际工作中光靠它还不够。
# 查看当前运行的内核版本 uname -r # 查看内核完整信息,包括编译时间、编译器版本等 uname -a # 查看系统发行版信息,确认是Anolis OS哪个大版本 cat /etc/os-release # 查看已安装的内核相关包 rpm -qa | grep ^kernel输出大概是这样的:
[root@anolis ~]# uname -r 4.18.0-372.32.1.an8_6.x86_64 [root@anolis ~]# cat /etc/os-release NAME="Anolis OS" VERSION="8.6" ID="anolis" ID_LIKE="rhel fedora centos" VERSION_ID="8.6" PLATFORM_ID="platform:an8" PRETTY_NAME="Anolis OS 8.6" ANSI_COLOR="0;31" HOME_URL="https://openanolis.cn/"这里有两个信息特别关键:内核版本号和系统大版本号。Anolis OS 8系列默认的内核是4.18,这是从RHEL/CentOS 8沿袭下来的内核主线,Anolis在此基础上做了大量的补丁和优化。如果你看到内核版本里带an8字样,说明这是龙蜥官方适配过的内核。
1.2 硬件与内核兼容性摸底
升级内核之前,我强烈建议先做一轮硬件兼容性检查。内核升级后遇到的绝大多数问题,其实不是内核本身的问题,而是新内核和旧硬件驱动之间的适配问题。
需要重点检查的硬件包括:
- 网卡芯片型号,尤其是板载网卡和万兆网卡
- RAID卡和HBA卡(直通卡)型号
- GPU型号(如果有)
- NVMe SSD的固件和驱动情况
- 主板上的BMC/iDRAC管理口芯片
查询方式可以用:
# 查看PCI设备列表 lspci | grep -i ethernet lspci | grep -i raid lspci | grep -i vga # 查看已加载的内核模块 lsmod # 查看当前内核支持的模块路径 ls /lib/modules/$(uname -r)/我见过最典型的一个案例:一台机器上用着老款的Broadcom网卡,CentOS 7自带的3.10内核一直跑得好好的,用户升级到4.18内核后,网卡驱动模块加载失败,服务器直接失联。最后排查下来是旧网卡不在新内核的驱动支持列表里,需要额外编译驱动模块。所以在升级前,把硬件清单拉出来,去内核的drivers/net目录或者其他驱动源里确认一下支持情况,这个动作能帮你省掉不少麻烦。
1.3 判断是否需要升级的四个信号
不是所有机器都需要没事就升内核,内核升级是有明确诉求才做的操作。我总结下来,出现以下四个信号之一,你就该认真考虑升级了:
第一,安全漏洞修复。系统发布安全公告后,如果涉及内核漏洞(比如脏管道、Dirty COW这类),且你的业务环境对安全等级有要求,那就得尽快跟进。
第二,硬件驱动支持不足。新采购的服务器,比如最新的NVMe盘、新的网卡,旧内核识别不了或者性能发挥不出来,这时候不升级不行。
第三,性能瓶颈。某些业务场景下,旧内核的调度器、网络栈表现不佳。比如高并发网络转发场景,新内核在TCP性能上往往有明显改善。
第四,容器和虚拟化需求。Docker、Kubernetes 对内核特性有要求,像 overlayfs、cgroup v2、iptables 的某些模块,新内核支持更完整,运行更稳定。
但反过来也要提醒一句:如果你的业务系统跑得好好的,没有安全诉求,也没有新硬件要支持,那就别折腾。内核升级是有风险的操作,稳定压倒一切,这是运维工作的铁律。
2. 升级前的准备工作:备份与依赖检查
2.1 系统快照与关键配置备份
说句实在话,内核升级前最重要的事不是执行升级命令,而是做好回滚预案。我见过太多人忽略了备份,结果新内核起不来,旧内核又被清理了,最后只能拿光盘进救援模式。那种酸爽,谁经历谁知道。
这里说的备份包括几层:
- 如果是虚拟机,优先做整机快照。操作前在虚拟化平台点一下快照,出问题一键还原,这是成本最低的保险方案。
- 如果是物理机,建议备份
/boot分区和整个/etc目录。内核升级会改动/boot下的vmlinuz、initramfs,同时可能改写/etc/default/grub和grub配置。 - 如果条件允许,把重要的业务数据进行异地备份,以防极端情况。
# 备份 /etc 目录 tar -czf /data/backup/etc_$(date +%Y%m%d%H%M%S).tar.gz /etc # 备份 /boot 目录 tar -czf /data/backup/boot_$(date +%Y%m%d%H%M%S).tar.gz /boot2.2 软件源配置检查
Anolis OS的内核升级依赖软件源,所以升级前必须先确认yum源配置正确。Anolis默认的源是repo.openanolis.cn,你可以在/etc/yum.repos.d/下看到相关的repo文件。
# 查看已配置的源 yum repolist # 查看内核相关的可用包 yum list available kernel*检查的时候注意几个点:
第一,确认源文件没有损坏,baseurl或mirrorlist地址能正常访问。有时候内网环境需要走代理,那就要在/etc/yum.conf里配置好代理。
第二,确认源的gpgcheck设置。官方源的gpgcheck一般是1,这是为了校验软件包签名,防止被篡改,不建议关闭。
第三,如果公司内部有镜像源,可以用内网源替换默认源,速度会快很多。我之前在内网部署了一个龙蜥源的镜像,升级内核时下载速度能从几MB/s提升到上百MB/s。
2.3 磁盘空间与引导分区检查
内核升级会占用不少磁盘空间,特别是/boot分区,因为每个内核版本都会在/boot下生成 vmlinuz 和 initramfs 两个文件,加起来大概几十MB到上百MB。如果/boot分区当初分配得太小,升级完新内核后,旧的还来不及清理,很容易把分区撑爆。
检查命令:
# 查看各分区使用情况 df -h # 重点看 /boot 分区的剩余空间 df -h /boot # 查看 /boot 下已有的内核文件 ls -lh /boot/我的建议是:升级前保证/boot至少有200MB以上的空闲空间,/分区(或者说/usr分区)至少有2GB以上空闲。Anolis OS 8.6默认的/boot分区大小一般是1GB,如果你用的是默认分区方案,正常来说够用,但运行了一段时间后里面可能积累了不少旧内核文件,那就得先手动清理一下。
注意:清理旧内核的时候不要用
rpm -e一个个删,可能会出现依赖问题。建议用dnf remove --oldinstallonly或者手动保留最近两个版本,其余的统一移除。具体方法后面会展开讲。
3. 内核升级实操:在线与离线两种路径
3.1 在线升级:一条命令到最新稳定版
Anolis OS是基于RHEL 8体系构建的,软件管理走的是dnf(yum)。所以最直接的在线升级方法就是:
# 刷新软件源缓存 dnf makecache # 查看可用的内核包 dnf list available kernel # 安装最新内核 dnf install kernel -y执行完成后,系统会安装一个新的内核包,并自动为你生成对应的initramfs文件。需要注意,这时候新内核并不会立即生效,重启机器后默认进入的也不一定是新内核,需要手动指定引导项或设置默认内核。
另外,Anolis OS 8.6的官方源里,内核包是分拆的,除了kernel主包,还有kernel-core、kernel-modules、kernel-modules-extra等子包。安装kernel的时候会通过依赖关系自动把需要的子包装上,一般不需要手动干预。但如果你的业务需要某些特殊模块(比如文件系统驱动、网络过滤模块),升级后要检查一下kernel-modules-extra是否也更新到了同版本。
# 检查内核相关包的版本一致性 rpm -qa kernel\* | sort升级完成后,建议同步更新一下系统工具,避免新内核和旧用户态工具之间出现兼容性问题:
# 同步更新系统(不推荐在生产环境直接全量更新,但内核升级后建议更新相关工具) dnf update -y实际操作中,我不建议一上来就dnf update全量更新,那样变化范围太大,出了问题不好排查。更稳妥的做法是只升级内核和与之直接相关的包,观察一段时间没问题后再做其他更新。
3.2 指定版本内核安装与离线安装路径
有些时候你不能装最新版内核,比如业务方有特殊要求,或者内网环境与外网隔离,无法访问在线源。这时候就需要走指定版本安装或离线安装的路径。
先看看怎么装指定版本。假设你的软件源里有多个内核版本,可以用下面的命令查询:
# 查看源里所有可用的内核版本 dnf list kernel --showduplicates # 安装指定版本,比如 kernel-4.18.0-372.19.1.an8_5.x86_64 dnf install kernel-4.18.0-372.19.1.an8_5.x86_64 -y离线安装场景就比较麻烦了。常见的做法是,在一台能上网的Anolis机器上先下载好内核RPM包,再拷贝到内网机器上安装。
# 在联网机器上下载内核包(不安装,只下载) dnf download kernel kernel-core kernel-modules kernel-modules-extra --destdir=/tmp/kernel_rpms # 如果有依赖包没下载全,可以用下面的命令把依赖也一起下载 dnf download kernel* --resolve --alldeps --destdir=/tmp/kernel_rpms然后把/tmp/kernel_rpms下的所有rpm包拷贝到目标机器上,用本地安装:
# 在离线机器上安装本地rpm包 dnf install /tmp/kernel_rpms/*.rpm -y这里有个坑要特别提醒:离线安装时,如果内核的依赖包和目标机器上已有的包版本不一致,dnf可能会报依赖错误。解决办法是把依赖包也一并下载齐全,或者用--setopt=obsoletes=0选项避开某些过时包的冲突(这个操作有风险,不建议新手使用)。
3.3 内核模块与第三方驱动的兼容性处理
升级内核后,原来自行编译安装的内核模块(比如网卡驱动、GPU驱动、安全软件的内核模块)可能会失效,因为模块是针对特定内核版本编译的。这是内核升级里最容易翻车的地方。
处理思路是这样的:升级前先搞清楚有哪些第三方模块在运行:
# 查看当前加载的所有模块,标记一下哪些不是系统自带的 lsmod # 查看模块文件路径,如果是在 /lib/modules/xxx/extra 或 /lib/modules/xxx/updates 下,就是第三方编译的 find /lib/modules/$(uname -r)/ -type f -name "*.ko*" | grep -E "extra|updates"对于这些第三方模块,升级前要向厂商确认兼容性,或者把源码准备好,升级后重新编译。比较典型的像NVIDIA GPU驱动,每次内核升级后基本都要重新编译。Anolis OS的软件源里其实有适配好的NVIDIA驱动包,可以直接用dnf install nvidia-driver安装,但生产环境用的话,我还是建议走厂商官方支持渠道。
另外有个小技巧:如果某个第三方模块在新内核里编译不过去,你可以临时加载旧内核的模块文件夹到新内核下试试。这不是正规做法,但在应急场景下偶尔能救急。具体操作是:
# 找到旧内核模块目录 ls /lib/modules/ # 把旧内核模块软链接到新内核目录(谨慎使用,只能作为临时手段) ln -s /lib/modules/$(旧内核版本)/extra /lib/modules/$(新内核版本)/extra这个操作之后,需要重新生成initramfs才能生效:
dracut -f但说真的,这个应急方案问题很多,特别是内核抽象层(KABI)不兼容的情况下,强行加载旧模块可能导致内核崩溃,建议不到万不得已不要用。
4. 引导配置:让新内核真正生效
4.1 grubby:管理引导项的神器
内核装好了,重启之前必须先做一件事:确认新内核会被默认加载。如果不做配置,重启后系统可能还是进入旧内核,甚至直接进入救援模式(如果引导配置损坏的话)。
Anolis OS 8系列使用的是GRUB 2引导器,推荐的管理工具是grubby。这个工具比手动改grub.cfg安全得多,它会自动处理很多细节。
# 查看当前默认的内核引导项 grubby --default-kernel # 查看所有可用的内核引导项 grubby --info=ALL # 设置新内核为默认引导项 grubby --set-default=$(ls /boot/vmlinuz-* | tail -1) # 或者直接指定内核版本号 grubby --set-default=/boot/vmlinuz-4.18.0-372.32.1.an8_6.x86_64grubby --info=ALL的输出信息量很大,它会列出每个内核引导项的索引、内核路径、initrd路径、启动参数等。执行过之后你能清楚看到新版内核的入口信息。
4.2 手动调整GRUB配置文件
虽然grubby很方便,但有时候你也需要手动修改GRUB配置,比如调整内核启动参数、修改默认超时时间等。
GRUB 2的主配置文件路径是/etc/default/grub,里面的内容大致如下:
[root@anolis ~]# cat /etc/default/grub GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto spectre_v2=retpoline rhgb quiet" GRUB_DISABLE_RECOVERY="true"常用的几个配置项含义:
GRUB_TIMEOUT:开机时引导菜单等待时间,单位是秒。生产环境建议设置成5秒,既不影响开机速度,也留了手动选择内核的时间。GRUB_DEFAULT:默认启动项,可以是saved(记住上次选择)、数字索引或具体的菜单项名称。GRUB_CMDLINE_LINUX:内核启动参数。一般不需要动,但如果你的服务器要调整某些内核参数(比如关闭透明大页、调整IO调度器),就是通过改这里实现的。
修改完/etc/default/grub后,记得重新生成grub配置:
grub2-mkconfig -o /boot/grub2/grub.cfg注意,UEFI启动的机器输出路径不同:
grub2-mkconfig -o /boot/efi/EFI/anolis/grub.cfg怎么判断自己是BIOS还是UEFI启动?看有没有/sys/firmware/efi目录:
[ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS"4.3 设置默认启动项与开机超时
grubby设置默认内核以后,默认启动项就变了。如果想确认是否设置成功,可以执行:
grubby --default-kernel grubby --default-index其中一个细节值得注意:如果/etc/default/grub里的GRUB_DEFAULT=saved,那么系统每次启动时,默认加载的内核是grubby --set-default指定的那个;但如果你在GRUB菜单里手动选择了其他内核,下次开机默认会记住你上次的选择。这个行为默认是saved模式造成的,如果你希望无论上次选了啥,每次开机都固定进某个内核,可以把GRUB_DEFAULT改成具体的菜单项名称或索引数字。
# 查看当前默认启动项对应的菜单名称 grubby --info=$(grubby --default-kernel) | grep title # 将GRUB_DEFAULT设置为固定的菜单名称 sed -i 's/^GRUB_DEFAULT=.*/GRUB_DEFAULT="Anolis OS (4.18.0-372.32.1.an8_6.x86_64) 8.6"/' /etc/default/grub # 重新生成grub配置 grub2-mkconfig -o /boot/grub2/grub.cfg5. 升级后验证与回滚机制
5.1 验证新内核是否正常运行
重启之后,第一件事就是确认系统是否正常跑起来了,别急着高兴。我给自己定了一个检查清单:
# 1. 确认内核版本 uname -r # 2. 确认系统运行时间(如果uptime很短,说明重启过,正常) uptime # 3. 查看系统日志里有没有内核报错 dmesg | grep -i error journalctl -k -b | grep -i error # 4. 确认关键模块加载正常 lsmod | grep -E "ext4|xfs|virtio|e1000|igb|mlx" # 5. 确认网络、文件系统、服务状态 systemctl status network mount | grep -E " / | /boot"有时候uname -r显示的确实是新内核,但系统状态并不健康。我遇到过一种情况:新内核起来了,网络服务也重启了,但SELinux上下文错乱,导致很多服务无法正常启动。这种情况下通常要检查SELinux的状态,甚至可能需要用touch /.autorelabel触发文件系统重新打标签。
5.2 应用兼容性验证清单
系统层面没问题,不代表应用层面没问题。内核升级后,影响最大的几个应用层面是:
第一,容器运行时。如果你在跑Docker或Kubernetes,要重点关注cgroup版本和iptables规则的兼容性。新内核默认可能启用了cgroup v2(取决于内核编译选项),而旧版本的Docker不一定支持cgroup v2。验证的方式是:
docker info | grep -i cgroup cat /sys/fs/cgroup/cgroup.controllers第二,数据库和中间件。MySQL、Java应用这些对内核参数比较敏感,比如TCP拥塞控制算法、透明大页(THP)设置。升级后建议观察一段时间业务指标,对比升级前后的CPU、内存、IO性能数据。
第三,安全软件和监控agent。很多安全软件会加载内核模块或者依赖特定的syscall行为,内核升级后它们可能无法正常工作。我的建议是升级前就跟安全团队或厂商确认好兼容性。
5.3 出问题怎么回滚
如果新内核有问题,也不能慌。回滚的思路其实很简单:重启时在GRUB菜单里选择旧内核,或者用grubby重新设置旧的默认内核。
重启机器后,在GRUB引导菜单界面快速按下方向键或Esc键(不同版本按键不同),进入菜单选择界面,用上下键选中旧内核那一项,回车启动。
如果你人能进系统但想永久切回旧内核:
# 查看当前已有内核版本 grubby --info=ALL | grep -E "^kernel|^title" # 设置旧内核为默认引导项 grubby --set-default=/boot/vmlinuz-4.18.0-372.19.1.an8_5.x86_64 # 确认已切换 grubby --default-kernel如果新内核启动后系统都不稳定,没法正常进系统,那你只能在GRUB菜单里选择旧内核启动,然后重新执行grubby --set-default切回去。
回滚之后,建议先不要把新内核的rpm包删掉,留着观察一段时间。确认没问题后,再清理旧内核包或者决定是否重新升级。
6. 常见问题与排查技巧实录
6.1 重启后网络不通
这个是我遇到频率最高的问题。新内核起来了,但网络不通,SSH完全连不上,只能在控制台上操作。排查思路如下:
# 查看网卡是否识别 ip link show # 查看网卡驱动是否加载 ethtool -i eth0 # 查看NetworkManager状态 systemctl status NetworkManager # 如果网卡没起来,手动拉起试试 ip link set eth0 up dhclient eth0大部分情况下,网络不通是因为内核升级后网卡驱动模块没有自动加载。解决方法是找到匹配的驱动模块,手动加载:
modprobe igb # 以Intel I350为例如果驱动的确不存在,那就得回到旧内核启动,然后安装或编译匹配的驱动模块。
6.2 dracut生成的initramfs有问题
新内核安装后,默认会自动运行dracut生成initramfs文件。但如果dracut配置有问题,或者某些驱动模块没打进去,启动时就会出现mount: could not find root device之类的报错。
遇到这种情况,先别慌,从GRUB菜单进旧内核,然后手动重建initramfs:
# 重建当前默认内核的initramfs dracut -f # 重建指定内核版本的initramfs dracut -f /boot/initramfs-4.18.0-372.32.1.an8_6.x86_64.img 4.18.0-372.32.1.an8_6.x86_64重建完成后,再切回新内核启动一次。如果还是报mount root失败,大概率是根文件系统所在磁盘的驱动(比如nvme、sata、virtio驱动)没进initramfs,此时需要检查/etc/dracut.conf配置,确保必要的驱动被纳入。
6.3 旧内核清理与磁盘空间管理
系统里堆积了大量旧内核后,/boot分区很容易告警。Anolis OS 8系列默认有installonly_limit限制,系统里最多保留3个内核包,超过会自动清理。默认值虽然省心,但我建议在生产环境改成5,留出更多回滚余地。
# 查看当前installonly_limit值 grep installonly_limit /etc/dnf/dnf.conf # 修改为5(在/etc/dnf/dnf.conf中追加) echo "installonly_limit=5" >> /etc/dnf/dnf.conf手动清理旧内核(只保留当前用的和最新的一个):
# 查看已安装的内核包 rpm -qa | grep ^kernel # 删除指定旧版本(注意不要删除当前运行的内核版本) dnf remove kernel-4.18.0-372.19.1.an8_5.x86_64这里有个血泪教训:手动删除内核包的时候,一定要看清楚当前uname -r的版本,别把自己正在用的内核给删了。我见过有同事手一抖,把正在跑的版本删了,结果系统直接没法引导。如果真发生这种情况,只能通过光盘救援模式把内核包重装回去。
6.4 升级到新内核后性能反而下降
这种情况一般出现在有特殊硬件或特殊应用场景的机器上。新内核默认启用的特性可能不适用于你的业务,比如新内核默认开启的CPU频率调节策略、内存管理策略、透明大页选项等。
这时候排查思路是,先用以下命令看看当前内核参数:
# 查看CPU调频策略 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor # 查看透明大页状态 cat /sys/kernel/mm/transparent_hugepage/enabled # 查看TCP拥塞控制算法 sysctl net.ipv4.tcp_congestion_control根据业务场景,通过修改启动参数或运行时sysctl调整策略。比如对延迟敏感的数据库应用,可以禁用透明大页:
echo never > /sys/kernel/mm/transparent_hugepage/enabled如果要永久生效,就加到内核启动参数里:
grubby --update-kernel=ALL --args="transparent_hugepage=never"6.5 一个额外的建议:先在测试环境跑一遍
最后真心建议一句:内核升级这种事,千万别拿生产环境当第一个实验对象。有条件的,先在测试环境或者一台业务量小的机器上完整走一遍流程,包括升级、重启、验证、回滚测试,确认没问题了,再逐步扩大范围。
我自己维护的服务器有上百台,每次内核升级的节奏都是:先在测试机跑一遍,观察48小时,然后在非核心业务机器上跑,再观察48小时,最后才轮到核心业务机器。这套节奏看起来慢,但其实是最省时间的方式——因为出一次生产事故的时间,够你按这个节奏跑好几轮了。
个人经验是,Anolis OS的内核升级在整个Linux发行版里算是比较平滑的,毕竟它跟RHEL 8的体系一脉相承,rpm包管理和grub配置的逻辑都是标准的,只要你按照“查询现状-准备备份-安装内核-设置引导-重启验证-准备回滚”这条主线走下来,基本上不会出大问题。最后再分享一个小技巧:升级完内核后,别急着删旧内核,至少保留两个可用版本,这是你系统稳定运行的最后一道安全网。