上一篇 下一篇 分享链接 返回 返回顶部

如何在香港服务器中进行操作系统内核升级,避免驱动兼容性和内核参数冲突带来的系统崩溃?

发布人:Minchunlin 发布时间:2025-08-17 09:25 阅读量:903


我在香港葵涌数据中心做夜间变更,机房温度恒定在 22℃,风机声像白噪音。值班工程师递来纸杯咖啡,我盯着 iDRAC 的 KVM 窗口,左手 SSH,右手工单。目标很简单:把一批 CentOS 7 的宿主机内核从 3.10 升到 5.x LTS,既要让 Intel X710 和 Mellanox 25G 卡稳定工作,又不能把阵列卡和 NVMe 启动盘“整丢”。这篇文章就是那次升级的完整复盘和标准化流程,保守、可回滚,兼顾新手和老手。

适用对象与我的环境说明

适用: 裸金属/虚拟化宿主(KVM、Docker、K8s 边缘节点)运行 CentOS 7(兼容 Rocky/Alma 8/9 的方法也能借鉴)。

目标: 通过 ELRepo 升级到 kernel-lt(长期支持)或 kernel-ml(主线),全过程确保:

  • 引导介质(SATA / NVMe / RAID LUN)可识别;
  • 关键网卡(Intel X710 i40e、Mellanox mlx5)驱动稳定;
  • 常见 out-of-tree 模块(ZFS、NVIDIA、DRBD、WireGuard)有解;
  • 内核参数与 sysctl 不冲突,避免启动/运行时崩溃。

我的现场硬件(样例一台“金丝雀”主机):

组件 型号/固件 关键驱动 是否内核内置
机型 Dell R650 (BIOS 1.9.x)
CPU Xeon Silver 43xx microcode 按发行版
RAID LSI/Broadcom 9361-8i (FW 4.68) megaraid_sas
启动盘 Intel P4510 NVMe nvme,nvme_core
25G 网卡 Mellanox ConnectX-4 Lx mlx5_core
10G 网卡 Intel X710 i40e
带外 iDRAC9 / IPMI

金丝雀策略:先挑一台非关键业务的“同构”主机升级(网络/存储/固件相同),把所有坑踩完,再批量灰度。

