| RFC-0212:软件包集 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 提议对 Fuchsia 上软件包集的定义和菜单进行一系列更改 |
| 问题 | |
| Gerrit 更改 | |
| 作者 | |
| 审核人 | |
| 提交日期(年-月-日) | 2022-11-17 |
| 审核日期(年-月-日) | 2023-03-07 |
摘要
此 RFC 为“软件包集”一词提供了官方定义,并提出了一个更新的软件包集框架。此框架根据软件包集提供的可用性和版本控制来表示软件包集,并可容纳:
- 三个现有软件包集
- 之前未与软件包集集成的早期软件交付工作
- 新的软件包集,可根据产品要求更灵活地交付 Fuchsia 软件。
设计初衷
软件包是 Fuchsia 上的软件分发单元。软件包用于交付平台软件和产品软件,还可用于各种不同的测试和开发工作流程。
每款 Fuchsia 产品都使用特定于产品的软件包和平台提供的软件包的某种组合;此组合的内容因产品而异。产品使用的所有软件包不必同时交付,也不必使用相同的策略进行更新。例如,某些软件包可能会作为无线更新的一部分进行下载,而其他软件包可能要等到用户采取某些操作后才会下载。
“软件包集”是指产品使用的一组软件包,该集中的所有软件包都使用相同的策略进行交付和更新。Fuchsia 目前使用三种不同的软件包集:基础、缓存和全集。
由于以下几个原因,Fuchsia 上软件包集的当前状态不足:
- “套装”一词的定义不够明确。
- 现有软件包集尚未明确定义,并且从其名称来看,它们提供的行为并不明显。同一术语在不同情境下重复使用,但含义不同。例如,设备存储在其软件包缓存中的软件包集与“缓存”软件包集并不相同。
- 现有软件包集尚未更新,无法反映最新的软件交付 RFC,例如急切的软件包更新、子软件包或 bootfs 软件包。
- 现有的软件包集无法满足多项产品开发者的需求。例如:
- 当磁盘空间有限时,应可以延迟提取非必需软件包。
- 应能够独立于平台更新产品软件(这在 RFC-0145 中进行了设计,但尚未包含在软件包集定义中)。
- 在开发期间,应能够快速可靠地更新软件包。
此 RFC 旨在实现以下目标:
- 明确定义“软件包集”一词。
- 定义潜在软件包集定义所在的设计空间。
- 说明现有软件包概念在此设计空间中的位置,并根据该位置优化我们用于指代这些概念的名称。
- 确定设计空间中应通过未来 RFC 中的设计来填补的缺口。
- 确定不再需要且应弃用的现有概念。
利益相关方
辅导员:
- abarth
审核者:
- wittrock (SWD)
- amituttam(项目经理)
- aaronwood(软件汇编)
- markdittmer(安全性)
- sethladd (DX)
- marvinpaul(服务器基础架构)
已咨询:
- yaar, senj, etrylezaar, galbanum, richkadel
共同化:
在软件交付团队内部的一系列设计讨论中,我们讨论了促成此 RFC 的工作。此 RFC 中的文本早期版本已与软件组装、服务器基础设施、第一方产品和 PM 团队中的利益相关者进行了审核。
定义
-
<
软件包是文件的集合,例如清单、元数据、零个或多个可执行文件(例如组件)和资源。“软件包”一词既指此类集合的定义(例如,由其build 规则定义的 Timekeeper 软件包),也指根据该定义生成的单个制品(例如,2022 年 11 月 14 日构建的 Timekeeper 软件包,其 Merkle 根为
de07b9f06ae01181b0536b61c7f643496025598c3a2908dca5c72fce191be5d1)。在本 RFC 中,我们仅使用前一种含义。 - 软件包版本 - 特定软件包的单个实例(例如,2022 年 11 月 14 日构建的 Timekeeper 软件包,其 Merkle 根为
de07b9f06ae01181b0536b61c7f643496025598c3a2908dca5c72fce191be5d1)。Fuchsia 目前不要求对软件包版本进行编号(甚至不要求排序)。某些热切更新软件包的 CUP 元数据可能包含用于回退检查的有序版本号,如 RFC-0145 中所定义。 - 产品定义了 build 将生成的软件配置。最重要的是,产品通常会定义所提供的用户体验类型,例如用户可能会看到的图形界面外壳类型、是否包含多媒体支持等。
- 产品 build - 特定产品的组装系统的单个版本。产品 build 是根据产品定义的规范生成的制品。例如“Workstation 8.20220622.2.1”。
- 产品版本 - 已推送到更新渠道的产品 build。
- 套餐 - 请参阅下文。
- 版本控制方 - 一种服务器或代码库,用于确定 Fuchsia 设备应使用哪个版本的软件包。在生产系统中,Omaha 充当版本控制机构,而在开发期间,主机上的 TUF 代码库充当版本控制机构。
- 基础(最初称为“monolith”)- 在此 RFC 之前定义的软件包集。基本软件包集的内容始终存在于设备上,且版本由产品发布版本固定。此 RFC 建议保留基本软件包集。
- 缓存(最初称为“预安装”)- 在此 RFC 之前定义的软件包集。缓存软件包集的内容在几乎所有情况下都存在于设备上,但在本地开发期间,版本可能会在某些情况下更新。此软件包集不会在生产环境中使用。此 RFC 建议创建以开发者为中心的新流程来替换缓存软件包集。
- Universe(最初称为“available”)- 在此 RFC 之前定义的软件包集。宇宙软件包集的内容会根据版本控制机构确定的版本按需下载。此软件包集目前未在生产环境中使用。“universe”一词既指代此软件包集的内容,也指代所有软件包集的内容。为避免混淆,此 RFC 建议将 universe 软件包集重命名为“可发现”。
- 急切更新 - 一种独立于产品发布版本更新软件包的机制,如 RFC-0145 中所定义。
- Bootfs 软件包 - 存储在 bootfs 文件系统中的软件包,如 RFC-0167 中所定义。
- 子软件包 - 根据 RFC-0154 中的定义,由某个其他软件包引用并以原子方式提取的软件包。
- 父软件包 - 根据 RFC-0154 的定义,引用子软件包的软件包。
- 垃圾回收 - 从 blobfs 中移除不再需要的软件包内容的过程。
- 系统更新(也称为“OTA”)- 将 Fuchsia 设备从一个产品版本更新到另一个版本的流程。
设计
套装
软件包集是指一组软件包,其中所有软件包都使用相同的策略进行交付和更新。例如,在基本软件包集中,所有软件包都会在系统更新期间以产品发布版本确定的版本进行提取。此基本软件包集中的软件包保证在设备运行时始终存在。
软件包集的内容由产品定义。特定软件包可能存在于产品 A 的一个软件包集中,但存在于产品 B 的另一个软件包集中(或完全省略)。软件包所在的软件包集反映了软件包与使用它的产品之间的关系;对产品运行至关重要的软件包应放置在可保证这些软件包始终存在于设备上的软件包集中。通常情况下,一个软件包只会存在于给定商品的一个软件包集中,但也有一些情况是,一个软件包可以存在于多个软件包集中。
根据“软件包集”一词的使用背景,人们提出了几个相关但略有不同的定义。下面我们将介绍其中一些,并提供可用于明确指代相应定义的名称。
- 符合条件的软件包集 - 设备允许解析的软件包集。例如,“符合条件的基本软件包集”是指设备可以成功解析并放置在其交付的基本软件包集中的所有软件包的集合。
- 已构建的软件包集(也称为 build 依赖项集)- 在构建 Fuchsia 产品时生成的一组软件包。已构建的软件包集通常等于相应的符合条件的软件包集,但在某些情况下,它可能会小得多。例如,某个设备可能具有数千个符合条件的通用软件包,但相应 build 可能不会生成任何此类软件包。
- 已交付的软件包集 - 已交付给设备的一组软件包。交付的软件包集是相应符合条件的软件包集的子集。
本文档的其余部分重点介绍软件交付系统的设计,因此也重点介绍了“符合条件的软件包集”的定义。
建议的设计空间
软件交付系统可解答以下两个关键问题:
- 软件包的版本由什么决定?
- 软件包何时可在设备上使用?
此 RFC 建议采用二维设计空间,根据这两个问题对软件包集进行分类,如下图所示:

