- 容器运行时
- 云原生
- 网络
【免费下载链接】rkt
[Project ended] rkt is a pod-native container engine for Linux. It is composable, secure, and built on standards.
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 在镜像处理上的关键差异
原提案给出了一张对比表,概括两种格式在镜像处理层面的核心区别:
| 方面 | OCI | ACI |
|---|---|---|
| 依赖 | 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):DATAcimd:容器镜像分发 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 分发点
原提案给出了当前支持的三种分发点:
| 名称 | 示例 |
|---|---|
| appc | cimd:appc:v=0:coreos.com/etcd?version=v3.0.3&os=linux&arch=amd64 |
| ACIArchive | cimd:aci-archive:v=0:file%3A%2F%2Fabsolute%2Fpath%2Fto%2Ffile |
| Docker | cimd: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.
相关推荐
如何在DeepForge中创建自定义操作?零基础开发者的完整指南
如何在DeepForge中创建自定义操作?零基础开发者的完整指南 DeepForge是一个现代化的深度学习开发环境,允许开发者创建、管理和执行复杂的机器学习工作
OCI镜像转换指南:将现有镜像迁移到OCI标准格式
OCI镜像转换指南:将现有镜像迁移到OCI标准格式 OCI镜像格式作为容器技术的行业标准,为容器镜像提供了统一、可互操作的规范。本指南将详细介绍如何将现有镜像迁
云原生存储OCI镜像格式与Docker镜像的10个关键差异对比
OCI镜像格式与Docker镜像的10个关键差异对比 想要理解容器技术的演进历程?OCI镜像格式作为开放容器倡议的标准规范,与传统的Docker镜像有着本质的区
云原生存储
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考