1. 升级总体策略

  • 最小风险路线:ELRepo kernel-lt(5.4 LTS 族)优先,其次 kernel-ml(主线新特性多、变动也多)。
  • 双保险:保留旧内核、设默认启动为旧内核,第一次重启手动选择新内核验证;通过串口/带外留后路。
  • 驱动优先:先看驱动、再谈内核。凡是 out-of-tree 的模块(DKMS)必须先确认支持目标内核。
  • initramfs 冗余:对启动关键驱动 dracut --add-drivers 打进新 initramfs,必要时 nohostonly 全打。
  • 参数保守:核查 grub 启动参数与 /etc/sysctl.d/*,避免重复/相反配置导致启动慢/挂起/软中断飙升。

2. 变更前“摸底”与风险矩阵

先跑一段脚本把资产和风险点抓干净,我现场就这么干的:

#!/usr/bin/env bash
set -euo pipefail
OUT=/root/preflight_$(hostname)_$(date +%F_%H%M).tar.gz
mkdir -p /root/preflight && cd /root/preflight

echo "# uname & os" > sys.txt
uname -a >> sys.txt
cat /etc/redhat-release >> sys.txt

echo -e "\n# cpu & mem" >> sys.txt
lscpu >> sys.txt
free -h >> sys.txt

echo -e "\n# block" >> sys.txt
lsblk -o NAME,SIZE,TYPE,MODEL,ROTA,TRAN,MOUNTPOINT >> sys.txt

echo -e "\n# pci" >> sys.txt
lspci -nnk >> pci.txt

echo -e "\n# modules" >> sys.txt
lsmod | sort >> modules.txt

echo -e "\n# dkms" >> sys.txt
command -v dkms && dkms status || echo "dkms not installed" >> sys.txt

echo -e "\n# network" >> sys.txt
ip -br a >> sys.txt
ethtool -i eth0 2>/dev/null >> sys.txt || true
ethtool -i eth1 2>/dev/null >> sys.txt || true

echo -e "\n# grub/cmdline" >> sys.txt
cat /proc/cmdline >> sys.txt

echo -e "\n# sysctl" >> sys.txt
sysctl -a | sort > sysctl_dump.txt

tar czf "$OUT" *
echo "Saved to $OUT"

风险矩阵(从易到难):

领域 风险 典型表现 预防/处置
引导存储 initramfs 没有 nvme / megaraid_sas dracut emergency、找不到根分区 dracut --add-drivers 重建;必要时 nohostonly
网卡 驱动版本与固件不配 链路 flap、丢包、Rx no-buffer 固件先行、核对 ethtool -i;必要时固定 i40e 版本
DKMS ZFS/DRBD/NVIDIA 不支持新内核 模块编译失败、服务起不来 升级 DKMS 版本或 pin 内核 先不升
容器 cgroup/iptables 行为差异 容器启动慢、网络策略异常 保持 cgroup v1(CentOS 7 默认),避免混用 nft
内核参数 grub 与 sysctl 冲突 启动卡顿、NUMA/THP 异常 参数合并,确保唯一来源
固件 HBA/NIC 旧固件 + 新驱动 间歇性 IO/网断 先窗口升级固件(带回滚)

3. 准备:回滚与带外通道是升级的“安全带”

备份与救援

重要配置:/etc、/boot、/var/lib/docker(如容器)、业务配置。

内核与 grub:

cp -a /boot /boot.bak.$(date +%F)
awk -F\' '/^menuentry / {print NR-1 " : " $2}' /etc/grub2.cfg

有条件用 全盘镜像/LVM 快照;没有就准备好 救援 ISO(带外虚拟介质可挂载)。

带外可用性

iDRAC/IPMI 测试电源控制 & SOL(串口 over LAN):

ipmitool -I lanplus -H <bmc-ip> -U <user> -P <pass> power status
ipmitool -I lanplus -H <bmc-ip> -U <user> -P <pass> sol activate

维护窗口与回退标准

明确回退判据:新内核下出现(任一)严重丢包/存储异常/核心业务指标劣化 ≥10% 即回退。

灰度节奏:金丝雀 → 5% → 25% → 100%,每步观察≥1 个业务周期。

4. 选择内核与启用 ELRepo

我的经验:先选 kernel-lt(LTS),除非你明确需要主线特性(如最新硬件支持)再上 kernel-ml。

# 1) 导入 ELRepo
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm

# 2) 安装 kernel-lt 或 kernel-ml(二选一)
yum --enablerepo=elrepo-kernel install -y kernel-lt
# 或
# yum --enablerepo=elrepo-kernel install -y kernel-ml

# 3) 查看已安装内核
rpm -qa | grep -E 'kernel-(lt|ml)'

不要卸载旧内核。 先保留两代以上。

5. 关键驱动版本核对(网卡/存储为先)

5.1 网卡

# Intel X710
ethtool -i ens1f0
# 关注 driver: i40e, version, firmware-version

# Mellanox ConnectX-4/5
ethtool -i ens2f0
# 关注 driver: mlx5_core, firmware-version

经验要点:

固件要与驱动匹配。X710 某些旧固件 + 新 i40e 会 Link flap;Mellanox 建议先用官方工具把固件升到近几年稳定版(如需)。

生产中尽量使用内核自带驱动。除非被特性卡住,再考虑厂商 out-of-tree 驱动(会增加后续维护成本)。

5.2 存储/HBA/RAID/NVMe

lspci -nnk | egrep -i 'raid|sas|nvme'
modinfo megaraid_sas | egrep 'version|vermagic' || true

NVMe 启动盘:确保新 initramfs 带有 nvme、nvme_core。

RAID/HBA:megaraid_sas、mpt3sas 等必须在 initramfs 内,否则进不了根文件系统。

6. 为新内核重建 initramfs(把要命的驱动“焊死”进去)

# 找到新内核版本号
NEWKVER=$(rpm -q --qf '%{VERSION}-%{RELEASE}.%{ARCH}\n' kernel-lt | tail -n1)

# 方案A:最稳妥(全量驱动、镜像大但稳)
dracut -f --kver "$NEWKVER" --no-hostonly

# 方案B:定点加驱动(镜像小、可控)
dracut -f --kver "$NEWKVER" --add-drivers "nvme nvme_core megaraid_sas mlx5_core i40e"

小贴士:如果你的根盘在 LVM/MD/Multipath 上,也把对应驱动加进去(例如 dm_mod, dm_multipath)。

7. 整理内核参数与 sysctl,避免“打架”

7.1 GRUB 启动参数统一

编辑 /etc/default/grub(CentOS 7):

# 示例(按需取舍,不要照搬)
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet \
intel_pstate=disable \
transparent_hugepage=never \
numa_balancing=disable \
rd.driver.pre=nvme rd.driver.pre=megaraid_sas"

生成配置(BIOS 与 UEFI 二选一):

# BIOS:
grub2-mkconfig -o /boot/grub2/grub.cfg
# UEFI:
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

只保留一处生效的设置。如果你把 THP 设为 never,就不要再在 rc.local/sysfs 里重复 echo。唯一来源原则能省掉大量诡异问题。

7.2 sysctl 规范化

放到 /etc/sysctl.d/99-tuning.conf:

# 网络缓冲/连接跟踪按需(示例)
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.core.netdev_max_backlog = 250000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65000

# vm
vm.swappiness = 10
vm.max_map_count = 262144
sysctl --system

避免冲突:确认不存在多个 .conf 文件设置同一 key 且值不同;sysctl -a | grep <key> 二次核对。

8. 设定启动顺序与超时、串口后门

# 把旧内核设为默认(第一次重启手选新内核)
grub2-set-default 0   # 0 通常是旧内核,具体用下面命令列出确认
awk -F\' '/^menuentry / {print NR-1 " : " $2}' /etc/grub2.cfg

# 给自己留 5 秒菜单选择时间
sed -ri 's/^GRUB_TIMEOUT=.*/GRUB_TIMEOUT=5/' /etc/default/grub
grub2-mkconfig -o /boot/grub2/grub.cfg