请注意,在这两种情况下,都没有“最佳”答案;每个轴都表示两种理想属性之间的权衡。对于某些使用情形,轴的一端可能最适合,而对于其他使用情形,另一端则更适合。
轴 1 - 版本控制
确定软件包的当前正确版本对于系统的安全性和可更新性至关重要。更改软件包版本对于发布新功能和修复 bug 是必要的,但如果具有选择软件包版本权限的实体遭到入侵,则可能会被用来部署不当或恶意版本的软件。频繁更改软件包版本通常涉及运行不太成熟的软件或尚未一起测试过的软件组合。
版本控制轴是在高敏捷性和高确定性之间进行权衡。例如:
- 系统的关键元素不需要经常更改,必须集中严格控制。在这些情况下,最好将软件包的版本锁定到平台或产品版本。
- 最终用户应用可能会根据开发它们的组织的节奏而频繁变化。在这种情况下,发布者希望向兼容设备发布新版本,而无需等待产品发布。
- 开发者调试的组件可能会在每次更改代码时每隔几秒发生变化。在这些情况下,最好立即自动更新版本。
轴 2 - 可用性
软件包的存在是为了在 Fuchsia 设备上实现一些有用的功能,并且只有当它们存在于(且已知为正确)该设备上时,才能实现这些功能。
可用性轴是在高可用性和低资源利用率之间进行权衡。例如:
- 即使网络不可用,系统的关键元素也需要始终可用。在这些情况下,必须在整个使用期间存储相应软件包。这意味着在更新期间同时存储软件包的先前版本和当前版本。
- 产品体验中不太关键的部分可能不需要提供可用性保证。在这些情况下,最好在提取更新版本之前删除软件包的旧版本,以减少峰值存储需求。
- 某些最终用户应用可能仅能在少数设备上使用。在这些情况下,最好仅在有信号表明用户打算使用某个软件包时才通过提取该软件包来消耗资源。
映射到现有概念
现有的软件包集和与软件包相关的 RFC 分为四种不同的版本控制类别:
- 软件包版本由产品固定:适用于 base 和 bootfs。
- 产品将特定软件包的版本控制委托给具有约束的版本控制机构:适用于急切更新的软件包。对于急切更新的软件包,产品发布版本可能会限制可接受的最低版本。
- 产品将特定软件包的版本控制权委托给不受限制的版本控制机构:适用于缓存软件包。
- 产品将网域中所有网址的版本控制委托给不受限制的版本控制机构:适用于不在基本集或缓存集中的宇宙软件包。请注意,这是唯一一个商品发布版本不定义集合中每个软件包是否存在的类别。
现有的软件包集和与软件包相关的 RFC 分为四种不同的可用性类别:
- 始终可用:适用于 base 和 bootfs。
- 几乎总是可用:适用于急切更新的软件包(当指定了回退版本时)和缓存软件包。在这些情况下,意图是让软件包始终可用,但缓存软件包解析和垃圾收集算法的当前设计意味着在某些情况下,软件包将不可用。
- 在系统更新后自动提取:适用于未指定回退版本的急切更新软件包。在系统更新提交后,只要网络状况良好,这些软件包就会在一段时间后提供。
- 按需提取:适用于不在其他软件包集(例如基本软件包集)中的全宇宙软件包。在发出软件包解析请求后,只要网络运行正常,这些软件包就会在一段时间后可用。
子软件包引用包含目标的内容哈希,因此子软件包遵循其父软件包的版本控制类别。 子软件包与其父软件包以原子方式解析(如果没有解析父软件包的上下文,则无法解析子软件包),因此子软件包的可用性取决于其父软件包。
总而言之,现有软件包概念符合建议的设计空间,如下图所示:

