Fedora 45 香肠工厂
摘要
详细讲解 Fedora 45 的构建流水线,从包源到发布制品,介绍 dist-git、Koji 和 Bodhi 等工具与流程。
暂无内容
查看缓存全文
缓存时间: 2026/07/25 14:09
# Fedora 45 香肠工厂
来源:https://supakeen.com/weblog/the-fedora-45-sausage-factory/
本文详细介绍 Fedora 如何将源代码和软件包转化为您下载并安装的制品:ISO、云镜像、容器镜像以及 OSTree 部署。我们将追踪一个软件包,从打包者的 Git 推送开始,直至组合发布完成。
本文描述的是 Fedora 45 版本中“香肠”的制作流程,内容随时可能变化;我希望能在每个或每几个 Fedora 发布周期更新本文档,既保留历史记录,也让人们能获取最新信息。
事实上,本文当前仍在修订中,因为 Fedora 45 尚未正式发布,所以本文很可能会在发布前持续更新。文中的一些细节(特别是`boot.iso` 的生产方式,这也是本文相当大的一部分内容)正受到若干变更提案的影响。
因此,现在也是向我反馈错误的最佳时机。如果您发现任何错误,请发送邮件至 `[email protected]`。
---
## 起点:dist-git
一切始于打包者向软件包推送提交。
Fedora 将每个软件包的源定义存储在 src.fedoraproject.org (https://src.fedoraproject.org/) 的独立 Git 仓库中。每个仓库包含一个 RPM spec 文件、任何下游补丁,以及一个指向上游 tarball(存储在单独的 lookaside 缓存中)的 `sources` 文件。大型二进制文件不存储在 Git 中;其他文件则存放在 Git 内,因此享有完整的版本控制。
打包者通常通过 `fedpkg`(一个封装了常见操作的 CLI 工具)与这些仓库交互,包括克隆仓库、上传源码 tarball、提交构建以及创建更新。`fedpkg build` 的关键在于它实际执行的操作:它构造一个指向 Git 仓库中特定提交的 URL,并将其交给 Koji(构建系统)。从该提交哈希开始,构建是完全可重现的。
分支映射到版本:`rawhide` 用于开发,`f44` 用于 Fedora 44。托管服务由 Pagure(src.fedoraproject.org)和 Forgejo(forge.fedoraproject.org (https://forge.fedoraproject.org/))共同提供,目前正从前者迁移至后者。
打包者可以不使用 `fedpkg`,但为了本文的叙述方便,我们假定使用 `fedpkg`,因为它屏蔽了一些与读者无关的细节。
## 构建软件包:Koji
当 `fedpkg build` 提交那个 Git URL 后,Koji 便开始接管。Koji 是 Fedora 的构建系统,自 Fedora 7 以来一直存在,几乎所有东西都由它构建。
Koji 采用中心辐射型架构。中心是一个被动的 XML-RPC 服务器,前端连接一个 PostgreSQL 数据库。构建守护进程轮询中心获取任务,为每次构建创建一个全新的 Mock (https://github.com/rpm-software-management/mock) chroot 环境,执行构建,并上传结果。每次构建都从洁净室开始。你不可能会因为上周有人在构建机上安装了某些软件而得到不同的结果。
其组织模型基于**标签**。标签是一个命名的构建集合。构建目标将一个传入的构建请求映射到两个标签:构建标签(定义构建根,即构建期间可用的软件包)和目标标签(完成后的构建存放位置)。标签支持多重继承,因此你可以在基础标签之上叠加 Fedora 44 标签,而无需复制所有内容。
Koji 不仅构建 RPM。通过其插件系统和内容生成器,它还编排镜像构建:通过 `kiwiBuild` 任务类型构建 Kiwi 镜像,通过 `imageBuilderBuild` 构建 Image Builder 制品,以及通过 runroot 任务构建 OSTree 组合。我们稍后会提到这些。
## 门控更新:Bodhi
位于 Koji 中的全新 RPM 构建不会自动到达用户手中。对于分支版本(除 Rawhide 之外的任何版本),它会经过 Bodhi (https://bodhi.fedoraproject.org/),即 Fedora 的更新管理系统。
Bodhi 通过反馈和测试周期来门控更新的发布。打包者提交一个包含一个或多个构建的更新。该更新会经历一系列状态:待定、测试中、稳定。用户和自动化测试提供 karma(+1 / -1)。当更新达到 +3 karma 或在测试中停留足够天数后,会自动推送到稳定版。如果更新达到 +1 karma,维护者可以手动推送到稳定版(关键路径需要 +2)。
在后台,Bodhi 通过 Koji 标签管理这一切。当更新从测试版转为稳定版时,Bodhi 会将构建从 `f44-updates-testing` 标签移动到 `f44-updates` 标签。然后它调用 Pungi 来组合更新仓库,也就是用户运行 `dnf upgrade` 时实际拉取的 yum/dnf 仓库。
关键路径软件包(系统启动和运行所必需的)有更严格的要求:在测试中停留 14 天而非 7 天,并且需要更多 karma。Bodhi 还与 Greenwave 和 ResultsDB 集成,用于 CI 测试门控,因此自动化测试失败可能会阻止更新进入稳定版。
对于 Rawhide,这些流程的配置不同。非关键路径软件包会立即进入稳定版,除非存在门控策略(因为软件包处于关键路径,或者软件包本身具有该策略),此时门控仍然适用,更新可能会被暂缓直至测试通过。
## 组合发布:Pungi
单个 RPM,即使经过 Bodhi 的门控,也仅仅是软件包而已。将它们转化为可以下载和安装的东西(ISO、云镜像、仓库)是 Pungi (https://forge.fedoraproject.org/pungi/pungi) 的工作。
Pungi 是组合编排器。它本身并不做太多繁重的工作。相反,它协调其他工具,确保所有内容都基于同一组一致的软件包构建。
这个名字指的是 pungi (https://en.wikipedia.org/wiki/Pungi),一种诱蛇乐器。它“引诱” Fedora 的安装程序 Anaconda (https://fedoraproject.org/wiki/Anaconda)。这个双关语自 2006 年沿用至今。
当 `pungi-koji` 运行时(由 cron 为 Rawhide 每日组合触发,或为里程碑版本手动触发),组合便开始了。它加载一个配置文件(对于 Fedora,是 pungi-fedora (https://forge.fedoraproject.org/releng/pungi-fedora) 仓库中的 `fedora.conf`),并按顺序执行一系列阶段。
### 冻结软件包集合
Pungi 做的第一项实际工作是从 Koji 标签快照软件包集合。这是 **Pkgset** 阶段,至关重要:后续每个阶段都基于这个冻结的集合工作。如果在组合运行期间有人向 Koji 提交了新的构建,它不会偷偷溜进组合中。基于标签的快照使整个组合可审计。你始终可以确定哪个版本的哪个软件包最终进入了哪个给定的组合。
### 决定内容去向:comps 与 variant
软件包冻结后,Pungi 需要确定哪些软件包属于哪个产品。这里需要两个 XML 输入。
**comps**(`fedora-comps`)定义了软件包组,即相关软件包的集合,例如 `gnome-desktop`、`server-product` 或 `core`。组中的每个软件包都有一个类型:必选、默认、可选或条件。这与 `dnf group install` 以及 Anaconda 的软件选择界面所使用的分组系统相同。
**variants XML**(pungi-fedora 中的 `variants-fedora.xml`)定义了组合中的产品:Everything、Server、Workstation、KDE、Silverblue 等。每个 variant 列出了它包含的 comps 组以及支持的架构。现代 Fedora 中的大多数 variant 都设置为 `is_empty="true"`,意味着它们仅使用来自 Everything variant 仓库中的软件包来生成镜像(通过 Kiwi、Image Builder 或 OSTree)。只有 Everything 和 Server 实际运行软件包收集管道。
### 构建引导镜像
**Buildinstall** 阶段运行 lorax (https://weldr.io/lorax/) 来创建 `boot.iso`,即用于启动 Anaconda 安装程序的镜像。Lorax 将最小的软件包集合安装到临时根目录中,配置 Anaconda 环境,将其压缩为 `install.img`,并用引导加载程序封装成 ISO。每个 variant-架构组合会运行一个 lorax 任务,通常在 Koji 的 runroot 环境中进行隔离。
生成的 boot.iso 是安装程序 ISO 的基础。它本身不包含软件包。这些软件包会在下一步中叠加到其上,以生成 `dvd.iso`。
### 构建 ISO
**Createiso** 阶段获取来自 Buildinstall 的 boot.iso,使用 xorriso 在其上叠加软件包和仓库元数据,并生成最终的安装程序 ISO。对于 Fedora 的生产组合,这主要指的是 Server dvd.iso。大多数其他 variant 的介质来自 Kiwi 或 Image Builder。
### 使用 Kiwi 构建镜像
Kiwi (https://osinside.github.io/kiwi/) 是 Fedora 组合中的主要镜像构建工具。它构建云镜像(AWS、Azure、GCP、通用)、Vagrant 盒子、容器基础镜像、WSL 镜像以及大多数桌面衍生版(spins)的 Live ISO。
Kiwi 最初由 SUSE 于 2005 年左右创建,是一个两步构建器:首先通过安装软件包准备根文件系统,然后将其打包为目标格式。镜像定义是 XML 文件,需经过 RELAX NG 模式验证。Fedora 的定义位于 fedora-kiwi-descriptions (https://forge.fedoraproject.org/releng/fedora-kiwi-descriptions) 仓库中,按团队组织:`teams/cloud/`、`teams/kde/`、`teams/spins/`、`teams/wsl/`。
Kiwi 通过内置插件与 Koji 集成,提供 `kiwiBuild` 任务类型。父任务从 SCM 检出镜像描述,解析 XML,并为每个架构生成一个子任务。每个子任务创建一个 Mock 构建根,将 XML 中的所有仓库定义替换为 Koji 控制的仓库(以便构建使用组合的冻结软件包集合),运行 `kiwi-ng system build`,并上传结果。
### 使用 Image Builder 构建镜像
Image Builder (https://github.com/osbuild/image-builder) 处理基于 ostree 和 bootc 的制品:Atomic Desktop ISO、Fedora IoT、Fedora Minimal 以及 boot.iso。
在底层,Image Builder 构建于 osbuild (https://github.com/osbuild/osbuild) 之上,osbuild 是一个基于管道的构建引擎,处理 JSON 清单。每个清单描述了一个有向无环图(DAG)的管道,每个管道运行一系列顺序的阶段,这些阶段是只做一件事(安装软件包、配置引导加载程序、创建分区表、嵌入 OSTree 提交)的小型可执行文件。目前有 176 个阶段。阶段在 bubblewrap 沙盒环境中运行,具有文件系统和网络隔离。
`image-builder` CLI 是无状态的:它读取发行版定义,解析软件包依赖关系,生成 osbuild 清单,并直接运行 osbuild。
Image Builder 通过 koji-image-builder (https://github.com/osbuild/koji-image-builder) 与 Koji 集成,这是一个独立的 Koji 插件,提供 `imageBuilderBuild` 任务类型。每次构建在 Koji 工作节点上的 Mock 构建根内运行 `image-builder`。
### 构建 Atomic Desktop:rpm-ostree
Fedora Silverblue、Kinoite、Sway Atomic、Budgie Atomic 和 COSMIC Atomic 的构建方式与传统基于软件包的 variant 不同。这些 variant 不是向用户提供一堆 RPM 供其安装,而是提供一个带版本号、带校验和的文件系统树(即 OSTree 提交),客户端以原子方式复制该树。
rpm-ostree (https://github.com/coreos/rpm-ostree) 是实现这一功能的工具。它是一个混合镜像/软件包系统,结合了 libostree (https://ostreedev.github.io/ostree/)(原子 OS 树部署)和 RPM(通过 libdnf 进行包管理)。
在组合方面,`rpm-ostree compose tree` 接受一个 treefile(一个 YAML 规格说明,列出软件包、配置和后处理脚本)和一组 RPM 仓库,并生成一个 OSTree 提交。Pungi 的 OSTree 阶段在 Koji 的 runroot 环境中为每个 Atomic Desktop variant 调用此命令。
Treefile 位于 workstation-ostree-config (https://forge.fedoraproject.org/atomic-desktops/config) 仓库中。它们使用分层包含系统:`silverblue-ostree.yaml` 包含 `silverblue-common.yaml`,后者又包含 `common.yaml`,该文件有条件地包含 `fedora.yaml` 和架构特定文件。`comps-sync.py` 脚本在 comps 组和 treefile 软件包列表之间架起桥梁。它解析 comps XML,从 `gnome-desktop` 和 `workstation-product` 等组中提取默认和必选软件包,并将它们写入生成的 YAML 文件中。这样,桌面环境软件包就能与 comps 定义保持同步,而 treefile 则添加 ostree 特定的软件包(bootupd、composefs),并排除那些已 Flatpak 化或与 ostree 不兼容的软件包。
### 组合元数据:productmd
每次组合都会生成一组描述其内容的元数据文件。这些文件由 productmd (https://github.com/release-engineering/productmd) 定义,这是一个标准化格式的 Python 库。
关键文件包括:
- `composeinfo.json`:发布身份、variant 定义、文件系统路径
- `images.json`:每个镜像的类型、格式、校验和和大小
- `rpms.json`:按 variant 和架构组织的每个 RPM
- `.treeinfo`:每个 variant 的元数据,由 Anaconda 用于查找安装树
Pungi 在构建过程中逐步创建这些文件。开始时,它会生成一个组合 ID(例如,`Fedora-Rawhide-20260723.n.0`)。每个生成镜像的阶段都会添加 Image 对象。Gather 阶段填充 RPM 清单。最终化时,所有内容都会被写出。
下游消费者严重依赖这些文件。Anaconda 读取 `.treeinfo` 以在安装过程中发现软件包和引导镜像的位置。Bodhi 检查组合元数据以进行更新管理。openQA 读取 `images.json` 以定位用于测试的镜像。镜像管理工具查询元数据以决定同步内容。
### 测试:openQA
组合完成后,openQA (https://openqa.fedoraproject.org/) 会接手进行自动化测试。openQA 是一个针对操作系统的自动化测试系统,最初由 SUSE 开发,后由 Adam Williamson (https://www.happyassassin.net/) 和 Fedora QA 团队改编用于 Fedora。
openQA 在虚拟机中启动组合的镜像,并运行测试场景:安装工作流(交互、kickstart、各种磁盘布局)、桌面功能、升级路径以及基本的系统验证。测试由测试脚本(用于视觉匹配的“needles”和用于交互的 Perl 测试模块)组合编写,并维护在 os-autoinst-distri-fedora (https://forge.fedoraproject.org/quality/os-autoinst-distri-fedora) 仓库中。
每个 Rawhide 每日组合以及每个里程碑组合(Beta、Final)都会触发 openQA 运行。结果反馈到发布验证流程中,openQA 发现的阻塞性缺陷可以阻止发布的进行。系统还会测试来自 Bodhi 的更新组合,从而在回归问题触及用户之前将其捕获。
## 香肠制作流程
以下是典型 Fedora 组合中各阶段的流程:
```
pungi-koji
│
├── 第1步:初始化
│ 解析 comps + variants XML
│
├── 第2步:Pkgset
│ 从 Koji 标签快照软件包
│
├── 第3步:基础软件(并行)
│ ├── Buildinstall (lorax → boot.iso)
│ ├── Gather + Createrepo(包仓库)
│ └── OSTree (rpm-ostree compose tree)
│
├── 第4步:镜像(并行)
│ ├── Createiso(dvd.iso 由 boot.iso + 软件包生成)
│ ├── KiwiBuild(云镜像、Live、容器、WSL)
│ └── ImageBuilder(Atomic Desktop ISO、IoT、Minimal)
│
│ (OstreeContainer 在第3-4步期间后台运行)
│
├── 第5步:校验和
│ 写入 productmd 元数据,SHA256
│
│ (OstreeContainer 在第3-4步期间后台运行)
│
├── 第6步:最终化
│ 写入最终元数据,上传日志,通知 downstream
│
└── 通知 openQA 开始测试
```
这个大纲高度简化,但涵盖了主要流程。实际的组合运行方式要微妙得多:Pungi 配置文件(`fedora.conf`)允许每个阶段独立启用或禁用,并支持复杂的依赖关系。并非所有阶段都每次运行。例如,Rawhide 每日组合可能跳过最终化,而里程碑组合则会运行该流程以确保质量。
我将尝试进一步展开任何您感兴趣但细节不够充分的阶段。
相似文章
Fedora 44 Gnome 评测 - 我们已不在堪萨斯
对 Fedora 44 Gnome 版的评测,讨论安装和软件管理,并对二维码使用和 Gnome Software 漏洞提出批评。
使用 Fedora Silverblue 进行合成器开发
本指南介绍如何使用原子发行版 Fedora Silverblue 开发 niri Wayland 合成器,重点介绍了不可变系统在系统组件开发中的优势。
为小型社区构建发行版构建工具
Chimera Linux 发布 cbuild,一款统一的发行版构建工具,可自动化打包、仓库管理、沙盒化构建以及 CI 式验证,旨在降低门槛,让任何用户都能在几分钟内成为打包者,并在本地复现该项目的远程基础设施。
KDE Linux 使用体验
作者 AksDev 分享了一年日常使用 KDE Linux 的体验,强调其原子设计在开发中的优势,但指出 Flatpak 问题,最终切换回 Fedora KDE。
构建系统改进、集中概览等
文章讨论了构建系统的改进以及一个集中概览功能。