串口控制台(可选,救命稻草)

在 GRUB_CMDLINE_LINUX 追加:

console=tty0 console=ttyS0,115200n8

9. 窗口执行(分钟级 Runbook)

T-10 分钟:

  • 通知业务降流/摘除单点;开启带外 KVM;确认回退标准。
  • 关闭非必要服务(例如批处理任务)。

T-5 分钟:

# 切到单用户(可选)或维持多用户但停大负载
systemctl stop <heavy-service1> <heavy-service2>

T-0 分钟(安装已完成,开始验证并重启):

# 再次核对新内核 initramfs 存在
ls -lh /boot/initramfs-$NEWKVER.img

# 重启
reboot

T+2 分钟(GRUB 菜单):

手动选择新内核(旧内核仍为默认),观察启动日志是否卡在 dracut/A start job is running for dev-...。

T+5 分钟(登录后健康检查):

uname -r
dmesg -T | egrep -i 'error|fail|nvme|megaraid|i40e|mlx5' | tail -n 200
lsblk
mount | column -t
ip -br a
ethtool -S eth0 | egrep 'rx_(errors|missed)|tx_errors' | tail

T+10 分钟(回归测试):

网络:iperf3(同机房对端),丢包/吞吐稳定;

存储:fio 小压测(顺序/随机读写 1~3 分钟级);

业务:核心接口 QPS、P99、错误率。

一切正常 → 用新内核设为默认:

grubby --default-kernel
# 输出还是旧内核?那就切换:
grubby --set-default /boot/vmlinuz-$NEWKVER
grubby --default-kernel

10. 我踩过的坑与现场解法

坑 1:X710 链路抖动(i40e)

症状:升级后 dmesg 反复 NIC Link is Down/Up,ethtool -S 里 rx_no_buffer_count 增长。

解法:

先升级网卡固件到与驱动兼容的稳定版;

临时缓解:调大 ring buffer、关不成熟 offload:

ethtool -G eth0 rx 4096 tx 4096
ethtool -K eth0 lro off gro on gso on tx-udp-segmentation off

特定旧固件可 pin 到稳定 i40e 版本,或换 kernel-lt 而非 ml。

