
容器运行时云原生网络【免费下载链接】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点击查看免费下载rktexport子命令负责把一个已经退出exited的单应用 Pod的根文件系统连同其 Image Manifest 重新打包成一个标准的 App Container Image.aci文件从而实现「容器运行态 → 可分发镜像」的逆向转化。本文以 Documentation/subcommands/export.md 为骨架结合 rkt/export.go、pkg/pod/pods.go 等源码实现系统讲解rkt export的调用方式、前置条件、应用选择规则、--overwrite行为以及底层 OverlayFS 挂载与 ACI 打包原理帮助你理解并正确使用这一镜像导出能力。命令概览与基本用法rkt export的用法非常简洁命令形式为rkt export UUID OUTPUT_ACI_FILE其中UUID是已退出 Pod的 UUID支持前缀匹配见后文OUTPUT_ACI_FILE是要写入的.aci文件路径。最简单的调用示例如下$ rkt export UUID .aci即指定 Pod 的 UUID 与输出 ACI 文件名rkt 就会把该 Pod 中应用的根文件系统与清单打包为 ACI。从 rkt/export.go 的 cobra 命令定义可以看到其完整形式export [--appAPPNAME] UUID OUTPUT_ACI_FILE--app用于在包含多个应用的 Pod 中指定要导出的应用默认行为见「应用选择逻辑」一节。命令的入口逻辑位于 rkt/export.go 的runExport函数它首先校验参数个数必须是两个然后校验输出文件扩展名解析 Pod UUID检查 Pod 状态选择应用最后根据 Pod 是否使用 OverlayFS 走不同的文件收集路径并调用buildAci完成打包。前置条件只能导出已退出的 Podrkt export只接受已退出的 Pod。源码中rkt 通过 Pod 在数据目录中的位置与锁状态判定其生命周期状态详见 pkg/pod/pods.go 中定义的状态常量如Embryo、Preparing、Prepared、Running、Exited、ExitedGarbage等state : p.State() if state ! pkgPod.Exited state ! pkgPod.ExitedGarbage { stderr.Print(pod is not exited. Only exited pods can be exported) return 254 }也就是说只有状态为exited或exited garbage的 Pod 才能被导出仍处于running、prepared或preparing等状态的 Pod 会被拒绝并打印提示pod is not exited. Only exited pods can be exported。在实际操作中一个常见的「导出工作流」是$ rkt prepare coreos.com/etcd:v2.3.4 # 先准备 Pod $ rkt run-prepared UUID # 运行 Pod $ rkt list # 查看 Pod 状态与 UUID $ rkt export UUID my-app.aci # Pod 退出后导出为 ACIUUID 支持前缀匹配runExport通过pkgPod.PodFromUUIDString解析 UUID见 rkt/export.go。该函数内部会先把传入字符串转为小写再对所有 Pod 目录做前缀匹配见 pkg/pod/uuid.go无匹配报错no matches found for ...多个匹配报错ambiguous uuid, N matches恰好一个匹配返回完整的 UUID。因此你可以像rkt export bc3c export.aci这样使用 UUID 前缀只要前缀是唯一的即可。应用选择逻辑单应用自动选中多应用必须指定--app一个 Pod 中可以包含多个应用App。导出时必须明确「导出哪个应用」。rkt/export.go 中getApp函数实现了三段式选择逻辑若通过--appAPPNAME显式指定了应用名则从 Pod Manifest 的Apps列表中按名字匹配若该名字不存在报错app name is not present in pod若未指定--app且 Pod 中恰好只有一个应用则直接导出该应用若未指定--app而 Pod 中包含多个应用则把所有应用名打印到stderr并要求用户用rkt export --app...明确指定否则报错退出。也就是说单应用 Pod 可以省略--app多应用 Pod 则必须显式指定。应用名来自 Pod Manifest 中runtimeApp的name字段schema.RuntimeApp导出时会据此定位该应用的 rootfs 与清单文件。--overwrite控制是否覆盖已存在的输出文件rkt export唯一专属选项是--overwrite。原文档中的参数表如下FlagDefaultOptionsDescription--overwritefalsetrueorfalseOverwrite the output ACI if it exists该选项默认关闭false。源码层面rkt/export.go 的buildAci在打开输出文件时根据该标志组合文件打开模式mode : os.O_CREATE | os.O_WRONLY if flagOverwriteACI { mode | os.O_TRUNC } else { mode | os.O_EXCL } aciFile, err : os.OpenFile(target, mode, 0644) if err ! nil { if os.IsExist(err) { return errors.New(target file exists (try --overwrite)) } ... }不传--overwrite时使用O_EXCL若目标文件已存在则直接报错target file exists (try --overwrite)传入--overwrite时改用O_TRUNC目标文件会被截断并覆盖写入。因此重复导出到同一路径时要么先删除旧文件要么加上--overwrite标志。输出文件必须使用.aci扩展名runExport会强制校验输出文件扩展名rkt/export.goext : filepath.Ext(outACI) if ext ! schema.ACIExtension { stderr.Printf(extension must be %s (given %s), schema.ACIExtension, outACI) return 254 }schema.ACIExtension来自 appc spec即.aci。如果输出文件名不是.aci结尾例如export.tar命令会以退出码 254 报错extension must be .aci (given ...)。底层导出流程OverlayFS 与非 Overlay 两条路径rkt export的打包核心是buildAci但在进入打包之前它必须先从已退出的 Pod 中收集到应用的「完整 rootfs 快照」。由于 rkt 支持用 OverlayFS 运行 Pod导出逻辑依据p.UsesOverlay()即 Pod 目录下是否存在overlay-prepared标记文件见 pkg/pod/pods.go 与 common/common.go 的OverlayPreparedFilename分两条路径处理。路径一OverlayFS Pod —— 重新挂载合并视图当 Pod 使用 OverlayFS 时应用的最终 rootfs 由底层镜像lower与应用运行期写入的上层upper叠加而成。为了导出完整内容runExport会在数据目录下创建临时目录$dataDir/tmp/rkt-export-UUID并在其中建立rootfs子目录rkt/export.go调用mountOverlay把该应用的真实文件系统挂载到这个临时目录上rkt/export.go。mountOverlay通过 imagestore 与 treestore 定位底层从 Pod 的appsinfo/app/treeStoreID文件读取 treestore IDGetAppTreeStoreID以其 rootfs 作为 overlay 的lowerdirupper 层位于 Pod 目录的overlay/treeStoreID/upper/appwork 层位于overlay/treeStoreID/work/app。随后调用 common/overlay/overlay.go 的Mount执行mount(overlay, dest, overlay, 0, opts)系统调用func Mount(cfg *MountCfg) error { err : syscall.Mount(overlay, cfg.Dest, overlay, 0, cfg.Opts()) ... }其中挂载选项由MountCfgLower/Upper/Work/Dest/Lbl构造为lowerdir...,upperdir...,workdir...目录名中的冒号与逗号会被转义以避免被内核当作分隔符sanitize。挂载完成后临时挂载点便呈现出应用在退出时的完整文件系统视图。在runExport中临时挂载点与临时目录通过defer保证在函数返回前被卸载syscall.Unmount和删除os.RemoveAll。这一设计确保导出过程不污染 Pod 数据目录。路径二非 OverlayFS Pod —— 校验无残留挂载点当 Pod 未使用 OverlayFS 时应用的 rootfs 直接存在于磁盘上$poddir/opt/stage2/app/rootfs理论上可以直接打包。但若 Pod 退出后仍残留未清理的挂载点直接打包会得到不完整的文件系统。因此runExport会先用mountinfo.ParseMounts解析宿主挂载表并按应用的 rootfs 路径前缀过滤rkt/export.goappRootfs : common.AppRootfsPath(p.Path(), app.Name) string(filepath.Separator) mnts, err : mountinfo.ParseMounts(0) ... mnts mnts.Filter(mountinfo.HasPrefix(appRootfs)) if len(mnts) 0 { stderr.Printf(pod has remaining mountpoints. Only pods using overlayfs or with no mountpoints can be exported) return 254 }注意 rootfs 路径后追加了路径分隔符目的是避免误匹配到appRootfs前缀相同的其他路径。如果检测到残留挂载点则报错pod has remaining mountpoints. Only pods using overlayfs or with no mountpoints can be exported。换言之要么使用 OverlayFS要么 Pod 中不存在任何残留挂载点二者满足其一即可导出。ACI 打包gzip tar appc ImageWriter无论走哪条路径最终都汇聚到buildAcirkt/export.go其打包流程如下以相应打开模式创建输出.aci文件权限0644依次构造gzip.Writer与tar.Writer即 ACI 实际是 gzip 压缩的 tar 归档从$poddir/appsinfo/app/manifest即common.AppInfoPathaci.ManifestFile读取并解析该应用的 Image Manifestschema.ImageManifest使用 appc 规范提供的aci.NewImageWriter(im, tr)创建镜像写入器通过filepath.Walk(root, aci.BuildWalker(root, iw, walkerCb))递归遍历 rootfs将每个文件以 tar 头写入调用iw.Close()收尾写入 ACI 布局所需的补充条目若中途出错defer 中会关闭所有 writer 并删除目标文件避免留下不完整的 ACI。用户命名空间支持导出时对 uid/gid 反偏移如果 Pod 是以--private-users启动的即使用了用户命名空间Pod 目录下会存在private-users-prepared文件见 common/common.go 的PrivateUsersPreparedFilename。runExport会读取并反序列化其中的shift:count偏移信息rkt/export.go构造*user.UidRangeprivUserFile : filepath.Join(p.Path(), common.PrivateUsersPreparedFilename) privUserContent, err : ioutil.ReadFile(privUserFile) if err nil { uidRange user.NewBlankUidRange() if err : uidRange.Deserialize(privUserContent); err ! nil { ... } }UidRange的定义与序列化/反序列化实现位于 pkg/user/uid_range.go。该结构记录Shift偏移量与Count范围大小启动时由--private-users触发SetRandomUidRange(user.DefaultRangeCount)默认范围0x10000见 rkt/run.go 与 pkg/user/uid_range.go。导出时由于 Pod 内文件的所有者 uid/gid 是「宿主 uid 偏移量」后的值直接打包会得到错误的属主。因此buildAci在写入每个 tar 头时通过uidRange.UnshiftRange(uid, gid)把 uid/gid 减去偏移量还原成镜像内部的原始属主rkt/export.govar walkerCb aci.TarHeaderWalkFunc func(hdr *tar.Header) bool { if uidRange ! nil { uid, gid, err : uidRange.UnshiftRange(uint32(hdr.Uid), uint32(hdr.Gid)) ... hdr.Uid, hdr.Gid int(uid), int(gid) } return true }这样导出的 ACI 在普通命名空间下重新运行时文件属主是正确且一致的。全局选项与 rkt 的所有子命令一样rkt export也接受一组全局选项原文档通过[global-options]链接指向 Documentation/commands.md此处摘录关键项FlagDefaultOptionsDescription--debugfalsetrueorfalse向stderr输出更多调试信息--dir/var/lib/rkt目录路径rkt 数据目录路径--local-config/etc/rkt目录路径本地配置目录路径--system-config/usr/lib/rkt目录路径系统配置目录路径--user-config目录路径用户配置目录路径--insecure-optionsnonenone、http、image、tls、pubkey、capabilities、paths、seccomp、all-fetch、all-run、all逗号分隔的需关闭的安全特性列表--trust-keys-from-httpsfalsetrueorfalse自动信任从 HTTPS或配合pubkey时从 HTTP获取的 GPG 公钥其中--dir与导出关系最为密切它决定了 Pod 数据目录的位置进而决定runExport查找 Pod、创建临时目录以及访问 imagestore/treestore 的根路径。错误处理与退出码rkt export的错误路径统一返回退出码254源码中以return 254表示失败典型失败场景包括参数个数不为 2打印用法并退出输出文件扩展名不是.aciUUID 无法解析、无匹配或存在歧义Pod 尚未退出仍处于 running/prepared 等状态指定的--app不存在或多应用 Pod 未指定--app非 OverlayFS Pod 存在残留挂载点目标 ACI 已存在但未加--overwrite打开、打包或卸载过程中出现文件系统错误。此外清理临时目录或卸载临时挂载点时若发生错误exit会被置为 1作为非致命错误的温和提示。测试验证覆盖六类典型场景仓库中的功能测试为rkt export的行为提供了完整的验证样本。核心测试定义在 tests/rkt_export_test.go 中exportTestCases覆盖了六类场景noOverlaySimpleTest--no-overlay启动导出单应用 Pod 后运行新 ACI 校验文件内容specifiedAppTest使用--apprkt-inspect显式指定应用multiAppPodTest多应用 Pod 中通过--app导出指定应用另一个应用写入不同的文件内容以作区分userNS--private-users --no-overlay启动后导出验证 uid/gid 反偏移逻辑overlaySimpleTestOverlayFS Pod 导出overlaySimulateReboot模拟重启后卸载 overlay 再导出。每个用例的验证流程高度一致用 inspect 镜像的--write-file在 Pod 内写入一个测试文件 → 运行 Pod 使其退出 →rkt export导出 ACI → 用rkt run运行新 ACI 并执行--read-file读取同一文件确认内容一致ThisIsATest→ 最后执行rkt gc与rkt image gc清理。测试按 stage1 风格分流执行常规容器 stage1 在 tests/rkt_export_container_test.go 中遍历全部用例并通过common.SupportsOverlay()、common.SupportsUserNS()探测运行环境能力不满足条件的用例自动跳过fly stage1 则在 tests/rkt_export_fly_test.go 中单独运行overlaySimpleTest。这些测试文件同时是「如何完整走通一次导出并验证产物」的最佳实操范例。与rkt image export的区分rkt export与镜像仓库导出命令rkt image export容易混淆二者针对不同的对象命令对象行为rkt export UUID OUTPUT_ACI_FILE已退出的 Pod把应用在 Pod 中的运行态文件系统含运行时写入重新打包为 ACIrkt image export IMAGE OUTPUT_ACI_FILE本地镜像仓库中的镜像把已存储的原始镜像按镜像 ID 或名字引用直接复制为 ACI不做任何重新打包从实现上看rkt/image_export.go 只是打开 imagestore 并io.Copy原始数据流到输出文件而rkt export需要经过挂载合并、清单读取、tar/gzip 重建等完整流程。如果你需要的是「容器运行后产生的最终状态」请使用rkt export如果只是备份仓库中某个镜像应使用rkt image export。小结rkt export是一个把运行态 Pod 逆向还原为可分发 ACI 镜像的实用工具。使用时需要记住四个关键点只能导出已退出的 Pod、输出文件必须带.aci扩展名、多应用 Pod 必须用--app指定导出目标、目标文件已存在时需要--overwrite。在底层rkt 依据 Pod 是否使用 OverlayFS 分别通过「临时挂载合并视图」或「残留挂载点校验」收集完整 rootfs再借助 appc 规范的 ImageWriter 重建 gziptar 格式的 ACI并针对--private-users启动的 Pod 自动完成 uid/gid 反偏移。相关实现与测试可作为进一步学习 rkt 生命周期、OverlayFS 与 ACI 规范的绝佳切入点。赞分享容器运行时云原生网络【免费下载链接】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点击查看免费下载相关推荐Podman Volume Export 实战指南将命名卷导出为 tar 归档Podman Volume Export 实战指南将命名卷导出为 tar 归档 podman volume export 是 Podman 提供的卷备份与迁移容器运行时云原生CLIuv export将 uv.lock 导出为 requirements.txt、pylock.toml 与 CycloneDX SBOM 的实践指南uv export将 uv.lock 导出为 requirements.txt、pylock.toml 与 CycloneDX SBOM 的实践指南 本文基于包管理器开发工具CLIdirty_sock exploit开发详解如何构造恶意snap包实现root权限获取dirty_sock exploit开发详解如何构造恶意snap包实现root权限获取 dirty_sock是一个针对Linux系统的本地提权漏洞利用工具通容器运行时云原生网络上一篇从T5到Tk-Instruct-small-def-pos解码器模型的革命性进化下一篇为什么选择anton-l/wav2vec2-large-xlsr-53-estonian爱沙尼亚语语音识别工具对比分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考