Ubuntu 18.04.5 LTS i386阿里云小内存主机原地升级到Debian 10 Buster

背景

最近发现阿里云的1核512M内存的云主机上的Ubuntu是18.04.5,但是/etc/apt/sources.list中的dist名称却是bionic(20.04),就有些奇怪,为啥之前没有完成dist-upgrade的升级呢?

于是我试着做了一下do-release-upgrade,然后提示直接告诉我说Ubuntu 20.04不打算支持i386架构了,所以不能升级。

我没有更换ecs.t1.xsmall这个云主机的计划,且这个袖珍款从15年到现在的6年时间从运行Ubuntu 14.04 i386开始都很好的服务于我的博客系统,鉴于升级到x64会显著增加应用的内存占用,所以我想原地更换当前发行版到一个还持续维护的i386的发行版。看了一圈还是Debian最合适,毕竟是同源的东西。

但是如何原地升级呢? 今天打算具体实操下。

方案探索

网上搜索基本给出的都是说不可能或会失败。我有看过他们升级到视频,明显看出了各种问题。一个油管上的老哥的视频操作把dist release名称直接换成了debian-testing,然后升级到一半就挂了,这个是必然的,因为libc的版本差异太大了,原地运行必然挂掉。

这里总结出升级系统的几个必要的点

  • 要提前安装兼容于两个发行版的高版本内核
  • 新的Debian发行版的libc版本要与Ubuntu 18.04.5相近且二进制兼容
  • 新的Debian发行版大部分包的版本要高于18.04.5且绝大多数版本是兼容的

其中第一条保证了两个发行版在内核层面都能正常工作。第二条保证了原地升级期间,无论是libc系列升级前还是升级后,都可以支撑Debian和Ubuntu的包正常运行。第三条保证绝大多数包都可以通过自动升级的机制直接升级到Debian的包,不用过多的手工操作。

另外还要准备一套保底机制

  • 使用阿里云的快照功能,给升级前的机器的云盘创建一个可以恢复的快照,避免玩挂了之后回不去
  • 使用阿里云的VNC远程功能,在出现无法通过SSH连接时,提供通过本地操作的方式进行维护的能力
  • 准备一台应急的同可用区的云主机(如果没有现成的可以直接买一个按量付费的机器,用后删掉)如果在出现了rootfs中直接无法运行或启动的问题,可以挂载不可启动的磁盘到应急主机的数据盘,使用debootstrap和chroot进行修复

那么到底应该选择哪个Debian发行版呢?

根据Debian的发版时间,我本来选取了Debian 9 stretch作为备选系统。因为其libc是2.28,Ubuntu 18.04.5是2.27,两个发行版在时间上也相近,兼容性是不错的。

方案实操

接下来开始实操。

更换apt源

首先替换/etc/apt/sources.list中的bionicstretch,并进行apt update操作。

此时会存在一个缺失debian的gpg的问题,参照这个文章的方法,将缺失的PUB_KEY获取到本地,再重新apt update即可。

然后检查了一下可以升级到包数量

发现只有60多个包。对比apt list --installed | wc -l的600+个包,差的有点多。

所以这里面临了一个选择,即我不得不再考虑升级到下一个Debian发行版。所以接着我替换/etc/apt/sources.list中的stretchbuster,并进行apt update操作。

然后再次查看可以升级到包的数量,这次是500+了,看起来比较稳了。剩下一部分包是使用第三方的apt源安装的,如nginx, php这些,升级完成后再替换即可。

apt原地升级包

接下来就要执行原地升级了。

接下来就是等待了,大概执行了有不到20分钟,期间需要在提示Y/N时进行一下操作,很顺利的就完成了,包括libc这些都顺利安装。

批量安装debian的必备包

因为debian毕竟和ubuntu有些基础包的差异,所以这里还需要手工选中debian工作的必备包,再执行一下安装。

我在这里找了一个相对比较干净的Debian 10 amd64架构的机器(如果不存在可以安装虚拟机,或制作一个chroot的rootfs来构建),执行了下面的命令来获取已经安装的软件包

然后因为其是amd64架构,将其中的:i386全部提换掉

接下来将这些包在debian上选中

然后执行变更动作

接下来比较快,大概几分钟就安装完了。

到现在这一步,支撑Debian 10运行的基础包已经不缺失了。

手工替换残留的Ubuntu源的包

接下来看看还有哪些包还是从Ubuntu的源安装的。一般情况下Ubuntu的包版本号里会带着ubuntu字样,所以我采取下面的方法来查看

这种情况,一般都是Debian的包具有以下特点

  • 名称与Ubuntu包有不同
  • 版本号一样或更低
  • 依赖有问题,需要手工安装替换

这种包,只能手工安装dpkg来替换。提换的流程如下

  • 从pakcages.ubuntu.com检查未被替换包的功能,版本号及依赖项,如https://packages.ubuntu.com/bionic/zlib1g
  • 从packages.debian.org检查新的后选项包的信息,如https://packages.debian.org/buster/i386/libatomic1/download
  • 如果没有对应名称的包,在debian这里搜索名称一样不带版本号的包,或者直接去google搜索功能一样的包对应的是什么名称。
  • 然后从packages.debian.org下载对应的包,使用dpkg -i手工安装

鉴于这样的包有100多个,为了加速上面个步骤,我写了一个脚本来执行debian包的下载、安装及删除动作

pkg.sh包内容

只需要执行sh pkg.sh [pkg_name]即可完成包的替换安装工作。

经过一系列的包替换工作,最后只剩两个包不能更新

  • mysql-server-5.7
  • php-7.4

接下来经过搜索,增加了新的第三方apt source,将my-sql-server-5.7替换为mariadb-server-10.3,添加了新的php-7.4源。

至此带ubuntu字样的包都替换完成了。但是其实还是有剩余的,这里采用一个方法来进行检查,即重新reinstall包看哪些包不能安装

根据提示,不能升级的包再执行一遍手工替换工作,到最后提示全部包可以重新安装时即可。

彻底删除不用的包

接下来执行删除所有旧的包

这里注意,不要选择删除对应的数据。这里我就手滑删掉了数据库。。。后面花了很多功夫才恢复了关键数据

再重新安装一遍所有的包,确保之前purge时,被debian包覆盖安装时文件和配置都正常安装

更换内核及motd

至此就仅剩余内核还是使用了Ubuntu提供的版本,另外motd信息还是Ubuntu的信息

我在这里手工安装了Debian的最新内核

安装成功后,重启机器,再卸载掉其他之前Ubuntu安装的内核包。

最后是motd信息的修改。因为Ubuntu存在/etc/lsb-release信息,这里直接删除该文件即可

另外进入/etc/update-motd.d/,删除掉除了00-header10-uname之外的所有文件

再次使用ssh登录,发现提示已经变成Debian 10了

后记

此次成功将Ubuntu 18.04.5 LTS i386升级到了Debian 10 i386,在这个ecs.t1.xsmall的阿里云机器上又可以享受到可以持续更新的发行版了。

发表评论

为防机器,验证码请直接输入4个数字1

*