☰
rkt 原生支持 OCI 镜像格式的路线图:从 ACI 到多格式镜像分发架构的演进
2026/9/25 3:44:32 网站建设 项目流程
  • 容器运行时
  • 云原生
  • 网络

【免费下载链接】rkt

[Project ended] rkt is a pod-native container engine for Linux. It is composable, secure, and built on standards.

项目地址:https://gitcode.com/gh_mirrors/rk/rkt
点击查看免费下载

rkt 的镜像处理历来以 appc 规范下的 ACI(Application Container Image)为核心,本提案系统梳理了 rkt 内部三个镜像子系统(fetching、image store、tree store)的现状,并规划了在不移除 ACI 支持的前提下,通过 CIMD 分发点、基于引用的镜像存储、传输处理器与 tree store OCI 适配四个步骤逐步实现 OCI 镜像原生支持的技术路线。阅读本文后,你将理解 rkt 的镜像格式转换链路、CIMD URI 的完整语法与各分发点实现、镜像存储对 SHA-512 的依赖及其改造方向,以及该路线图背后的兼容性风险。

背景:rkt 与 ACI/OCI 两种镜像规范

rkt 当前实现的是 appc 规范,因此内部依赖 ACI(Application Container Image)这一镜像格式。而 OCI(Open Container Initiative) 定义了一套独立规范下的全新镜像格式,它与 rkt 内部基于 ACI 的镜像处理方式差异显著——OCI 镜像以 manifest 中的 layers 数组表达依赖,而 ACI 依赖图则由 appc 规范的依赖关系决定。

从仓库源码可以确认,rkt 的镜像处理链路确实被划分成三个独立子系统:

  • fetching(拉取):负责下载各种类型的镜像。非 ACI 镜像(Docker、OCI)通过委托 docker2aci 中的docker2aci.ConvertRemoteRepo(registryURL, config)调用,这是当前所有 Docker/OCI 镜像进入 rkt 的唯一转换入口。
  • image store(镜像存储):负责持久化和管理已下载的镜像,由两部分组成:存储镜像文件 blob 的目录树(通常位于/var/lib/rkt/cas/blob),以及存储镜像元数据的嵌入式 SQL 数据库(通常位于/var/lib/rkt/cas/db/ql.db)。实现位于github.com/rkt/rkt/store/imagestore包。在 store/imagestore/store.go 中可以看到blob与imageManifest两个 diskv 存储区,以及sha512-前缀的 key 生成逻辑。
  • tree store(树存储):由于 ACI 镜像之间的依赖关系按照 appc 规范形成一个有向无环图(DAG),这些镜像会被预渲染到名为 tree store 缓存的目录中。若启用了 overlay 文件系统,预渲染结果将作为 pod 根文件系统的lowerdir使用。实现位于github.com/rkt/rkt/store/treestore包,源码可见 store/treestore/tree.go 中的Store结构体通过acirenderer依赖图渲染 ACI 镜像树。

rkt 内部镜像的完整生命周期记录在 架构文档 的 image lifecycle 章节中。

OCI 与 appc 在镜像处理上的关键差异

原提案给出了一张对比表,概括两种格式在镜像处理层面的核心区别:

方面OCIACI
依赖image manifest 中的 layers 数组基于 appc 规范的依赖图(DAG)
哈希算法可能支持多种算法(SHA-256 为首选)固定使用 SHA-512

正是这两点差异,直接决定了后续路线图中镜像存储改造(哈希算法扩展)与 tree store 适配(依赖渲染方式)的必要性。

目标与非目标:原生支持 OCI,保留 ACI

随着 appc 规范的弃用,rkt 现有内部架构不再占优。当前 rkt 已能支持 ACI、Docker、OCI 三类镜像,但通过docker2aci将 OCI 转换为 ACI 的这一步显得多余:它引入了 CPU 和 I/O 开销,且受限于两种格式之间的语义差异。因此本提案的目标是在 rkt 内部原生支持 OCI 镜像,与 ACI 并列共存;rkt 会继续支持 ACI 镜像格式及其分发机制,目前没有移除该支持的计划。

非目标是 OCI 运行时规范(runtime-spec)的实现——即在 rkt 内部直接运行 OCI 容器,这一话题由独立工作项跟踪。

为实现原生 OCI 支持,提案明确了四个必要步骤,下文逐一展开。

第一步:分发点(Distribution Points)——CIMD 统一镜像定位语法

rkt 历史上依靠镜像名称及围绕名称的启发式规则来判断镜像格式类型(appc、Docker、OCI)。"分发点"(distribution point)概念引入了一种 URI 语法,能够唯一指向不同镜像格式,并携带必要的元数据(文件位置、来源 URL、版本等)。

CIMD URI 语法

分发点选择了cimd(Container Image Distribution,容器镜像分发)作为 URI scheme。其通用形式为:

