镜像上 edge 分支软件包丢失的事后分析

在 UTC 时间 2024-10-25 18:55,我们通过 IRC 收到通知,edge 分支的软件包仓库丢失。调查证实,除了 riscv64 之外,所有其他架构的仓库都丢失了。所有稳定版本的仓库仍然存在。

screenshot of edge repository, showing only riscv64

检查 dl-master 镜像,那里的仓库也丢失了。下一步是检查构建器本身是否仍然包含所有软件包,幸运的是情况确实如此。

为了给我们时间调查发生了什么并防止更多潜在问题,所有 edge 构建器都已停止。

镜像基础设施

为了理解发生了什么,让我们解释一下 Alpine Linux 的镜像基础设施是如何工作的。

每个架构和每个发行版都有一个专用的构建器。构建器保留它构建的所有软件包的完整仓库。在完成构建仓库后,它会将本地仓库与 dl-master.alpinelinux.org 同步,这是一个在我们镜像基础设施中属于 0 级层的单服务器。

接下来我们有 3 个地理位置分散的 1 级服务器,它们与 dl-master 同步。这些 1 级服务器也充当 dl-cdn.alpinelinux.orgrsync.alpinelinux.org 的后端,所有其他镜像都使用它们来同步我们的仓库。

diagram showing the various components involved in the mirror infrastructure

因此,一旦文件从 dl-master 添加或删除,该更改就会自动且快速地复制到其他镜像。

罪魁祸首

由于这仅影响了单个发行版 (edge),我们可以快速排除文件系统损坏的可能性。检查服务器上的 dmesg 输出也没有发现任何可疑之处。

在我们的 #alpine-commits IRC 频道中快速找到了关于发生事件的线索,该频道记录了 aports git 仓库的更新,以及构建器完成构建仓库后的更新。

在 UTC 时间 18:45,报告了这些更新

2024-10-25 18:44:19     algitbot        edge/main/: uploaded
2024-10-25 18:44:36     algitbot        edge/community/: uploaded
2024-10-25 18:44:49     algitbot        edge/testing/: uploaded

如果您将这些消息与其他消息进行比较,您会注意到区别

2024-10-25 18:37:10     algitbot        edge/community/x86_64: uploaded

架构丢失了。

所有构建器的骨干是一个名为 aports-build 的脚本,它负责确保所有软件包和发行版都被构建和上传。该脚本还会向 mqtt 发送消息,然后这些消息会被记录到 IRC 中。

mosquitto_pub -h $mqtt_broker -t rsync/$upload_host/$rel/$arch -m "$rel/releases/$arch"

来自 algitbot 的消息中架构丢失的事实意味着变量 $arch 为空。

此变量仅在脚本的开头赋值一次

arch=$(abuild -A)

因此 $arch 为空一定意味着对 abuild -A 的调用由于某种原因失败了。为什么这会导致所有仓库被删除?$arch 变量在 rsync 命令中用于上传仓库的所有软件包

rsync --recursive \
    --update \
    --itemize-changes \
    --delete-delay \
    --delay-updates \
    --mkpath \
    $rsync_opts \
    $repo/$arch $i/$repo/ > /tmp/upload-$repo

在这种情况下,$arch 用于确定要上传的源目录。这是构建器上的目录结构的样子

└── main
   └── x86_64

dl-master 上,它看起来像这样

main
├── aarch64
├── armhf
├── armv7
├── loongarch64
├── ppc64le
├── riscv64
├── s390x
├── x86
└── x86_64

因此在正常情况下,它会将构建器上的 main/x86_64 上传到 dl-master 上的 main/x86_64

如果 $arch 为空,它现在会将构建器上的 main/ 与 dl-master 上的 main/ 同步,从而导致除了当前架构之外的所有目录都被删除。

此时,我们尚不清楚是什么原因导致 $arch 为空。

恢复

由于所有仓库仍然存在于构建器上,因此恢复它们非常简单。一旦我们了解了问题的原因,我们就开始再次将所有仓库从构建器同步到 dl-master,之后 t1 服务器就可以开始同步所有仓库。

在 UTC 时间 2024-10-26 05:45,所有仓库再次在我们的 t1 镜像上可用。

缓解措施

为了防止将来再次发生此特定问题,我们 强化了 aports-build,使其在 $arch 为空时停止,并在发生这种情况时记录日志。

我们决定此时不引入更多更改,以防止引入更多问题。

尽管当前的构建基础设施多年来一直为我们提供良好的服务,但它也有其局限性。这就是为什么我们已经有了关于重新设计构建架构的想法。目前,我们没有任何具体的计划,但我们不会对当前的基础设施进行任何较大的更改。