说实话,很多 sysadmin 在听到“升级 AlmaLinux 8 到 9”时,第一反应都是后背发凉。为什么?因为 Linux 大版本升级这事儿,历来是“三分技术,七分运气,九次翻车,三次回滚”。我见过太多人抱着“我就点击一下升级,应该没问题吧”的侥幸心理,结果生产环境直接炸了,连 SSH 都连不上,最后不得不哭着去找备份。
今天咱们不整那些虚头巴脑的官方文档翻译,我就以一个在机房摸爬滚打多年的老兵身份,跟你掏心窝子聊聊这件事。我会把这条路上所有的坑、所有的雷、所有的备选方案,以及怎么带着数据安全着陆,统统掰开了揉碎了讲给你听。不管你是想原地升级(In-place Upgrade),还是更稳妥的“系统重装+数据迁移”方案,甚至是你正在纠结该选哪条路,这篇文章都能给你答案。
先别急着动手:为什么 AlmaLinux 9 这么特殊?
在动手之前,你得先明白你在挑战什么。AlmaLinux 9 和 AlmaLinux 8 之间,隔着的不仅仅是一个版本号,而是一整套底层技术栈的迭代。
核心变化:从 EL8 到 EL9 的鸿沟
AlmaLinux 是基于 RHEL(Red Hat Enterprise Linux)源码重建的社区发行版,所以它的升级路径和 CentOS Stream 9 / RHEL 9 是一致的。当你从 8 升到 9,你面对的是:
- 内核大跳跃:从 4.18 系列直接跳到 5.14+ 甚至更新的内核。这意味着硬件驱动、内核模块(比如 NVIDIA 显卡驱动、某些虚拟化模块)需要重新编译或适配。
- Python 版本升级:系统默认 Python 从 3.6 变成了 3.9。这是一个巨大的变动,因为很多旧的脚本、Ansible 模块、甚至是某些监控代理都是基于 Python 2 或 3.6 写的。
- GCC 版本提升:从 GCC 8 到 GCC 11,编译型软件需要重新构建。
- 虚拟化架构:KVM/QEMU 版本更新,libvirt 的 API 也有变化。
- 安全模块强化:SELinux 策略、Firewalld 规则、甚至 PAM 认证模块都可能发生变化。
升级路径的限制:只能相邻升级
这是最关键的一点,官方规定:你不能直接从 AlmaLinux 8 升级到 AlmaLinux 10(如果未来有的话)。你只能升级到下一个大版本。而且,你必须是基于 AlmaLinux release 8.x 的某个点,升级到 AlmaLinux release 9.x。
更重要的是,你不能跳过版本。如果你现在还在用 AlmaLinux 7(虽然已经 EOL 了),你不能直接升 9,必须先到 8,再到 9。
方案选择:原地升级 vs. 重装迁移
在深入细节之前,我必须先给你两个方案的利弊分析,因为这决定了你后面的所有操作。
方案 A:原地升级(In-place Upgrade)
适合场景:个人测试机、非核心业务服务器、你非常有信心能处理异常情况、或者没有备份条件。
优点:
- 速度快,不需要恢复数据。
- 所有用户配置、防火墙规则、定时任务、自定义脚本都保留。
缺点:
- 风险极高。升级过程中任何一步出错,系统可能直接进入 rescue mode,甚至彻底崩盘。
- 依赖关系复杂,yum/dnf 的事务处理可能会遇到依赖地狱。
- 一旦升级失败,回滚极其困难(除非你有快照)。
方案 B:系统重装 + 数据迁移(Recommended)
适合场景:生产环境、核心数据库服务器、有重要业务数据的机器、你对稳定性要求极高。
优点:
- 干净利落。新系统没有任何历史包袱,不会有残留的旧配置冲突。
- 可控性强。你可以在新系统上慢慢迁移数据,验证一切正常后再切换。
- 可回滚。如果新系统出问题,随时可以切回旧系统。
缺点:
- 工作量大,需要时间恢复数据、重新配置服务。
- 需要额外的存储空间或另一台机器作为过渡。
我的建议:如果是生产环境,请务必选择方案 B。原地升级就像是在高速公路上给汽车换引擎,理论上可行,但风险太大了。接下来,我会重点讲方案 B 的详细流程,并穿插原地升级的注意事项。
第一阶段:升级前的准备(无论选哪个方案都必需)
不管你是原地升级还是重装,这一步是决定你能不能活下来的关键。90% 的升级失败,都是因为准备不足。
1.1 完整的系统备份
这不是建议,这是命令。你需要做的是:
# 使用 rsync 备份关键目录到外部存储或另一台机器
rsync -avz --progress /etc/ /mnt/backup/etc-alma8-backup/
rsync -avz --progress /home/ /mnt/backup/home-alma8-backup/
rsync -avz --progress /var/www/ /mnt/backup/var-www-alma8-backup/
rsync -avz --progress /var/lib/mysql/ /mnt/backup/var-lib-mysql-alma8-backup/ # 如果是数据库服务器
# 备份 yum 包列表,方便后续排查
rpm -qa --qf '%{NAME}\n' | sort > /tmp/packages-alma8.txt
cp /etc/yum.repos.d/*.repo /mnt/backup/yum.repos.d-backup/
如果是云服务器,务必先创建快照!这是你最后的救命稻草。如果物理机,确保你有外部存储可以挂载。
1.2 检查当前系统状态
在升级前,确保你的 AlmaLinux 8 是最新的。
# 检查是否有未完成的更新
sudo dnf check-update
# 确保所有包都是最新的
sudo dnf update -y
sudo reboot # 如果有内核更新,重启一下
# 检查是否有第三方源冲突
sudo dnf repolist all
常见坑位:很多服务器安装了 EPEL、Remi、Nginx 官方源等第三方源。在升级到 9 之前,你必须检查这些源是否有对应的 EL9 版本。如果没有,你必须在升级后重新配置,或者暂时禁用它们。
1.3 清理系统垃圾
减少不必要的包可以降低升级失败的概率。
# 清除缓存
sudo dnf clean all
# 检查并删除孤儿包(可选,但推荐)
sudo dnf autoremove --assumeno
1.4 记录关键配置
很多配置不会自动迁移,你需要手动记录:
- YUM/DNF 源列表:
cat /etc/yum.repos.d/*.repo - 防火墙规则:
sudo firewall-cmd --list-all - SELinux 状态:
getenforce - 已安装的 RPM 包:
rpm -qa > installed-packages.txt - 系统服务状态:
systemctl list-units --type=service --state=running > running-services.txt - 自定义脚本位置:
/etc/cron.d/,/etc/systemd/system/ - 数据库权限和用户:如果是 MySQL/MariaDB,导出所有数据库用户和权限。
第二阶段:原地升级流程详解(如果你非要这么做)
好,如果你坚持要原地升级,那我们就一步步来。请记住,每一步都要小心,每一步都要有心理准备。
2.1 安装 Preupgrade 工具
AlmaLinux 9 提供了一个工具叫 preupgrade,但更常用的是 Leapp 工具。
# 安装 leapp 和所需的包
sudo dnf install -y leapp leapp-upgrade leapp-data-almalinux
2.2 运行预检查
这是最重要的步骤,它会告诉你哪些东西会导致升级失败。
sudo leapp preupgrade
这个过程会生成一个详细的报告,保存在 /var/log/leapp/leapp-report.txt。你需要仔细阅读这个报告,它会列出所有需要手动处理的问题。
常见预检查失败原因及解决方案:
第三方内核模块:如果你安装了 NVIDIA 驱动、VirtualBox 内核模块等,它们可能不兼容 EL9 的内核。你需要先卸载它们,或者找到支持 EL9 的版本。
# 检查已加载的内核模块 lsmod | grep -E 'nvidia|virtualbox|vbox'旧版 Python 脚本:某些依赖 Python 2 的脚本会导致失败。你需要找出这些脚本并修改或删除。
EPEL 版本问题:确保你的 EPEL 源是最新的,并且支持 EL9。如果只有 EL8 的源,你需要先升级 EPEL。
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm第三方软件源:如前面所说,检查是否有不支持 EL9 的源。
2.3 处理预检查报告中的问题
根据 leapp-report.txt 的提示,逐一解决问题。例如,如果报告说某个包是阻碍,你就需要卸载它。
# 假设报告说某个软件包有冲突
sudo dnf remove <problematic-package>
2.4 开始升级
所有问题都解决后,就可以开始升级了。
sudo leapp upgrade
这个过程会下载大量的包,可能需要很长时间,取决于你的网络和服务器性能。请耐心等待。
2.5 重启并安装新内核
升级完成后,系统会提示你重启。
sudo reboot
重启后,你需要在 GRUB 菜单中选择新的 AlmaLinux 9 内核。如果默认进入的是旧内核,你可能需要手动选择。
2.6 升级后的检查
系统启动后,立即检查系统状态:
# 确认系统版本
cat /etc/os-release
# 检查内核版本
uname -r
# 检查是否有遗留的错误
journalctl -xb | grep -i error
# 重新加载防火墙规则
sudo firewall-cmd --reload
# 检查关键服务是否正常运行
sudo systemctl status sshd nginx mysql # 根据你的服务调整
2.7 处理 Python 和依赖问题
这是原地升级后最常见的坑。很多服务可能因为 Python 版本变化而无法启动。
# 检查 Python 版本
python3 --version
# 如果有应用依赖旧版 Python,你可能需要安装 pyenv 或从源码编译特定版本
第三阶段:系统重装 + 数据迁移流程(强烈推荐)
这是更稳妥的方案。我会以一台 Web 服务器为例,展示如何从 AlmaLinux 8 迁移到 AlmaLinux 9。
3.1 准备新系统
在新服务器上安装 AlmaLinux 9。你可以从官方镜像站下载最新的 ISO 进行最小化安装。
# 安装基础系统
# 这里省略具体的安装步骤,因为网上教程很多
安装完成后,更新系统。
sudo dnf update -y
sudo reboot
3.2 迁移用户数据
使用 rsync 将旧系统的数据同步到新系统。
# 在新系统上创建目标目录
sudo mkdir -p /mnt/backup-restore
# 挂载旧系统的数据盘,或者通过 SSH 从旧系统同步
# 假设旧系统 IP 是 192.168.1.100
rsync -avz --progress root@192.168.1.100:/home/ /mnt/backup-restore/home/
rsync -avz --progress root@192.168.1.100:/var/www/ /mnt/backup-restore/var-www/
rsync -avz --progress root@192.168.1.100:/etc/nginx/ /mnt/backup-restore/etc-nginx/
rsync -avz --progress root@192.168.1.100:/var/lib/mysql/ /mnt/backup-restore/var-lib-mysql/
3.3 迁移配置文件
配置文件不能直接拷贝,因为某些配置语法在新版本中可能变了。你需要逐一检查。
# 例如,nginx 配置
sudo cp -r /mnt/backup-restore/etc-nginx/* /etc/nginx/
# 检查 nginx 配置语法
sudo nginx -t
3.4 迁移数据库
数据库迁移是最复杂的部分。我推荐两种方法:
方法一:逻辑备份恢复
# 在旧系统上导出所有数据库
sudo mysqldump --all-databases --single-transaction --routines --triggers > /tmp/all-databases.sql
# 传输到新系统
rsync /tmp/all-databases.sql root@new-server:/tmp/
# 在新系统上导入
sudo mysql < /tmp/all-databases.sql
方法二:物理备份恢复(更快,但风险稍高)
如果数据库很大,逻辑备份太慢,可以使用物理备份。但要注意,MySQL 8.0 和 MySQL 5.7 的数据文件可能不兼容。AlmaLinux 9 默认使用 MariaDB 10.5 或 MySQL 8.0,你需要确保版本兼容。
3.5 迁移应用代码和依赖
如果运行的是 Python 应用,使用 pip 冻结依赖列表。
# 在旧系统上
pip freeze > requirements.txt
# 传输到新系统
rsync requirements.txt root@new-server:/path/to/app/
# 在新系统上安装
pip install -r requirements.txt
如果是 Node.js 应用:
rsync package.json package-lock.json root@new-server:/path/to/app/
npm install
3.6 迁移定时任务
# 在旧系统上备份 crontab
crontab -l > cron-backup.txt
# 传输到新系统
rsync cron-backup.txt root@new-server:/tmp/
# 在新系统上恢复
cat /tmp/cron-backup.txt | crontab -
3.7 迁移 systemd 服务
如果旧系统有自定义的 systemd 服务,需要复制并调整。
# 在旧系统上
systemctl list-units --type=service --all | grep enabled > enabled-services.txt
# 在新系统上安装相同的包,并启用服务
sudo dnf install <packages>
sudo systemctl enable <service>
3.8 测试和验证
在切换流量之前,你需要在新系统上进行充分的测试。
- 检查所有服务是否正常启动。
- 测试网站是否可以正常访问。
- 测试数据库查询是否正常。
- 测试定时任务是否执行。
- 检查日志文件是否有错误。
# 检查系统日志
sudo journalctl -xe
# 检查应用日志
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/messages
3.9 切换流量
一切测试通过后,你就可以将 DNS 指向新服务器,或者修改 /etc/hosts 进行内部切换。
第四阶段:常见坑位及避坑指南
坑位 1:第三方源的兼容性问题
问题描述:很多服务器安装了 EPEL、Remi、Nginx 官方源、Docker 官方源等。这些源在 EL8 上工作正常,但在 EL9 上可能不存在或版本不匹配。
解决方案:
- 在升级前,列出所有第三方源:
ls /etc/yum.repos.d/ - 检查每个源是否有 EL9 版本。
- 如果没有,在升级后重新配置。例如,Docker 源在 EL9 上可能需要重新添加。
- 对于 EPEL,直接使用最新版本的 release 包。
坑位 2:Python 依赖地狱
问题描述:很多系统工具和应用依赖特定版本的 Python。升级到 EL9 后,系统默认 Python 变成 3.9,可能导致旧脚本失效。
解决方案:
- 使用
pyenv安装多个 Python 版本。 - 对于依赖 Python 2 的老旧脚本,考虑重写或使用容器运行。
- 检查
/usr/bin/python和/usr/bin/python3的链接。
# 检查 Python 链接
ls -l /usr/bin/python*
坑位 3:内核模块不兼容
问题描述:NVIDIA 显卡驱动、VirtualBox 模块、某些 RAID 卡驱动等,在 EL9 的新内核上可能无法加载。
解决方案:
- 升级前,检查所有加载的内核模块:
lsmod - 查找对应模块是否有 EL9 的兼容版本。
- 如果没有,考虑使用容器或虚拟机替代。
坑位 4:SELinux 策略变化
问题描述:SELinux 策略在 EL9 中有较大变化,可能导致某些应用无法访问文件或网络。
解决方案:
- 升级后,使用
ausearch -m avc -ts recent检查 SELinux 拒绝记录。 - 使用
audit2allow生成自定义策略。 - 暂时将 SELinux 设置为 permissive 模式进行测试,但不要长期保持。
坑位 5:防火墙规则重置
问题描述:Firewalld 的配置可能在升级过程中丢失或重置。
解决方案:
- 升级前,导出防火墙规则:
firewall-cmd --runtime-to-permanent - 备份
/etc/firewalld/目录。 - 升级后,重新导入规则。
# 备份防火墙配置
sudo cp -r /etc/firewalld /etc/firewalld-backup-alma8
# 恢复防火墙配置
sudo cp -r /etc/firewalld-backup-alma8/* /etc/firewalld/
sudo firewall-cmd --reload