坑 2:initramfs 未包含 megaraid_sas 导致进不了根

症状:dracut emergency,找不到 root=... 设备。

解法:用救援介质进入后:

mount /dev/sdXn /mnt/sysroot
mount -t proc /proc /mnt/sysroot/proc
mount --rbind /sys /mnt/sysroot/sys
mount --rbind /dev /mnt/sysroot/dev
chroot /mnt/sysroot
dracut -f --kver "$NEWKVER" --add-drivers "megaraid_sas"

坑 3:ZFS DKMS 编不过

症状:dkms build 失败、zpool 无法导入。

解法:先不要升内核,或同步升级到支持该内核的 ZFS 版本;必要时把数据临时迁出再变更。

坑 4:THP 与数据库冲突

症状:PostgreSQL/ES 吞吐抖、延迟突刺。

解法:统一在 GRUB 里 transparent_hugepage=never,删除所有重复 sysfs 脚本。

11. 变更后对照表(我会留档到工单里)

11.1 驱动与固件对照

设备 变更前 变更后 备注
i40e v2.12.x v2.18.x flap 消失,rx_no_buffer 归零
mlx5_core 4.9x 5.xx 固件同步升级
megaraid_sas 07.7x 07.7x(内核内置) initramfs 手动加入
nvme 内核 3.10 版 5.4 版 队列深度更优

注:表中版本为样例,实际以 ethtool -i/modinfo 输出为准。

11.2 参数差异

变更前 变更后 理由
GRUB rhgb quiet rhgb quiet transparent_hugepage=never numa_balancing=disable 数据库/延迟敏感
sysctl 默认 调大 net backlog/缓冲 10G/25G 低丢包
tuned balanced throughput-performance I/O 吞吐型负载

12. 批量化与自动化(生产必备)

当金丝雀验证通过,我会用 Ansible 批量推进,核心任务包括:

  • 安装 ELRepo & kernel;
  • 重建 initramfs(按硬件画像选择 --add-drivers);
  • 模板化 /etc/default/grub 与 /etc/sysctl.d/99-tuning.conf;
  • 统一 grub2-mkconfig 并把 默认内核仍指向旧版;
  • 编排重启顺序(成对/跨机架/跨 ToR 冗余);
  • 变更后自动跑 dmesg、ethtool -S、fio、iperf3 并回传报表。

13. 常用命令速查(可直接贴工单)

# 查看所有内核菜单项
awk -F\' '/^menuentry / {print NR-1 " : " $2}' /etc/grub2.cfg

# 设定默认内核(确认路径)
grubby --default-kernel
grubby --set-default /boot/vmlinuz-<VERSION>

# 查询网卡驱动/固件
ethtool -i ethX

# 观察错误计数
ethtool -S ethX | egrep 'errors|dropped|missed|no_buffer'

# 重建 initramfs(全量)
dracut -f --kver <VERSION> --no-hostonly

# 重建 initramfs(定点加驱动)
dracut -f --kver <VERSION> --add-drivers "nvme nvme_core megaraid_sas mlx5_core i40e"

# 生成 grub(BIOS/UEFI 选其一)
grub2-mkconfig -o /boot/grub2/grub.cfg
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

# 内核/模块版本
uname -r
modinfo <module>

14. 收尾与复盘

那晚 02:40,我把金丝雀主机切回默认用新内核,链路指标稳定、fio 的 P99 抖动比升级前更小。回旅馆的电梯里,我在手机上补完了“驱动/固件/参数对照表”和“回退判据”,第二晚就按灰度表推进剩余节点。
结论很朴素:驱动优先、参数单一来源、initramfs 冗余——把这三件事做到位,内核升级这类“高危操作”就会变成可控的日常维护。

附:最小可用流程(给赶时间的人)

做带外、备份、救援盘准备;

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

dracut -f --kver <NEW> --add-drivers "nvme nvme_core megaraid_sas mlx5_core i40e";

统一 GRUB_CMDLINE_LINUX,生成 grub;

默认仍旧内核 → 重启手动选新内核;

通过健康检查 → grubby --set-default /boot/vmlinuz-<NEW>;

灰度批量推进、复盘表留档。

目录结构
全文