ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

rkt rm 命令详解:按 UUID 精确删除 Pod 并立即释放全部资源

rkt rm 命令详解:按 UUID 精确删除 Pod 并立即释放全部资源 容器运行时云原生网络【免费下载链接】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 rm是 rkt 容器引擎提供的 Pod 清理命令用于按 UUID 精确删除指定的已退出 Pod并立即清理其关联的所有文件、网络对象与挂载资源无需像rkt gc那样等待垃圾回收周期。本文将以 Documentation/subcommands/rm.md 为骨架结合 rkt/rm.go、rkt/gc.go、pkg/pod/pods.go 等源码实现讲解rkt rm的完整用法、UUID 解析机制、Pod 状态机与底层删除流程帮助你掌握即时回收、精准定位、按名删除的 Pod 生命周期管理实战能力。一、命令定位与rkt gc的异同1.1 文档中的定义官方文档明确说明rkt rm会清理与 Pod 关联的所有资源文件、网络对象效果与rkt gc一致但区别在于rkt gc面向全体不再使用的 Pod按宽限期grace period批量回收适合通过 timer 或 cron 定期执行rkt rm面向指定的 Pod可立即释放资源无需等待垃圾回收调度适合运维中精确回收单个 Pod。从源码来看rkt rm的子命令定义进一步印证了这一点rkt/rm.gocmdRm cobra.Command{ Use: rm --uuid-fileFILE | UUID ..., Short: Remove all files and resources associated with an exited pod, Long: Unlike gc, rm allows users to remove specific pods., Run: ensureSuperuser(runWrapper(runRm)), }注意Run字段中的ensureSuperuser(...)包装器rkt rm与rkt gc一样必须由 root 用户执行这是因为它需要操作/var/lib/rkt数据目录、卸载挂载点并删除文件。1.2 二者共享的底层删除函数虽然命令入口不同但真正执行资源清理的deletePod函数是二者共用的定义在 rkt/gc.go。rkt rm在完成 Pod 状态迁移后调用它rkt gc在宽限期结束后也调用它从而保证两条清理路径的最终行为一致。二、基本用法2.1 按 UUID 删除单个 Podrkt rm c138310frkt rm接收的参数是 Pod 的UUID 前缀而非完整 UUID。rkt在解析时会将该前缀与所有 Pod 的完整 UUID 做前缀匹配大小写不敏感统一转小写如果匹配到唯一一个 Pod则删除成功如果匹配到零个Pod报错no matches found for uuid如果匹配到多个Pod报错ambiguous uuid, N matches要求输入更长的前缀。这一解析逻辑实现在 pkg/pod/uuid.go 的matchUUID/resolveUUID函数中func matchUUID(dataDir, uuid string) ([]string, error) { // 遍历所有 Pod 目录对每个 uuid 判断 strings.HasPrefix(p, uuid) ... } func resolveUUID(dataDir, uuid string) (*types.UUID, error) { uuid strings.ToLower(uuid) ... if len(m) 0 { return nil, fmt.Errorf(no matches found for %q, uuid) } if len(m) 1 { return nil, fmt.Errorf(ambiguous uuid, %d matches, len(m)) } ... }rkt rm主流程rkt/rm.go先通过pkgPod.PodFromUUIDString将 UUID 字符串解析为 Pod 对象随后进入状态检查与删除逻辑删除成功后会在标准输出打印完整的 UUIDif removePod(p) { stdout.Printf(%q, p.UUID) }提示可以一次传入多个 UUID 前缀rkt rm会逐个处理例如rkt rm c138310f 2f8a4b。2.2 从文件读取 UUID除了在命令行直接传 UUIDrkt rm还支持通过--uuid-fileFILE从文本文件中读取 UUIDrkt rm --uuid-file/run/rkt-uuids/mypod对应源码rkt/rm.gocmdRm.Flags().StringVar(flagUUIDFile, uuid-file, , read pod UUID from file instead of argument)读取逻辑在 pkg/pod/uuid.go// ReadUUIDFromFile reads the uuid string from the given path. func ReadUUIDFromFile(path string) (string, error) { uuid, err : ioutil.ReadFile(path) if err ! nil { return , err } return string(bytes.TrimSpace(uuid)), nil }文件内容会被自动TrimSpace因此文件中允许存在结尾换行符读取成功后同样进入前缀匹配流程。2.3 参数互斥规则源码中的switch分支明确规定了两种参数形态不可混用rkt/rm.go情形行为无位置参数 且--uuid-file非空从文件读取 UUID有位置参数 且--uuid-file为空使用命令行参数作为 UUID 列表其他组合如同时提供二者打印 usage 并以退出码 254 结束switch { case len(args) 0 flagUUIDFile ! : // 从文件读取 case len(args) 0 flagUUIDFile : podUUIDs args default: cmd.Usage() return 254 }因此rkt rm --uuid-file/path filearg这种用法是不合法的。三、按名称删除 Pod--uuid-file-save与--uuid-file的配合文档给出了一个非常实用的工作流rkt rm的--uuid-file可与rkt run的--uuid-file-save配合实现按名称删除 Podrkt run --uuid-file-save/run/rkt-uuids/mypod ... rkt rm --uuid-file/run/rkt-uuids/mypod3.1 写入侧--uuid-file-save--uuid-file-save由rkt run提供rkt/run.gocmdRun.Flags().StringVar(flagUUIDFileSave, uuid-file-save, , write out pod UUID to specified file)在rkt run启动流程中Pod 创建后会尽早写入 UUID 文件源码注释甚至点明了与rkt rm配合的意图rkt/run.go// if requested, write out pod UUID early so rkt rm can // clean it up even if something goes wrong if flagUUIDFileSave ! { if err : pkgPod.WriteUUIDToFile(p.UUID, flagUUIDFileSave); err ! nil { ... } }尽早写入意味着即使 Pod 后续启动失败或异常退出rkt rm依然能通过该文件找到并清理它。写入实现同样位于 pkg/pod/uuid.gofunc WriteUUIDToFile(uuid *types.UUID, path string) error { return ioutil.WriteFile(path, []byte(uuid.String()), 0644) }此外rkt app sandboxrkt app sandbox --uuid-file-save...同样支持该参数见 rkt/app_sandbox.go方便对沙箱 Pod 做同样的按名管理。3.2 读取侧--uuid-filerkt rm侧读取该文件如 2.2 节所述文件内容即为 Pod 完整 UUID。整体流程可概括为启动时rkt run --uuid-file-save/run/rkt-uuids/mypod → 把 UUID 落盘 回收时rkt rm --uuid-file/run/rkt-uuids/mypod → 从文件取 UUID 并删除这种模式特别适合脚本化运维不再需要解析rkt list的输出也不需要记忆或拼接长 UUID。四、删除前的状态检查Pod 生命周期状态机rkt rm并不是无脑删除它会先检查目标 Pod 当前所处的生命周期状态只有处于合法终态才会真正清理。完整的 Pod 状态在 pkg/pod/pods.go 中定义状态常量说明embryoEmbryo刚创建、尚未进入准备阶段preparingPreparing正在准备处于 prepare 目录且持有锁aborted prepareAbortedPrepare准备失败、未完成preparedPrepared准备完成、尚未运行runningRunning正在运行deletingDeleting正在被删除垃圾目录中持锁exited deletingExitedDeleting已退出且正在被删除exitedExited已退出exited garbageExitedGarbage已退出且被标记为垃圾garbageGarbage从未运行但被标记为垃圾这些状态与数据目录下的物理目录一一对应pkg/pod/pods.go/var/lib/rkt/pods/ ├── embryo/ # Embryo ├── prepare/ # Preparing / AbortedPrepare ├── prepared/ # Prepared ├── run/ # Running / Exited ├── exited-garbage/ # ExitedGarbage / ExitedDeleting └── garbage/ # Garbage / Deletingrkt rm的状态检查逻辑位于 rkt/rm.go 的removePod函数func removePod(p *pkgPod.Pod) bool { switch p.State() { case pkgPod.Running: stderr.Printf(pod %q is currently running, p.UUID) return false case pkgPod.Embryo, pkgPod.Preparing: stderr.Printf(pod %q is currently being prepared, p.UUID) return false case pkgPod.Deleting: stderr.Printf(pod %q is currently being deleted, p.UUID) return false case pkgPod.AbortedPrepare: // 迁移到 garbage p.ToGarbage() case pkgPod.Prepared: // 迁移到 garbage p.ToGarbage() case pkgPod.ExitedGarbage, pkgPod.Garbage: // 已经是垃圾无需迁移 case pkgPod.Exited: // 迁移到 exited-garbage p.ToExitedGarbage() } ... return deletePod(p) }总结各状态的处理策略拒绝删除running正在运行、embryo/preparing正在准备、deleting已被其他进程删除中。这些都是活动或进行中状态强行删除会导致竞争或破坏。先迁移再删除exited运行结束但未标记先调用ToExitedGarbage()迁移到exited-garbage目录aborted prepare准备失败和prepared已准备未运行先调用ToGarbage()迁移到garbage目录。直接删除已经是exited garbage或garbage状态无需迁移直接进入删除流程。状态迁移函数ToExitedGarbage、ToGarbage通过目录os.Rename实现并在迁移后对父目录做fsync保证持久性见 pkg/pod/pods.go。迁移完成后rkt rm会获取 Pod 的排他锁ExclusiveLock防止与并发清理操作竞争随后才执行最终删除。五、底层删除流程deletePod 究竟清理了什么deletePodrkt/gc.go是最终执行清理的函数它对 Pod 的清理可分为三个阶段5.1 前置校验与锁func deletePod(p *pkgPod.Pod) bool { podState : p.State() if podState ! pkgPod.ExitedGarbage podState ! pkgPod.Garbage podState ! pkgPod.ExitedDeleting { stderr.Errorf(non-garbage pod %q (status %q), skipped, p.UUID, p.State()) return false } ... }调用方必须已持有排他锁且 Pod 必须处于exited garbage、garbage或exited deleting状态否则直接拒绝。这正是rkt rm在removePod中先完成状态迁移的原因。5.2 stage1 与挂载点清理对于exited garbage状态的 Pod即运行过、有 stage1 环境的 PoddeletePod会打开镜像存储imagestore.NewStore与树存储treestore.NewStore必要时重挂载 stage1 overlaymountPodStage1以在宿主重启等场景下恢复可访问性调用stage0.GC执行 stage1 内部的垃圾回收清理 systemd 单元、app 运行残留等调用stage0.MountGC卸载 Pod 遗留的所有挂载点overlay 上下层、临时挂载等。对应代码rkt/gc.goif podState pkgPod.ExitedGarbage { // 打开 store 与 treestore ... // stage1 GC stage0.GC(p.Path(), p.UUID, globalFlags.LocalConfigDir) // 卸载所有遗留挂载 stage0.MountGC(p.Path(), p.UUID.String()) }注意这一步只对exited garbage执行——garbage状态的 Pod 从未真正运行过没有 stage1 环境因此跳过。5.3 文件系统清理挂载与 stage1 清理完成后deletePod依次删除rootfsp.Stage1RootfsPath()指向stage1/rootfsoverlay 模式下为overlay/treeStoreID/upper/Pod 目录整体os.RemoveAll(p.Path())。// remove the rootfs first; if this fails (eg. due to busy mountpoints), pod manifest // is left in place and clean-up can be re-tried later. rootfsPath, err : p.Stage1RootfsPath() if err nil { if e : os.RemoveAll(rootfsPath); e ! nil { ... } } // finally remove all remaining pieces if err : os.RemoveAll(p.Path()); err ! nil { ... }源码注释指出先删 rootfs、后删 Pod 目录是刻意设计的——若 rootfs 因挂载点繁忙删除失败Pod manifestpod文件会保留在原位后续可以重试清理。从源码结构看网络资源netinfo中记录的 network/IP/iface 信息随 Pod 目录的删除而一并移除Pod 锁与目录结构均在pods/下删除后对应条目即从rkt list中消失。六、全局选项rkt rm本身只有--uuid-file一个专属 flag其余为适用于所有rkt命令的全局选项。完整表格见全局选项文档这里列出与rm相关的几个要点Flag默认值说明--debugfalse输出更多调试信息到stderr开启后删除流程会输出更详细的中间过程--dir/var/lib/rktrkt 数据目录Pod 状态目录即位于其下pods/子目录直接决定rm到哪个目录树中查找 UUID--local-config/etc/rkt本地配置目录--system-config/usr/lib/rkt系统配置目录--insecure-options无逗号分隔的需关闭的安全特性列表rm主要受paths等影响# 示例指定自定义数据目录并删除 Pod rkt --dir/data/rkt rm c138310f全局选项在删除流程中主要影响两个环节--dir决定PodFromUUIDString(getDataDir(), ...)的查找范围--debug会在deletePod的 stage1 GC 阶段触发stage0.InitDebug()见 rkt/gc.go。七、实战工作流与验证7.1 完整生命周期演练# 1. 启动 Pod 并将 UUID 保存到命名文件 $ sudo rkt run --uuid-file-save/run/rkt-uuids/mypod \ --insecure-optionsimage coreos.com/etcd:v2.3.4 # 2. Pod 退出后查看状态 $ rkt list UUID APP IMAGE NAME STATE c138310f-... etcd coreos.com/etcd:v2.3.4 exited # 3. 按名删除 $ sudo rkt rm --uuid-file/run/rkt-uuids/mypod c138310f-2f8a-... # 4. 验证已消失 $ rkt list7.2 清理失败场景的表现当传入不存在的 UUID 时输出no matches found for 0f746094-3438-42bc-ab37-3cf85f132e60当删除正在运行的 Pod 时rkt rm会拒绝并提示pod uuid is currently running退出码非 0若一次删除多个 Pod 中部分失败最后会统一输出failed to remove one or more pods。7.3 测试用例佐证仓库中的功能测试直接覆盖了上述行为可作为行为规范参考tests/rkt_rm_test.goTestRm分别构造已运行结束preparerun-prepared与仅 prepared 未运行两类 Pod执行rkt rm后断言pods/run、pods/prepared、pods/exited-garbage目录均为空——验证了状态迁移与最终删除的完整性tests/rkt_rm_test.goTestRmInvalid对不存在的 UUID 分别通过位置参数与--uuid-file两种方式传入断言输出no matches found for uuid且命令失败tests/rkt_rm_test.goTestRmEmptyUUID验证空 UUID 报错UUID cannot be empty。八、使用建议与注意事项必须 root 执行rkt rm会操作宿主数据目录、卸载挂载点非特权用户会被ensureSuperuser拦截。只删除终态 Podrunning、preparing、deleting等状态会被拒绝需要停止运行中的 Pod 时先使用rkt stop见 stop 子命令文档。优先使用 UUID 文件多 Pod 自动化管理场景下run --uuid-file-saverm --uuid-file的组合避免了 UUID 前缀匹配的歧义风险也便于按业务名管理。与rkt gc的关系若想批量清理而非逐个指定仍应使用rkt gc --grace-period0s立即生效rkt rm是精确打击、rkt gc是定期扫雷二者共享deletePod底层实现见 gc 子命令文档。失败可重试若 rootfs 删除因挂载繁忙失败Pod manifest 会保留rkt rm或rkt gc之后可再次执行清理。相关阅读rkt rm 命令文档本文主题的原始权威文档rkt gc 命令文档与 rm 对应的批量垃圾回收全局选项表rkt list 命令文档查看 Pod 状态与 UUIDrkt stop 命令文档停止运行中的 PodPod 生命周期设计文档Pod 状态机与目录布局的完整说明核心实现rkt/rm.go、rkt/gc.go、pkg/pod/pods.go、pkg/pod/uuid.go功能测试tests/rkt_rm_test.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点击查看免费下载相关推荐filebrowser users rm 命令完全指南按用户名或 ID 删除用户filebrowser users rm 命令完全指南按用户名或 ID 删除用户 File Browser 的 CLI 为用户管理提供了完整的子命令集其中后端前端Velero 资源删除命令完全指南ark delete 命令详解Velero 资源删除命令完全指南ark delete 命令详解 本指南以 ArkVelero 前身v0.9.0 CLI 参考文档中的 ark delet云原生灾备存储后端git-bug bridge rm 命令详解删除已配置的桥接器Bridgegit bug bridge rm 命令详解删除已配置的桥接器Bridge git bug bridge rm 是 git bug 项目中用于删除已配置桥开发工具研发协作上一篇终极指南FastAPI数据序列化中的CamelCase与SnakeCase转换下一篇如何利用Marquez解决数据治理难题7个真实场景案例分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表