cimd:DISTTYPE:v=uint32(VERSION):DATA
  • cimd:容器镜像分发 scheme;
  • DISTTYPE:分发类型;
  • v=VERSION:分发类型格式的版本号(uint32);
  • DATA:具体的分发数据(opaque 部分与 query 参数)。

在源码层面,pkg/distribution/cimd.go 的parseCIMD用strings.SplitN(u.Opaque, ":", 3)将 opaque 数据切分为类型、版本和数据三段,并校验 scheme 必须为cimd;NewCIMDString则负责拼装cimd:Type:v=Version:Data形式的字符串。

rkt 当前支持的三种 CIMD 分发点

原提案给出了当前支持的三种分发点:

名称示例
appccimd:appc:v=0:coreos.com/etcd?version=v3.0.3&os=linux&arch=amd64
ACIArchivecimd:aci-archive:v=0:file%3A%2F%2Fabsolute%2Fpath%2Fto%2Ffile
Dockercimd:docker:v=0:busybox

appc 分发点(间接分发点)使用 appc 镜像发现机制,格式为cimd:appc:v=0:name?label01=....&label02=....,label 值必须经过 Query 转义。实现见 pkg/distribution/appc.go,其中NewAppc将 CIMD 数据与 query 参数重新拼接成 appc 发现字符串,交给discovery.NewAppFromString解析;NewAppcFromApp反向构造时会对 URI 进行 query 排序归一化(purell.FlagSortQuery),使同一镜像的不同书写形式可以稳定比较。

ACIArchive 分发点(直接分发点)直接定义镜像的最终位置,格式为cimd:aci-archive:v=0:ArchiveURL?query...,ArchiveURL 必须 Query 转义,例如cimd:aci-archive:v=0:file%3A%2F%2Fabsolute%2Fpath%2Fto%2Ffile与cimd:aci-archive:v=0:https%3A%2F%2Fexample.com%2Fapp.aci。实现见 pkg/distribution/aciarchive.go:NewACIArchive对数据段做url.QueryUnescape后得到真正的传输 URL(transport URL),可通过TransportURL()取出供底层传输层使用。

Docker 分发点(间接分发点)使用 Docker registry,其格式cimd:docker:v=0:[REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG|@DIGEST]与docker pull的镜像字符串格式一致。实现见 pkg/distribution/docker.go:NewDocker委托 docker2aci 的ParseDockerURL解析镜像引用,并维护simple(用户友好简写)与full(补全默认值的完整引用)两种表示。值得注意的默认值逻辑(见SimpleDockerRef/FullDockerRef):当使用默认 registry(registry-1.docker.io)时会省略 registry 前缀与library/仓库前缀,tag 默认latest。

分发点的注册与解析机制

pkg/distribution/distribution.go 定义了Distribution接口,包含三个方法:CIMD()返回 CIMD URI 副本、String()返回用户友好表示、Equals()比较两个分发点是否等价。各分发点类型通过init()中的Register()注册到全局表;Parse()/Get()负责从字符串或 URL 解析分发点,遇到未知类型或畸形 URI 会返回错误。这一"注册-解析"机制是后续扩展cimd:oci的基础——新增分发点只需实现接口并注册。

未来的 OCI 分发点

原提案的 TODO 明确列出:引入专用的远端cimd:oci分发点,以及潜在的本地cimd:oci-layout分发点(对应 OCI image-layout 规范)。在配套设计文档 Documentation/devel/distribution-point.md 中对这两个未来分发点做了更详细的规划:

  • OCI 镜像分发(间接):OCI 镜像当前可从 Docker registry 获取,未来 OCI 规范会定义从镜像名(含 tag/label)出发的自有分发方式;
  • OCI 镜像布局(直接):可从 OCI image layout 拉取镜像,location 可指向单个文件归档、本地目录布局或远端目录布局,示例格式如cimd:oci-image-layout:v=0:file%3A%2F%2Fabsolute%2Fpath%2Fto%2Ffile?ref=refname;由于一个布局可含多个镜像(通过 ref 选择),而分发点只对应单个镜像,故每个分发 URI 必须显式携带ref参数。

cimd:oci预计会是cimd:oci-image-layout的上层间接分发点,类似 appc 之于 ACIArchive 的关系。

用户友好字符串与向后兼容

CIMD URI 较长且复杂,为便于用户在 CLI 中使用,rkt 将输入镜像字符串映射为分发点 URI,以维持旧的 ImageType 启发式判别的向后兼容(详见 Documentation/devel/distribution-point.md 中的映射表):appc 发现字符串、文件路径、file URL、http(s) URL、docker URI/URL 分别映射到对应 CIMD 分发点。解析与生成用户友好字符串的工作被放在 distribution 包之外,使包的使用者能自行实现自己的友好字符串格式。

第二步:基于引用的镜像处理(Reference Based Image Handling)