建议的更改
如上所示,将现有软件包概念映射到此设计空间时,会立即发现几个问题:
- 现有概念未涵盖大部分设计空间,这表明我们当前的软件包集无法为许多潜在的有价值的用例提供解决方案。
- 缓存软件包和急切更新的软件包发挥着非常相似的作用。
- “几乎始终可用”的软件包不受欢迎,仅因缓存软件包解析和垃圾收集算法存在问题而存在。
- 现有概念的名称不遵循一致的模式,并且在大多数情况下,无法体现概念所占用的设计空间部分。
- 其中一些概念(例如热切更新)未定义为软件包集。
此 RFC 提出了一系列更改,这些更改共同解决了上述问题,并实现了更全面、更一致的设计空间覆盖,如下所示:

以下各部分将详细介绍每项变更。请注意,我们按计划启动顺序介绍这些更改,但许多更改可以并行进行。如果更改相互依赖,则会在正文中讨论这种关系。
更改 1 - 为软件包集引入统一的命名规范
在此 RFC 之前,软件包集使用单个字词命名。由于只有三组,并且它们位于单轴上,因此这种做法是可行的,但即使这样,简洁的名称也造成了一些混淆。
此 RFC 建议使用简短的短语来描述软件包集提供的属性。每个短语都包含一个用于描述软件包集中软件包可用性的字词,以及一个用于描述软件包集中软件包版本控制的字词,如下表中所定义:
| 提供期限 | 说明 |
| 永久 | 这些套餐在任何情况下均可使用 |
| 自动 | 当磁盘空间和网络可用性允许时,系统会自动提取这些软件包 |
| OnDemand | 仅当设备上的某些实体尝试使用这些软件包时,系统才会提取它们 |
| 版本控制期限 | 说明 |
| 锚定 | 这些软件包的版本由产品发布版本设置。 |
| 可升级 | 产品发布会将这些软件包的控制权委托给版本控制机构,并可选择性地添加约束条件,例如最低可接受版本。 |
| 可检测到 | 产品发布版本不定义此集中的各个软件包,而是将控制权委托给网址网域的版本控制机构。 |
例如,一个没有回退的急切更新的软件包将完整地称为“自动可用性、可升级的版本控制”软件包集的成员。在上下文和含义明确的情况下,这可以缩写为“自动且可升级”。
在左下角部分,我们有两个具有相同版本控制和可用性行为的不同软件包集 - base 和 bootfs。我们将保留这些名称来指代这些软件包集,同时使用“永久可用性、锚定版本控制”来指代它们共有的更一般行为。
在替换缓存软件包集之前,我们将保留现有的“缓存”名称来指代该软件包集(请参阅更改 6)。
“universe”一词在 Fuchsia 上有相互冲突的定义。最初的定义是所有已构建软件包的集合,这与该术语的集合论含义一致。如今,“universe”通常仅指已构建但未包含在其他软件包集中的软件包,即基本软件包不属于 universe。此定义与集合论中该术语的含义不一致。为避免这种混淆,我们在提及设计空间的右上角部分时,使用“可发现”而非“全域”这一名称。
变更 2 - 弃用“缓存”软件包集
缓存软件包集和具有回退功能的急切更新软件包是两种不同的解决方案,它们可满足同一需求:让版本控制服务器提供软件包的新版本,同时确保即使设备处于离线状态,软件包的某个版本仍可供使用。
如 RFC-0145 中所定义,急切更新的软件包可为此问题提供更可靠的解决方案:
- 与缓存软件包不同,服务器通信问题不会导致急切更新的软件包无法解析
- 与缓存软件包不同,如果设备处于离线状态,急切更新的软件包不会恢复到较早版本
缓存软件包目前仅在开发者流程中使用,但(由于上述问题和其他问题)它们不太适合这些使用场景。鉴于急切更新的软件包的优势,在生产流程中永远不应使用缓存软件包。
我们将弃用缓存软件包概念,这意味着 SWD 不会再投资于改进该流程。在部署并采用合适的替代方案之前,我们不会移除该流程和开发者文档(请参阅变更 6)。
请注意,弃用缓存软件包并不意味着弃用名称相似的“软件包缓存”组件。
更改 3 - 移除 RFC-0154 中的子软件包集限制
RFC-0154 要求子软件包“与”其父软件包“位于同一软件包集中”。随着我们引入新的软件包类别,此要求将变得难以满足,因为每次传递子软件包集发生变化时,产品维护人员都需要更新软件包集定义。
自 RFC-0154 以来,实现工作已经放宽了相同的软件包集限制,但此 RFC 正式移除了该限制。如上所述,子软件包仍遵循其父软件包的可用性和版本控制(因此仍有效地充当其父软件包集的成员),但产品维护人员不再需要将子软件包作为引用它们的软件包集的顶级成员单独包含在内。
安全审核工具用于验证产品的每个版本是否包含预期的一组软件包。用于此验证的基准文件将以传递方式包含锚定版本软件包集中的所有子软件包。这样可确保向锚定版本软件包集添加任何子软件包或嵌套子软件包都会接受人工审核。
更改 4 - 重新设计垃圾回收算法
Fuchsia 当前的软件包垃圾回收 (GC) 算法是在程序早期设计的,随着软件交付的发展,该算法的扩展性并不理想。即使在今天,我们仍然会遇到以下故障模式:删除必要的软件包,以及保留不必要的软件包。当前的 GC 算法无法处理新软件包集的引入。
我们将在不久的将来发布后续 RFC,其中包含可容纳更多软件包集的替换 GC 实现的要求和算法。
更改 5 - 设计自动锚定的软件包集
在每次发布产品时,产品维护人员都必须一起测试许多不同的平台和产品软件包的已修复版本,以确保它们能够正确集成。目前,产品包含软件包的固定版本的唯一方法是将其包含在基本软件包集中。这意味着在系统更新期间,可能需要在磁盘上同时存储所有这些软件包的两个副本,这使得在存储空间有限的设备上运行 Fuchsia 变得困难。
通过实现自动可用性、锚定版本软件包集(即支持版本由产品固定但直到系统更新成功提交后才下载的软件包)可以解决此问题。我们将在不久的将来发布后续 RFC,其中包含此软件包集的相应设计。
变更 6 - 设计面向开发者的替代软件包交付流程
如上文更改 2 中所述,缓存软件包流程不太适合开发者在开发期间轻松、快速、可靠地更新软件包的需求。我们将专注于开发者需求,研究出更好的解决方案,然后发布设计作为后续 RFC。
我们预计,所讨论的这种以开发者为中心的新流程将在工程 build 中作为设计空间的叠加层发挥作用,但我们将在后续 RFC 中进一步探讨这一点。
变更 7 - 设计按需锚定和/或按需可升级的套餐组合
借助这些软件包集,产品维护人员可以定义具有固定版本或受限版本的软件包,这些软件包在需要时才会提取。
这些软件包集可能对未来的产品有用,但与更改 5 中的自动锚定软件包集不同,我们目前还没有发布客户。
当出现特定产品或开发者需求时,我们将设计并实现这两个软件包集中的一个或两个。
总结
完成这些更改(包括提议的后续 RFC)后,软件交付堆栈将为产品开发者提供更大的灵活性。例如:
- 通过将非必需软件包从基本软件包移至自动和锚定或按需和锚定软件包集,产品将能够减少资源利用率,同时不会失去对版本控制的控制。
- 产品将能够使用可升级的软件包集来包含可独立于产品进行升级的软件包。
- 产品将能够控制这些可升级软件包的可用性。这包括将它们放置在永久且可升级的软件包集中,以确保它们始终可用。
- 这些可升级的软件包可以引用在构建时产品版本未知晓的其他软件包。
- 这可以通过以下方式实现:使用子软件包(父软件包设置所引用软件包的版本),或使用可发现软件包集中的网址(版本控制机构设置所引用软件包的版本)。
- 被引用软件包的可用性取决于引用软件包(如果是对子软件包的引用)或由引用软件包控制(如果是对可发现软件包的引用)。
- 产品可以通过启用可发现的软件包集来使用未在产品版本中明确定义的软件包。
- 在所有情况下,软件包只能从产品信任的代码库中提取。
- 软件交付会管理可用的 blob 存储空间,确保在需要执行系统更新时,非关键软件包会被逐出,并且在空间可用时,会自动提取自动软件包。
- 开发者将能够轻松更新开发期间需要修改的软件包。
此 RFC 中描述的更改还会对 SWD 堆栈中的假设产生重大影响。例如:
- 需要在软件包缓存中存储软件包的多个版本。可升级的软件包可能包含对已由产品在其锚定集中包含的软件包的子软件包引用。由于产品和可升级软件包不知道彼此的版本控制方案,因此它们无法协调以确保此通用软件包的版本在两者中相同。同样,同一可升级软件包集中的不同软件包可能包含对同一软件包的子软件包引用,但版本不同。
- 软件包缓存中的软件包必须支持多个软件包集。如上所述,可升级的软件包可能包含对产品已包含的软件包的子软件包引用。有时,此软件包在两个软件包集中的版本相同。在决定何时移除某个软件包时,有必要考虑该软件包支持的所有软件包集。
- 需要协调软件包提取和垃圾回收。可升级软件包集和自动软件包集都意味着,系统会在系统更新过程之外获取新的软件包版本。只有在有足够的 Blob 存储空间时,这些操作才能成功。在某些情况下,可能需要延迟或取消这些操作,因为空间不足;在其他情况下,可能需要逐出其他软件包,才能使操作成功。
- 软件包解析器与软件包集之间的关系将发生变化。 目前,基本软件包解析器和 Universe 软件包解析器与同名软件包集之间存在松散的相关性,但这种相关性并不完全准确,有时一个解析器会用于解析目标为另一个软件包集的软件包。这种相关性无法扩展到具有更复杂关系的大量软件包集,并且我们不会为本 RFC 中讨论的新软件包集添加额外的软件包解析器。未来,软件包解析器的选择和命名将成为软件交付堆栈的实现细节,从而使我们能够将与确定软件包版本相关的工作与确保软件包可用性相关的工作分离开来。
- 可执行性强制执行机制可能需要更改。目前,只有基本软件包的内容可在正式版中执行;这意味着,简单的可执行性控制机制就足够了。未来,每个软件包集中的软件包(以及它们引用的子软件包)的内容可能需要可执行。这可能需要更复杂的强制执行机制。
实现
此 RFC 的初始实现将主要涉及下文更详细介绍的文档更改。此 RFC 不会更改使用最频繁的软件包集(即 base、bootfs 和 cache)的名称。我们会根据情况,在源代码和工具中将“universe”的引用更新为“discoverable”。如果已弃用的源代码和工具使用“universe”一词,我们一般不会更新这些引用。
建议的更改 4、5 和 6 需要后续 RFC,这些 RFC 将记录所引入更改的实现。
性能
从长远来看,此 RFC 将减小基本软件包集的大小,目前位于基本软件包集中的某些软件包将移至资源要求较低的新软件包集中。从长远来看,这将改善多项性能指标,尤其是磁盘和网络利用率。
如果产品选择将软件包从具有永久可用性的软件包集移至具有自动或按需可用性的软件包集,则解析软件包的延迟时间可能会增加。
安全注意事项
我们认为,此 RFC 的净安全影响是积极的:
- 此 RFC 正式定义了可升级的软件包集。可升级的软件包集可让产品更轻松地更新某些软件包,以修补安全漏洞
- 此 RFC 明确了软件包之间的关系,从而更轻松地推断软件交付行为。从长远来看,这可能会提高安全性,但很难量化这种改进。
- 拟议变更 3 中放宽了对子软件包使用的限制,这需要安全团队进行分析。
隐私注意事项
我们认为此 RFC 对隐私权的净影响为中性:
- 此 RFC 将使定义在用户执行某些操作之前不会下载的软件包变得更加容易,从而更轻松地将网络流量与用户行为相关联
- 此 RFC 将使产品能够更轻松地更新产品软件版本,从而更轻松地修补隐私漏洞
- 受此 RFC 影响的软件交付组件不会直接处理用户数据
测试
提议的更改 4、5 和 6 需要后续 RFC,这些 RFC 将记录所引入更改的测试。
文档
接受此 RFC 后,我们将:
- 为“软件包集”“基本软件包”以及每个版本控制和可用性类别添加了词汇表条目。
- 更新了软件包的术语表条目
- 更新了概念中的软件包部分
- 更新了 IDK 中的软件包页面
- 更新入门指南中有关产品软件包的页面
缺点、替代方案和未知因素
缺点 1 - 名称变更
此 RFC 引入了对全能软件包和急切更新的软件包的命名方式的更改。任何命名更改都会给开发者带来一些困惑,但这些术语之前并未被许多开发者使用,而且使用方式也不一致。我们认为,名称更改带来的困惑与逻辑自洽的名称带来的长期可用性相比,前者微不足道。
替代方案 1 - 允许有保证的软件包和/或可自动发现的软件包
上方的建议的更改部分将设计空间的右下部分标记为“不适用”。我们不支持此组合的原因是,我们认为它不合逻辑:为了保证软件包或自动加载软件包,产品版本必须明确指定软件包,此时软件包符合纳入可升级软件包集的条件。