Ubuntu系统升级要做到"平滑过渡、业务不中断",核心思路就三步:先做完整备份和快照,再用分阶段滚动升级替代一次性全量更新,最后把重启安排在业务低峰窗口并配合自动化脚本完成。很多运维人员直接执行do-release-upgrade然后等重启,这是最危险的做法——一旦内核不兼容或者服务启动失败,你连回退的机会都没有。下面我把从评估、备份、升级、验证到重启的全流程拆开讲,每一步都给你具体命令和注意事项。
一、升级前的全面评估与环境摸底在动手之前,你必须先搞清楚当前系统的状态。很多人跳过这一步直接升级,结果发现依赖包冲突或者硬件驱动不支持新内核,被迫紧急回滚。具体操作如下:
首先查看当前Ubuntu版本和内核信息:
lsb_release -a uname -r cat /etc/os-release
然后检查已安装的关键服务和它们的依赖关系:
systemctl list-units --type=service --state=running dpkg --get-selections | grep -v deinstall > /tmp/package-list.txt
把这些信息存下来,升级后做对比用。特别要注意的是,如果你用了第三方PPA源或者非官方源,升级前一定要禁用或者评估兼容性。执行以下命令查看第三方源:
ls /etc/apt/sources.list.d/ grep -r "^deb" /etc/apt/sources.list /etc/apt/sources.list.d/
另外,如果服务器跑了Docker、KVM虚拟机或者数据库集群,这些都需要单独评估升级影响。Docker容器一般不受宿主系统升级影响,但内核升级后可能导致容器网络异常,需要提前测试。
二、完整备份策略——这一步决定你能不能睡安稳觉备份不是可选项,是必选项。我见过太多人因为没备份,升级失败后花三天重建环境。备份要做到三层:系统快照、配置文件、数据。
如果你用的是虚拟机(VMware、KVM、Proxmox),直接在升级前打一个完整快照,这是最快的回退手段。如果是物理机,用Timeshift或者rsync做系统级备份:
sudo apt install timeshift sudo timeshift --create --comments "Before Ubuntu upgrade" sudo rsync -avz /etc /root/etc-backup-$(date +%Y%m%d)/
数据库方面,MySQL/PostgreSQL在升级前必须做全量导出:
mysqldump --all-databases --single-transaction -u root -p > /backup/mysql-full-$(date +%Y%m%d).sql pg_dumpall -U postgres > /backup/pg-full-$(date +%Y%m%d).sql
配置文件单独备份一份,特别是/etc/network/、/etc/fstab、/etc/hosts、Nginx/Apache的虚拟主机配置。这些文件在升级过程中可能被覆盖或者修改,丢了就很麻烦。
三、平滑升级的核心方法——分阶段滚动升级Ubuntu官方推荐的do-release-upgrade是一次性跨版本升级,比如从20.04直接跳到22.04。这种方式风险高,因为跨度大、变化多。更稳妥的做法是逐级升级,每次只升一个LTS版本。
第一步,先把当前系统的所有包更新到最新:
sudo apt update sudo apt upgrade -y sudo apt dist-upgrade -y sudo apt autoremove -y
第二步,执行版本升级。如果你是20.04,先升到22.04:
sudo do-release-upgrade -c
如果你想更保守,可以先用-d参数升级到最新的开发版测试,确认没问题再正式升级。升级过程中会弹出很多交互提示,关于配置文件的处理,建议选择"保持当前版本"(N),除非你明确知道新版本的配置格式变化。
第三步,升级完成后不要立刻重启,先验证核心服务状态:
systemctl status sshd systemctl status nginx systemctl status docker systemctl status mysql
如果你管理的是多台服务器,不要同时升级所有机器。采用滚动升级策略:先升级一台测试机,观察24-48小时没问题,再逐步推广到生产环境。具体做法是按业务分组,每组间隔至少一周。
四、内核升级的单独处理——别让内核拖后腿很多时候Ubuntu版本升级了,但内核没有自动更新到最新的HWE(Hardware Enablement)内核。这会导致新硬件不支持或者安全补丁缺失。手动安装HWE内核:
sudo apt install --install-recommends linux-generic-hwe-22.04 sudo reboot
重启后确认内核版本:
uname -r
如果你需要回退内核,在GRUB启动菜单选择旧内核即可。建议保留至少两个旧内核版本,给自己留后路。
五、重启计划的制定与执行——把影响降到最低重启是升级流程中对业务影响最大的环节。制定重启计划要考虑三个维度:时间窗口、通知机制、回退预案。
时间窗口选择:通常选在凌晨2点到5点之间,这是大多数业务的最低谷。如果是面向全球用户的服务,要选一个对主要用户群体影响最小的时段,可能需要跨时区协调。
通知机制:提前48小时发通知,提前24小时再确认,提前2小时发最终提醒。通知内容要包含:预计中断时间、影响范围、联系方式、回退方案。
自动化重启脚本可以减少人为失误。以下是一个实用的重启前检查脚本:
#!/bin/bash echo "=== Pre-reboot Check ===" echo "1. Checking disk space..." df -h / | tail -1 echo "2. Checking memory..." free -h echo "3. Checking running services..." systemctl is-system-running echo "4. Checking pending updates..." apt list --upgradable 2>/dev/null | wc -l echo "5. Checking swap..." swapon --show echo "=== Check Complete ==="
重启执行时,如果你有负载均衡或者集群架构,先把流量从目标机器切走,再执行重启。单台服务器可以用以下命令做优雅重启:
sudo systemctl reboot
如果需要定时重启,可以用at命令:
echo "sudo systemctl reboot" | at 03:00 2024-12-20六、升级后验证与监控——别以为重启完就结束了
重启完成后,第一时间登录检查。重点验证以下内容:
网络连通性:
ping -c 4 8.8.8.8 ip addr show ss -tlnp
服务启动状态:
systemctl --failed journalctl -xb | grep -i error | tail -20
应用访问测试:用curl或者浏览器实际访问你的Web服务、API接口,确认功能正常。数据库连接测试:
mysql -u root -p -e "SELECT 1" psql -U postgres -c "SELECT 1"
接下来72小时要加强监控,重点关注CPU、内存、磁盘IO、网络流量的异常波动。如果用了Prometheus+Grafana,可以临时加一个升级监控面板,把关键指标的阈值调紧一些。
七、常见坑点与独家经验总结根据我多年的运维经验,以下几个坑是最容易踩的:
第一,SSH配置升级后可能导致远程连接失败。升级前确保/etc/ssh/sshd_config里没有被注释掉的旧参数,升级后第一时间验证SSH能连上再断开当前会话。
第二,GRUB引导问题。跨大版本升级后GRUB可能需要重新安装,特别是双系统或者RAID环境:
sudo grub-install /dev/sda sudo update-grub
第三,Python版本变化。Ubuntu 22.04默认Python3是3.10,如果你的应用依赖3.8或3.9,需要提前安装对应版本并配置alternatives:
sudo apt install python3.9 python3.9-venv sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
第四,不要忽略/etc/fstab的UUID变化。如果你用了LVM或者加密分区,升级后UUID可能变了,导致挂载失败。升级前记录fstab内容,升级后对比检查。
第五,如果你用了ufw防火墙,升级后规则可能被重置,需要重新确认:
sudo ufw status verbose
最后说一个很多人忽略的点:升级完成后,旧的内核镜像和旧版本的包文件会占用大量磁盘空间。及时清理:
sudo apt autoremove --purge sudo apt clean
整个升级流程走下来,从评估到验证大约需要一到两周时间(滚动升级的情况下)。不要追求快,追求稳。平滑升级的本质不是技术有多复杂,而是流程有多严谨、备份有多充分、回退方案有多可靠。把这三件事做扎实,Ubuntu升级就不再是一件让人提心吊胆的事。