现有 image store 实现不支持多种镜像格式:blob 镜像存储仅支持 SHA-512,ql 支撑的 SQL 镜像存储 schema 也仅引用 ACI 镜像。为准备 OCI 原生支持,需要以下改动:

  • 将 CIMD URI 作为当前镜像存储的主键;
  • 支持多种哈希算法:当前仅支持 SHA-512,OCI 额外需要 SHA-256 及潜在的其他算法;
  • 重做数据库 schema以反映多镜像支持。

这些判断与源码现状完全吻合。在 store/imagestore/store.go 中可见hashPrefix = "sha512-"、lenHash = sha512.Size等常量,blob 的 key 由 SHA-512 哈希生成;WriteACI写入时使用sha512.New()作为哈希器。而 store/imagestore/schema.go 中remote表以aciurl为主键、aciinfo表以blobkey为主键并带name/importtime/lastused/latest等字段,全部围绕 ACI 语义建模,且dbVersion当前为 7,schema 的每次演进都依赖迁移语句和数据库备份机制(backupDB保留 5 份备份)。这解释了提案中"不只是简单的 schema 变更,而是侵入式 schema 与目录布局变更"的风险判断。

配套设计文档同时建议引入一个新的基于 Bolt 的 key/value 存储;但当前共识是,ql的替换可独立进行,因此应作为 OCI 路线图的非目标。

第三步:传输处理器(Transport Handlers)

目前 rkt 直接拉取远端 ACI 镜像,或使用docker2aci代理非 ACI 镜像的拉取。由于缺少抽象层,现有实现很难集成独立的拉取子系统。

本步骤的提议是:将拉取逻辑抽象为"传输处理器"(transport handlers),为各种镜像格式提供独立(且可替换)的拉取实现。这既是分发点设计文档中"分发点与传输层分离"思路的自然延伸(例如 ACIArchive 分发点可调用 file、http、s3、bittorrent 等多种传输插件),也为引入github.com/containers/image这类第三方库委托 OCI/Docker 拉取提供了抽象边界。

当前状态:

  • 设计文档与初版实现均已提出但处于非常早期阶段,仅应作为启发参考;
  • TODO:必须支持所有格式的远端拉取与本地磁盘拉取;需确定最终设计;需抽象现有 fetcher 逻辑以引入替代库。

第四步:tree store 对 OCI 的支持

现有 tree store 实现仅用于渲染 ACI 镜像。要支持 OCI,需要新的设计文档与初始实现,以原型化"解压 OCI 镜像及其依赖"的流程。其难点在于 OCI 的依赖表达(layers 数组)与 ACI 的依赖图(DAG)不同,渲染策略需重新设计——包括 overlay 文件系统下如何将 OCI 图层组装成 pod 根文件系统的lowerdir。此项工作的状态为:尚未开始。

风险分析:向后兼容与回滚能力

提案明确指出的最大顾虑是向后兼容性与回滚能力。上述改动不只是 ql 数据库的简单 schema 变更,而是侵入式的 schema 和目录布局变更。结合源码可见,image store 的迁移流程(store/imagestore/store.go)在检测到旧版本数据库时会先获取独占锁、备份数据库再执行迁移,且非 root 用户执行迁移会被拒绝(ErrDBUpdateNeedsRoot)。任何新格式的引入都会沿着这条既有迁移路径放大风险:一旦新版本写入新布局,旧版本 rkt 将无法正确解读,回滚需要额外的备份恢复机制。因此,兼容性策略(包括cimd:oci分发点的引入节奏、schema 迁移的多版本共存能力)是本路线图落地前必须解决的首要问题。

总结

本路线图描绘了 rkt 从"单一 ACI 内部格式 + docker2aci 转换桥"走向"多格式原生并存"的清晰路径:以 CIMD 分发点统一镜像定位与引用(第一步),以引用化存储承载多哈希算法与多格式元数据(第二步),以传输处理器解耦各格式的拉取实现(第三步),以 tree store 适配覆盖 OCI 图层的根文件系统渲染(第四步)。每一环节都保留了 ACI 的完整支持与向后兼容边界,而 OCI 运行时执行本身则被明确排除在范围之外。对于想要深入 rkt 镜像子系统的读者,建议从 Documentation/devel/distribution-point.md(分发点设计)、store/imagestore/store.go 与 store/imagestore/schema.go(存储现状)、store/treestore/tree.go(树渲染)以及 rkt/image/dockerfetcher.go(当前转换链)入手。

  • 容器运行时
  • 云原生
  • 网络

【免费下载链接】rkt

[Project ended] rkt is a pod-native container engine for Linux. It is composable, secure, and built on standards.

项目地址:https://gitcode.com/gh_mirrors/rk/rkt
点击查看免费下载

相关推荐

上一篇:vscode-web-visual-editor 设置项完全指南:HTML可视化编辑器4个配置深度解读与最佳实践
下一篇:headlines.nvim 插件架构解析:代码实现细节揭秘

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询